LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [V2 2/5] powerpc: 40x: Add AHB, APB of_device_ids
From: Tanmay Inamdar @ 2012-04-09  7:20 UTC (permalink / raw)
  To: benh, jwboyer, grant.likely, linuxppc-dev, linux-kernel,
	devicetree-discuss
  Cc: Tanmay Inamdar
In-Reply-To: <1333956052-25319-1-git-send-email-tinamdar@apm.com>

Adding of_device_id's for AHB and APB buses used in klondike (APM8018X) in
platforms/40x/ppc40x_simple.c file

Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
---
:100644 100644 9761206... 7b518ed... M	arch/powerpc/platforms/40x/ppc40x_simple.c
 arch/powerpc/platforms/40x/ppc40x_simple.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c
index 9761206..7b518ed 100644
--- a/arch/powerpc/platforms/40x/ppc40x_simple.c
+++ b/arch/powerpc/platforms/40x/ppc40x_simple.c
@@ -29,6 +29,8 @@ static __initdata struct of_device_id ppc40x_of_bus[] = {
 	{ .compatible = "ibm,plb4", },
 	{ .compatible = "ibm,opb", },
 	{ .compatible = "ibm,ebc", },
+	{ .compatible = "apm,ahb", },
+	{ .compatible = "apm,apb", },
 	{ .compatible = "simple-bus", },
 	{},
 };
-- 
1.6.1.rc3

^ permalink raw reply related

* [V2 3/5] powerpc: dts: klondike: Add UART nodes
From: Tanmay Inamdar @ 2012-04-09  7:20 UTC (permalink / raw)
  To: benh, jwboyer, grant.likely, linuxppc-dev, linux-kernel,
	devicetree-discuss
  Cc: Tanmay Inamdar
In-Reply-To: <1333956052-25319-2-git-send-email-tinamdar@apm.com>

Adding UART nodes in Klondike device tree file.

Version 2:
Removed unnecessary 'virtual-reg' property from UART node.

Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
---
:100644 100644 4ff2852... b1e516e... M	arch/powerpc/boot/dts/klondike.dts
 arch/powerpc/boot/dts/klondike.dts |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/klondike.dts b/arch/powerpc/boot/dts/klondike.dts
index 4ff2852..b1e516e 100644
--- a/arch/powerpc/boot/dts/klondike.dts
+++ b/arch/powerpc/boot/dts/klondike.dts
@@ -222,6 +222,28 @@
 				#size-cells = <1>;
 				ranges;
 				clock-frequency = <0>;
+
+				UART0: serial@50001000 {
+				       device_type = "serial";
+				       compatible = "ns16550";
+				       reg = <0x50001000 0x00000100>;
+				       clock-frequency = <0>; /* Filled in by U-Boot */
+				       current-speed = <115200>;
+				       interrupt-parent = <&UIC0>;
+				       interrupts = <0x0 0x4>;
+				       reg-shift = <2>;
+				};
+
+				UART1: serial@50002000 {
+				       device_type = "serial";
+				       compatible = "ns16550";
+				       reg = <0x50002000 0x00000100>;
+				       clock-frequency = <0>; /* Filled in by U-Boot */
+				       current-speed = <115200>;
+				       interrupt-parent = <&UIC0>;
+				       interrupts = <0x1 0x4>;
+				       reg-shift = <2>;
+			       };
 			};
 		};
 	};
-- 
1.6.1.rc3

^ permalink raw reply related

* [V2 4/5] powerpc: config: 40x: Add 16650 UART support in klondike defconfig
From: Tanmay Inamdar @ 2012-04-09  7:20 UTC (permalink / raw)
  To: benh, jwboyer, grant.likely, linuxppc-dev, linux-kernel,
	devicetree-discuss
  Cc: Tanmay Inamdar
In-Reply-To: <1333956052-25319-3-git-send-email-tinamdar@apm.com>

Adding 16650 UART support in klondike_defconfig for APM8018X SOC

Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
---
:100644 100644 c0d228d... c35c345... M	arch/powerpc/configs/40x/klondike_defconfig
 arch/powerpc/configs/40x/klondike_defconfig |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/configs/40x/klondike_defconfig b/arch/powerpc/configs/40x/klondike_defconfig
index c0d228d..c35c345 100644
--- a/arch/powerpc/configs/40x/klondike_defconfig
+++ b/arch/powerpc/configs/40x/klondike_defconfig
@@ -30,6 +30,12 @@ CONFIG_SCSI_SAS_ATTRS=y
 # CONFIG_UNIX98_PTYS is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 # CONFIG_USB_SUPPORT is not set
-- 
1.6.1.rc3

^ permalink raw reply related

* [V2 5/5] powerpc: kernel: 16650 UART reg-shift support
From: Tanmay Inamdar @ 2012-04-09  7:20 UTC (permalink / raw)
  To: benh, jwboyer, grant.likely, linuxppc-dev, linux-kernel,
	devicetree-discuss
  Cc: Tanmay Inamdar
In-Reply-To: <1333956052-25319-4-git-send-email-tinamdar@apm.com>

In APM8018X SOC, UART register address space has been relocated to 32-bit
data boundaries for APB bus implementation.
Current legacy_serial driver ignores the reg-shift property. This patch
modifies legacy_serial.c and udbg_16550.c to work with above mentioned UARTs.

Signed-off-by: Tanmay Inamdar <tinamdar@apm.com>
---
:100644 100644 8338aef... f5fc106... M	arch/powerpc/include/asm/udbg.h
:100644 100644 bedd12e... d523b7d... M	arch/powerpc/kernel/legacy_serial.c
:100644 100644 6837f83... e0cb7dc... M	arch/powerpc/kernel/udbg_16550.c
 arch/powerpc/include/asm/udbg.h     |    2 +-
 arch/powerpc/kernel/legacy_serial.c |   16 +++++---
 arch/powerpc/kernel/udbg_16550.c    |   64 ++++++++++++++++++++++------------
 3 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index 8338aef..f5fc106 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -29,7 +29,7 @@ extern void udbg_printf(const char *fmt, ...)
 extern void udbg_progress(char *s, unsigned short hex);
 
 extern void udbg_init_uart(void __iomem *comport, unsigned int speed,
-			   unsigned int clock);
+			   unsigned int clock,  unsigned int regshift);
 extern unsigned int udbg_probe_uart_speed(void __iomem *comport,
 					  unsigned int clock);
 
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index bedd12e..d523b7d 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -33,6 +33,7 @@ static struct legacy_serial_info {
 	unsigned int			clock;
 	int				irq_check_parent;
 	phys_addr_t			taddr;
+	unsigned int			regshift;
 } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS];
 
 static struct __initdata of_device_id legacy_serial_parents[] = {
@@ -42,6 +43,7 @@ static struct __initdata of_device_id legacy_serial_parents[] = {
 	{.compatible = "ibm,opb",},
 	{.compatible = "simple-bus",},
 	{.compatible = "wrs,epld-localbus",},
+	{.compatible = "apm,apb",},
 	{},
 };
 
@@ -163,11 +165,6 @@ static int __init add_legacy_soc_port(struct device_node *np,
 	if (of_get_property(np, "clock-frequency", NULL) == NULL)
 		return -1;
 
-	/* if reg-shift or offset, don't try to use it */
-	if ((of_get_property(np, "reg-shift", NULL) != NULL) ||
-		(of_get_property(np, "reg-offset", NULL) != NULL))
-		return -1;
-
 	/* if rtas uses this device, don't try to use it as well */
 	if (of_get_property(np, "used-by-rtas", NULL) != NULL)
 		return -1;
@@ -319,7 +316,7 @@ static void __init setup_legacy_serial_console(int console)
 	if (info->speed == 0)
 		info->speed = udbg_probe_uart_speed(addr, info->clock);
 	DBG("default console speed = %d\n", info->speed);
-	udbg_init_uart(addr, info->speed, info->clock);
+	udbg_init_uart(addr, info->speed, info->clock, info->regshift);
 }
 
 /*
@@ -336,6 +333,7 @@ void __init find_legacy_serial_ports(void)
 	struct device_node *np, *stdout = NULL;
 	const char *path;
 	int index;
+	unsigned int regshift;
 
 	DBG(" -> find_legacy_serial_port()\n");
 
@@ -359,6 +357,12 @@ void __init find_legacy_serial_ports(void)
 				index = add_legacy_soc_port(np, np);
 				if (index >= 0 && np == stdout)
 					legacy_serial_console = index;
+				if (of_property_read_u32(np, "reg-shift",
+							&regshift) == 0) {
+					legacy_serial_infos
+					[legacy_serial_console].regshift =
+								regshift;
+				}
 			}
 		}
 		of_node_put(parent);
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 6837f83..e0cb7dc 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -47,12 +47,29 @@ struct NS16550 {
 
 #define LCR_DLAB 0x80
 
+static unsigned int reg_shift;
+#define ns16550_offset(addr) (addr - (unsigned char *)udbg_comport)
+
 static struct NS16550 __iomem *udbg_comport;
 
+static inline u8 serial_read(unsigned char *addr)
+{
+	u32 offset = ns16550_offset(addr) << reg_shift;
+	return readb(udbg_comport + offset);
+}
+
+static inline void serial_write(unsigned char *addr, char val)
+{
+	u32 offset = ns16550_offset(addr) << reg_shift;
+	writeb(val, udbg_comport + offset);
+}
+
 static void udbg_550_flush(void)
 {
+	u32 timeout = 1000;
 	if (udbg_comport) {
-		while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
+		while (((serial_read(&udbg_comport->lsr) & LSR_THRE) == 0)
+							&& --timeout)
 			/* wait for idle */;
 	}
 }
@@ -63,15 +80,15 @@ static void udbg_550_putc(char c)
 		if (c == '\n')
 			udbg_550_putc('\r');
 		udbg_550_flush();
-		out_8(&udbg_comport->thr, c);
+		serial_write(&udbg_comport->thr, c);
 	}
 }
 
 static int udbg_550_getc_poll(void)
 {
 	if (udbg_comport) {
-		if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
-			return in_8(&udbg_comport->rbr);
+		if ((serial_read(&udbg_comport->lsr) & LSR_DR) != 0)
+			return serial_read(&udbg_comport->rbr);
 		else
 			return -1;
 	}
@@ -81,15 +98,15 @@ static int udbg_550_getc_poll(void)
 static int udbg_550_getc(void)
 {
 	if (udbg_comport) {
-		while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
+		while ((serial_read(&udbg_comport->lsr) & LSR_DR) == 0)
 			/* wait for char */;
-		return in_8(&udbg_comport->rbr);
+		return serial_read(&udbg_comport->rbr);
 	}
 	return -1;
 }
 
 void udbg_init_uart(void __iomem *comport, unsigned int speed,
-		    unsigned int clock)
+		    unsigned int clock, unsigned int regshift)
 {
 	unsigned int dll, base_bauds;
 
@@ -103,22 +120,23 @@ void udbg_init_uart(void __iomem *comport, unsigned int speed,
 
 	if (comport) {
 		udbg_comport = (struct NS16550 __iomem *)comport;
-		out_8(&udbg_comport->lcr, 0x00);
-		out_8(&udbg_comport->ier, 0xff);
-		out_8(&udbg_comport->ier, 0x00);
-		out_8(&udbg_comport->lcr, LCR_DLAB);
-		out_8(&udbg_comport->dll, dll & 0xff);
-		out_8(&udbg_comport->dlm, dll >> 8);
+		serial_write(&udbg_comport->lcr, 0x00);
+		serial_write(&udbg_comport->ier, 0xff);
+		serial_write(&udbg_comport->ier, 0x00);
+		serial_write(&udbg_comport->lcr, LCR_DLAB);
+		serial_write(&udbg_comport->dll, dll & 0xff);
+		serial_write(&udbg_comport->dlm, dll >> 8);
 		/* 8 data, 1 stop, no parity */
-		out_8(&udbg_comport->lcr, 0x03);
+		serial_write(&udbg_comport->lcr, 0x03);
 		/* RTS/DTR */
-		out_8(&udbg_comport->mcr, 0x03);
+		serial_write(&udbg_comport->mcr, 0x03);
 		/* Clear & enable FIFOs */
-		out_8(&udbg_comport->fcr ,0x07);
+		serial_write(&udbg_comport->fcr, 0x07);
 		udbg_putc = udbg_550_putc;
 		udbg_flush = udbg_550_flush;
 		udbg_getc = udbg_550_getc;
 		udbg_getc_poll = udbg_550_getc_poll;
+		reg_shift = regshift;
 	}
 }
 
@@ -128,24 +146,24 @@ unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock)
 	u8 old_lcr;
 	struct NS16550 __iomem *port = comport;
 
-	old_lcr = in_8(&port->lcr);
+	old_lcr = serial_read(&port->lcr);
 
 	/* select divisor latch registers.  */
-	out_8(&port->lcr, LCR_DLAB);
+	serial_write(&port->lcr, LCR_DLAB);
 
 	/* now, read the divisor */
-	dll = in_8(&port->dll);
-	dlm = in_8(&port->dlm);
+	dll = serial_read(&port->dll);
+	dlm = serial_read(&port->dlm);
 	divisor = dlm << 8 | dll;
 
 	/* check prescaling */
-	if (in_8(&port->mcr) & 0x80)
+	if (serial_read(&port->mcr) & 0x80)
 		prescaler = 4;
 	else
 		prescaler = 1;
 
 	/* restore the LCR */
-	out_8(&port->lcr, old_lcr);
+	serial_write(&port->lcr, old_lcr);
 
 	/* calculate speed */
 	speed = (clock / prescaler) / (divisor * 16);
@@ -341,7 +359,7 @@ void __init udbg_init_wsp(void)
 {
 	udbg_comport = (struct NS16550 __iomem *)WSP_UART_VIRT;
 
-	udbg_init_uart(udbg_comport, 57600, 50000000);
+	udbg_init_uart(udbg_comport, 57600, 50000000, 0);
 
 	udbg_putc = udbg_wsp_putc;
 	udbg_flush = udbg_wsp_flush;
-- 
1.6.1.rc3

^ permalink raw reply related

* Re: [PATCH 1/1] Add support 2 SATA ports for Maui and change filename from sata_dwc_460ex.c to sata_dwc_4xx.c
From: Sergei Shtylyov @ 2012-04-09 10:12 UTC (permalink / raw)
  To: Thang Q. Nguyen
  Cc: devicetree-discuss, linux-kernel, Rob Herring, linux-ide,
	Paul Mackerras, Jeff Garzik, linuxppc-dev
In-Reply-To: <1333447938-16461-1-git-send-email-tqnguyen@apm.com>

Hello.

On 03-04-2012 14:12, Thang Q. Nguyen wrote:

> Signed-off-by: Thang Q. Nguyen<tqnguyen@apm.com>
[...]

> diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts
> index cfa23bf..803fda6 100644
> --- a/arch/powerpc/boot/dts/bluestone.dts
> +++ b/arch/powerpc/boot/dts/bluestone.dts
> @@ -155,6 +155,27 @@
>   					/*RXDE*/  0x5 0x4>;
>   		};
>
> +		/* SATA DWC devices */
> +		SATA0: sata@bffd1000 {
> +			compatible = "amcc,sata-apm821xx";
> +			reg =<4 0xbffd1000 0x800   /* SATA0 */
> +			       4 0xbffd0800 0x400>; /* AHBDMA */
> +			dma-channel=<0>;
> +			interrupt-parent =<&UIC0>;
> +			interrupts =<26 4    /* SATA0 */
> +			              25 4>;  /* AHBDMA */
> +		};
> +
> +		SATA1: sata@bffd1800 {
> +			compatible = "amcc,sata-apm821xx";
> +			reg =<4 0xbffd1800 0x800   /* SATA1 */
> +			       4 0xbffd0800 0x400>; /* AHBDMA */
> +			dma-channel=<1>;
> +			interrupt-parent =<&UIC0>;
> +			interrupts =<27 4    /* SATA1 */
> +			              25 4>;  /* AHBDMA */
> +		};
> +

    So, this is dual SATA controller, not dual port SATA controller?
BTW, it's wrong to have the same AHBDMA resource in two device nodes I think.

MBR, Sergei

^ permalink raw reply

* Re: [PATCH] powerpc: 512x: Fix mpc5121_clk_get()
From: Richard Weinberger @ 2012-04-09 13:06 UTC (permalink / raw)
  To: Richard Weinberger; +Cc: paulus, agust, linuxppc-dev, linux-kernel
In-Reply-To: <1332788489-27435-1-git-send-email-richard@nod.at>

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

Am 26.03.2012 21:01, schrieb Richard Weinberger:
> If try_module_get() fails, mpc5121_clk_get() might return
> a wrong clock.
> 
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
>  arch/powerpc/platforms/512x/clock.c |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
> index 1d8700f..9f771e0 100644
> --- a/arch/powerpc/platforms/512x/clock.c
> +++ b/arch/powerpc/platforms/512x/clock.c
> @@ -54,14 +54,16 @@ static DEFINE_MUTEX(clocks_mutex);
>  static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
>  {
>  	struct clk *p, *clk = ERR_PTR(-ENOENT);
> -	int dev_match = 0;
> -	int id_match = 0;
> +	int dev_match;
> +	int id_match;
>  
>  	if (dev == NULL || id == NULL)
>  		return clk;
>  
>  	mutex_lock(&clocks_mutex);
>  	list_for_each_entry(p, &clocks, node) {
> +		dev_match = id_match = 0;
> +
>  		if (dev == p->dev)
>  			dev_match++;
>  		if (strcmp(id, p->name) == 0)

*ping*

Thanks,
//richard


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* Re: [PATCH 00/14] Backport 8xx TLB to 2.4
From: Willy Tarreau @ 2012-04-09 13:08 UTC (permalink / raw)
  To: Joakim Tjernlund; +Cc: Scott Wood, linuxppc-dev, Dan Malek
In-Reply-To: <OFE7D02EF5.C8AA7552-ONC125799E.0037BB62-C125799E.0040126D@transmode.se>

Hi Joakim,

On Wed, Feb 08, 2012 at 12:39:50PM +0100, Joakim Tjernlund wrote:
> I figure, after 2.4.37.12, a public git tree on kernel org which still
> receives fixes would be enough.

FYI, I've merged your patches and pushed them along with a few pending
other ones here :

   http://git.kernel.org/?p=linux/kernel/git/wtarreau/linux-2.4.git;a=summary

There will only be git updates from now on. Probably that once in a while I'll
tag the tree to make things easier to check.

Thanks for taking care of sending fixes for old kernels !

Cheers,
Willy

^ permalink raw reply

* Re: Problem with framebuffer mmap on platforms with large addressing
From: Dmitry Eremin-Solenikov @ 2012-04-09 16:18 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linux-fbdev, Florian Tobias Schandinat, Tony Breeds, linuxppc-dev
In-Reply-To: <1332222008.2982.13.camel@pasglop>

On Tue, Mar 20, 2012 at 9:40 AM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
>
>> >> That is interesting! Are those patches published or otherwise available
>> >> somewhere? We are also very interested in enabling Canyonlands
>> >> with Radeon KMS!
>> >
>> > You will run into additional problems with 460 due to the fact that it's
>> > not cache coherent for DMA. Tony patches don't address that part of the
>> > problem (they were used on a 476 based platform).
>>
>> Hmm. Could you please spill a little bit more of details? Also are those patches
>> for 476 merged or present somewhere?
>
> Well, DMA on 46x isn't cache coherent. The DRM plays interesting games
> with mapping/unmapping pages for DMA by the chip and I don't think we
> have the right hooks to do the appropriate cache flushing on these guys,
> but Tony might be able to comment, I don't know whether he tried or not.
>
> On the other hand 476 has fully cache coherent DMA so the only problem
> there is the >32-bit physical address space.
>
> As for the patches, you'll have to wait for Tony to respond (I'll poke
> him locally).

Any news on these patches? A dirty and "not for the upstream yet" version
would be sufficient for me for now.

>
> Cheers,
> Ben.
>

-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: Problem with framebuffer mmap on platforms with large addressing
From: Benjamin Herrenschmidt @ 2012-04-09 21:37 UTC (permalink / raw)
  To: Dmitry Eremin-Solenikov
  Cc: linux-fbdev, Florian Tobias Schandinat, Tony Breeds, linuxppc-dev
In-Reply-To: <CALT56yOU2FDTNRnr=aLVFTGHiVsGNKVoqLqAWQ7Q+Xzg6_B8qQ@mail.gmail.com>

On Mon, 2012-04-09 at 20:18 +0400, Dmitry Eremin-Solenikov wrote:
> > As for the patches, you'll have to wait for Tony to respond (I'll
> poke
> > him locally).
> 
> Any news on these patches? A dirty and "not for the upstream yet"
> version
> would be sufficient for me for now.

I'll poke again..

Cheers,
Ben.

^ permalink raw reply

* Re: P4080 Device tree
From: Scott Wood @ 2012-04-09 22:50 UTC (permalink / raw)
  To: dimitar; +Cc: linuxppc-dev
In-Reply-To: <4F7B056F.8010100@nateurope.com>

On 04/03/2012 09:13 AM, dimitar wrote:
> Hello,
> 
> I hope I'm posting my question on the right place.
> Please be gentle to me, since I'm newbie in Linux Kernel.
> 
> I'm porting Linux to a custom board based on P4080DS BSP. My problem is
> that I cannot understand the configuration of th DPA in the device tree
> including QMAN, BMAN and FMAN.

None of the datapath stuff is in mainline Linux yet -- for BSP support
you should ask support@freescale.com (or your sales/FAE/etc. contact).

-Scott

^ permalink raw reply

* RE: [PATCH 1/1] Add support 2 SATA ports for Maui and change filename from sata_dwc_460ex.c to sata_dwc_4xx.c
From: Thang Nguyen @ 2012-04-10  3:46 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: devicetree-discuss, linux-kernel, Rob Herring, linux-ide,
	Paul Mackerras, Jeff Garzik, linuxppc-dev
In-Reply-To: <4F82B61D.8010502@mvista.com>

Hi Sergei,
Thanks for your review.
On Maui, there are 2 separate SATA controllers but they share the same
AHBDMA controller. Each SATA controller is assigned a fixed DMA channel on
the AHBDMA (channel 0 is assigned to SATA controller 0 and channel 1 is
assigned to SATA controller 1).
For the 460EX, there is only 1 SATA controller and it uses channel 0 for
transferring data.

In my opinion, in the case of Maui, we can use the same DMA information in
2 device nodes as they use the same DMA controller. And in another CPU, if
they use different DMA controller, the corresponding information will also
be different.

Regards,
Thang Nguyen -
-----Original Message-----
From: Sergei Shtylyov [mailto:sshtylyov@mvista.com]
Sent: Monday, April 09, 2012 5:13 PM
To: Thang Q. Nguyen
Cc: Benjamin Herrenschmidt; Paul Mackerras; Jeff Garzik; Grant Likely; Rob
Herring; linuxppc-dev@lists.ozlabs.org; linux-kernel@vger.kernel.org;
linux-ide@vger.kernel.org; devicetree-discuss@lists.ozlabs.org
Subject: Re: [PATCH 1/1] Add support 2 SATA ports for Maui and change
filename from sata_dwc_460ex.c to sata_dwc_4xx.c

Hello.

On 03-04-2012 14:12, Thang Q. Nguyen wrote:

> Signed-off-by: Thang Q. Nguyen<tqnguyen@apm.com>
[...]

> diff --git a/arch/powerpc/boot/dts/bluestone.dts
b/arch/powerpc/boot/dts/bluestone.dts
> index cfa23bf..803fda6 100644
> --- a/arch/powerpc/boot/dts/bluestone.dts
> +++ b/arch/powerpc/boot/dts/bluestone.dts
> @@ -155,6 +155,27 @@
>   					/*RXDE*/  0x5 0x4>;
>   		};
>
> +		/* SATA DWC devices */
> +		SATA0: sata@bffd1000 {
> +			compatible = "amcc,sata-apm821xx";
> +			reg =<4 0xbffd1000 0x800   /* SATA0 */
> +			       4 0xbffd0800 0x400>; /* AHBDMA */
> +			dma-channel=<0>;
> +			interrupt-parent =<&UIC0>;
> +			interrupts =<26 4    /* SATA0 */
> +			              25 4>;  /* AHBDMA */
> +		};
> +
> +		SATA1: sata@bffd1800 {
> +			compatible = "amcc,sata-apm821xx";
> +			reg =<4 0xbffd1800 0x800   /* SATA1 */
> +			       4 0xbffd0800 0x400>; /* AHBDMA */
> +			dma-channel=<1>;
> +			interrupt-parent =<&UIC0>;
> +			interrupts =<27 4    /* SATA1 */
> +			              25 4>;  /* AHBDMA */
> +		};
> +

    So, this is dual SATA controller, not dual port SATA controller?
BTW, it's wrong to have the same AHBDMA resource in two device nodes I
think.

MBR, Sergei
CONFIDENTIALITY NOTICE: This e-mail message, including any attachments, 
is for the sole use of the intended recipient(s) and contains information 
that is confidential and proprietary to AppliedMicro Corporation or its subsidiaries. 
It is to be used solely for the purpose of furthering the parties' business relationship. 
All unauthorized review, use, disclosure or distribution is prohibited. 
If you are not the intended recipient, please contact the sender by reply e-mail 
and destroy all copies of the original message.

^ permalink raw reply

* [PATCH] gianfar: add missing include
From: Michael Neuling @ 2012-04-10  4:18 UTC (permalink / raw)
  To: David S. Miller, Richard Cochran; +Cc: linuxppc-dev, linux-next, netdev

next-20120405 compiled with mpc85xx_defconfig gives the following:

  CC      drivers/net/ethernet/freescale/gianfar_ethtool.o
drivers/net/ethernet/freescale/gianfar_ethtool.c: In function 'gfar_get_ts_info':
drivers/net/ethernet/freescale/gianfar_ethtool.c:1751:4: error: 'SOF_TIMESTAMPING_RX_SOFTWARE' undeclared (first use in this function)
drivers/net/ethernet/freescale/gianfar_ethtool.c:1751:4: note: each undeclared identifier is reported only once for each function it appears in
drivers/net/ethernet/freescale/gianfar_ethtool.c:1752:4: error: 'SOF_TIMESTAMPING_SOFTWARE' undeclared (first use in this function)
drivers/net/ethernet/freescale/gianfar_ethtool.c:1757:3: error: 'SOF_TIMESTAMPING_TX_HARDWARE' undeclared (first use in this function)
drivers/net/ethernet/freescale/gianfar_ethtool.c:1758:3: error: 'SOF_TIMESTAMPING_RX_HARDWARE' undeclared (first use in this function)
drivers/net/ethernet/freescale/gianfar_ethtool.c:1759:3: error: 'SOF_TIMESTAMPING_RAW_HARDWARE' undeclared (first use in this function)
drivers/net/ethernet/freescale/gianfar_ethtool.c:1762:9: error: 'HWTSTAMP_TX_OFF' undeclared (first use in this function)
drivers/net/ethernet/freescale/gianfar_ethtool.c:1763:9: error: 'HWTSTAMP_TX_ON' undeclared (first use in this function)
drivers/net/ethernet/freescale/gianfar_ethtool.c:1765:9: error: 'HWTSTAMP_FILTER_NONE' undeclared (first use in this function)
drivers/net/ethernet/freescale/gianfar_ethtool.c:1766:9: error: 'HWTSTAMP_FILTER_ALL' undeclared (first use in this function)

This is because of a missing include file from:
  6663628 gianfar: Support the get_ts_info ethtool method.

Signed-off-by: Michael Neuling <mikey@neuling.org>
CC: Richard Cochran <richardcochran@gmail.com>
CC: David S. Miller <davem@davemloft.net>

diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 27f49c7..3c34b32b 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -29,6 +29,7 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
+#include <linux/net_tstamp.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>

^ permalink raw reply related

* Re: 3.4.0-rc1: No init found
From: Christian Kujau @ 2012-04-10  5:47 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, LKML
In-Reply-To: <1333440522.3040.9.camel@pasglop>

On Tue, 3 Apr 2012 at 18:08, Benjamin Herrenschmidt wrote:
> On Tue, 2012-04-03 at 00:20 -0700, Christian Kujau wrote:
> > Going from 3.3-rc7 to 3.4-rc1 (with "make oldconfig" inbetween) did not 
> > go well on this PowerBook G4 machine:
> > 
> > Apr  2 15:18:23 [   8.318816] EXT4-fs (hda6): mounted filesystem with ordered data mode. Opts: (null)
> > Apr  2 15:18:23 [   8.320286] VFS: Mounted root (ext4 filesystem) readonly on device 3:6.
> > Apr  2 15:18:23 [   8.341555] devtmpfs: mounted
> > Apr  2 15:18:23 [   8.343384] Freeing unused kernel memory: 204k freed
> > Apr  2 15:18:23 [   8.457056] Kernel panic - not syncing: No init found.  Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
> > Apr  2 15:18:23 [   8.459936] Rebooting in 180 seconds..
> 
> I have observed this randomly on the G5 ... sometimes, if I try again,
> it works... it's very very odd. There is some kind of race maybe with
> async startup ? Or a problem with the vfs path walking ? It's certainly
> not easily reproducable for me, it goes away from one boot to the next.

I tried to sit this one out, but when -rc2 did not magicially fix it I 
started a git bisect, this is what I got:

* a546498f3bf9aac311c66f965186373aee2ca0b0 is the first bad commit

commit a546498f3bf9aac311c66f965186373aee2ca0b0
Author: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date:   Wed Mar 7 16:48:45 2012 +1100

    powerpc: Call do_page_fault() with interrupts off


Full bisect-log & more: http://nerdbynature.de/bits/3.4.0-rc1/init/ 

Thanks,
Christian.
-- 
BOFH excuse #124:

user to computer ration too low.

^ permalink raw reply

* Re: [PATCH] gianfar: add missing include
From: Richard Cochran @ 2012-04-10  6:36 UTC (permalink / raw)
  To: Michael Neuling; +Cc: linuxppc-dev, linux-next, David S. Miller, netdev
In-Reply-To: <25411.1334031527@neuling.org>

On Tue, Apr 10, 2012 at 02:18:47PM +1000, Michael Neuling wrote:
> This is because of a missing include file from:
>   6663628 gianfar: Support the get_ts_info ethtool method.
> 
> Signed-off-by: Michael Neuling <mikey@neuling.org>

I did a poor job testing the non-x86 stuff in this series.  Thanks for
the fix.

Acked-by: Richard Cochran <richardcochran@gmail.com>

^ permalink raw reply

* Re: [PATCH] gianfar: add missing include
From: Michael Neuling @ 2012-04-10  6:41 UTC (permalink / raw)
  To: Richard Cochran; +Cc: linuxppc-dev, linux-next, David S. Miller, netdev
In-Reply-To: <20120410063641.GA10025@localhost.localdomain>

Richard Cochran <richardcochran@gmail.com> wrote:
> On Tue, Apr 10, 2012 at 02:18:47PM +1000, Michael Neuling wrote:
> > This is because of a missing include file from:
> >   6663628 gianfar: Support the get_ts_info ethtool method.
> > 
> > Signed-off-by: Michael Neuling <mikey@neuling.org>
> 
> I did a poor job testing the non-x86 stuff in this series.  Thanks for
> the fix.
> 
> Acked-by: Richard Cochran <richardcochran@gmail.com>

Looks like davem fixed it before my post anyway...

http://git.kernel.org/?p=linux/kernel/git/davem/net-next.git;a=commitdiff;h=65a85a8d4dcabe95587ab61bece38b8d58174043

This is in next-20120410.

Sorry for the noise. 

Mikey

^ permalink raw reply

* Re: 3.4.0-rc1: No init found
From: Benjamin Herrenschmidt @ 2012-04-10  7:23 UTC (permalink / raw)
  To: Christian Kujau; +Cc: linuxppc-dev, Suzuki K. Poulose, LKML
In-Reply-To: <alpine.DEB.2.01.1204040944210.4930@trent.utfs.org>

On Wed, 2012-04-04 at 09:45 -0700, Christian Kujau wrote:
> On Wed, 4 Apr 2012 at 18:06, Suzuki K. Poulose wrote:
> > > INFO: Uncompressed kernel (size 0x6d4b80) overlaps the address of the
> > > wrapper(0x400000)
> > > INFO: Fixing the link_address of wrapper to (0x700000)
> > >    Building modules, stage 2.
> > >    MODPOST 24 modules
> > > ------------
> > > 
> > > I started to see these messages in January (around Linux 3.2.0), but never
> > > investigated what it was since the produced kernels continued to boot just
> > > fine.
> > 
> > The above change was added by me. The message is printed when the 'wrapper'
> > script finds that decompressed kernel overlaps the 'bootstrap code' which does
> > the decompression. So it shifts the 'address' of the bootstrap code to the
> > next higher MB. As such it is harmless.
> 
> OK, good to know that it's harmless. Thanks for the explanation.

I think I found it :-)

can you test the patch below ?

>From 08f1ec8a594c60bf3856e3c45b6d15fd691d90bb Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Tue, 10 Apr 2012 17:21:35 +1000
Subject: [PATCH] powerpc: Fix page fault with lockdep regression

commit a546498f3bf9aac311c66f965186373aee2ca0b0
introduced a regression on 32-bit when irq tracing
is enabled by exposing an old bug in our irq tracing
code for exception entry.

The code would save and restore some GPRs around the
calls to the C lockdep code, however, it tries to be
too smart for its own good and restores some of the
GPRs from the exception frame (as saved there on
exception entry).

However, for page faults, we do replace those GPRs with
arguments to do_page_fault before we call transfer_to_handler
and so restoring from the exception frame is plain wrong in
this case.

This was fine as long as we didn't touch the interrupt state
when taking page fault, but when I started doing it, it would
trigger the lockdep calls and the bug.

This fixes it by cleaning up that code a bit. It did create
a small stack frame for the sake of backtraces, so let's
make it a bit bigger and use it to save and restore the
stuff we care about.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/entry_32.S |   39 +++++++++++++++++++++------------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 3e57a00..ba3aeb4 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -206,40 +206,43 @@ reenable_mmu:				/* re-enable mmu so we can */
 	andi.	r10,r10,MSR_EE		/* Did EE change? */
 	beq	1f
 
-	/* Save handler and return address into the 2 unused words
-	 * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything
-	 * else can be recovered from the pt_regs except r3 which for
-	 * normal interrupts has been set to pt_regs and for syscalls
-	 * is an argument, so we temporarily use ORIG_GPR3 to save it
-	 */
-	stw	r9,8(r1)
-	stw	r11,12(r1)
-	stw	r3,ORIG_GPR3(r1)
 	/*
 	 * The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1.
 	 * If from user mode there is only one stack frame on the stack, and
 	 * accessing CALLER_ADDR1 will cause oops. So we need create a dummy
 	 * stack frame to make trace_hardirqs_off happy.
+	 *
+	 * This is handy because we also need to save a bunch of GPRs,
+	 * r3 can be different from GPR3(r1) at this point, r9 and r11
+	 * contains the old MSR and handler address respectively,
+	 * r4 & r5 can contain page fault arguments that need to be passed
+	 * along as well. r12, CCR, CTR, XER etc... are left clobbered as
+	 * they aren't useful past this point (aren't syscall arguments),
+	 * the rest is restored from the exception frame.
 	 */
+	stwu	r1,-32(r1)
+	stw	r9,8(r1)
+	stw	r11,12(r1)
+	stw	r3,16(r1)
+	stw	r4,20(r1)
+	stw	r5,24(r1)
 	andi.	r12,r12,MSR_PR
-	beq	11f
-	stwu	r1,-16(r1)
+	b	11f
 	bl	trace_hardirqs_off
-	addi	r1,r1,16
 	b	12f
-
 11:
 	bl	trace_hardirqs_off
 12:
+	lwz	r5,24(r1)
+	lwz	r4,20(r1)
+	lwz	r3,16(r1)
+	lwz	r11,12(r1)
+	lwz	r9,8(r1)
+	addi	r1,r1,32
 	lwz	r0,GPR0(r1)
-	lwz	r3,ORIG_GPR3(r1)
-	lwz	r4,GPR4(r1)
-	lwz	r5,GPR5(r1)
 	lwz	r6,GPR6(r1)
 	lwz	r7,GPR7(r1)
 	lwz	r8,GPR8(r1)
-	lwz	r9,8(r1)
-	lwz	r11,12(r1)
 1:	mtctr	r11
 	mtlr	r9
 	bctr				/* jump to handler */
-- 
1.7.9.5

^ permalink raw reply related

* RE: [RFC] powerpc/fsl-pci: Document the "fsl,has-isa" property for Freescale PCI
From: Jia Hongtao-B38951 @ 2012-04-10  9:17 UTC (permalink / raw)
  To: Kumar Gala
  Cc: devicetree-discuss@lists.ozlabs.org,
	linuxppc-dev@lists.ozlabs.org, Li Yang-R58472, Jia Hongtao-B38951
In-Reply-To: <412C8208B4A0464FA894C5F0C278CD5D019DBE90@039-SN1MPN1-002.039d.mgd.msft.net>


> -----Original Message-----
> From: linuxppc-dev-bounces+b38951=3Dfreescale.com@lists.ozlabs.org
> [mailto:linuxppc-dev-bounces+b38951=3Dfreescale.com@lists.ozlabs.org] On
> Behalf Of Jia Hongtao-B38951
> Sent: Friday, April 06, 2012 11:05 AM
> To: Kumar Gala
> Cc: devicetree-discuss@lists.ozlabs.org; linuxppc-dev@lists.ozlabs.org;
> Li Yang-R58472
> Subject: RE: [RFC] powerpc/fsl-pci: Document the "fsl,has-isa" property
> for Freescale PCI
>=20
>=20
> > -----Original Message-----
> > From: Kumar Gala [mailto:galak@kernel.crashing.org]
> > Sent: Wednesday, April 04, 2012 9:09 PM
> > To: Jia Hongtao-B38951
> > Cc: linuxppc-dev@lists.ozlabs.org; Li Yang-R58472; devicetree-
> > discuss@lists.ozlabs.org
> > Subject: Re: [RFC] powerpc/fsl-pci: Document the "fsl,has-isa" property
> > for Freescale PCI
> >
> >
> > On Apr 1, 2012, at 1:56 AM, Jia Hongtao wrote:
> >
> > > If PCI is primary bus we should set isa_io/mem_base when parsing PCI
> > bridge
> > > resources from device tree. The previous way to check the primary bus
> > based
> > > on a hard-coded address named primary_phb_addr. Now we add a property
> > named
> > > "fsl,has-isa" into device tree. In kernel we use this property to
> find
> > out
> > > the bus is primary or not. This way is more flexible.
> > >
> > > Signed-off-by: Jia Hongtao <B38951@freescale.com>
> > > Signed-off-by: Li Yang <leoli@freescale.com>
> > > ---
> > > .../devicetree/bindings/powerpc/fsl/pci.txt        |   36
> > ++++++++++++++++++++
> > > 1 files changed, 36 insertions(+), 0 deletions(-)
> > > create mode 100644
> > Documentation/devicetree/bindings/powerpc/fsl/pci.txt
> >
> > This isn't freescale specific, its linux specific.  If anything the
> > property should be linux,has-isa.
> >
> > But in general I dont think this is a good idea.  In truth one could
> > search the device tree for:
> >
> > 	device_type =3D "isa";
> >
> > to try and set this dynamically.
> >
> > - k
> >
>=20
> Yes, it's not Freescale specific, but it's only used by Freescale now in
> the kernel. This is why I named the property as "fsl,has-isa".
>=20
> To indicate PCI bus is primary we have three ways to go and we now like
> the 2nd solution:
>=20
> 1. As this patch said, we add a property to device tree manually.
>=20
> 2. Set this property dynamically in uboot when scanning PCI bridge.
> Actually we have already done this. The problem is users should update
> uboot and kernel together or it's not work. To support old uboot we
> decide
> to add this property into device tree too temporarily. We will remove it
> from device tree at an appropriate future.
>=20
> 3. Just as you said we could search the device tree by device_type =3D
> "isa".
>    There are two problems here:
> 	* There is no OF API for searching just in PCI node now. That means
> 	  we can't easily find whether there is "isa" bridge or not under
> 	  this PCI controller while scanning it.
> 	* Boards MPC8541CDS and MPC8555CDS has no "isa" node in device tree
> 	  but has ISA bridge under PCI controller.
>=20
> - Jia Hongtao
>=20

Hi Kumar,

I agree with the name change from "fsl,has-isa" to "linux,has-isa".
If this is ok I will update this patch and send the patches based on this
new property.

Also, I have a question about "isa" node in dts. Is this node being used
by kernel? If not we can remove it from all boards and check the primary
bus by uboot. If "isa" is useful why MPC8541CDS and MPC8555CDS has no
"isa" node in device tree but has ISA bridge under PCI controller?

Thanks.
- Jia Hongtao

^ permalink raw reply

* Re: [PATCH 1/1] Add support 2 SATA ports for Maui and change filename from sata_dwc_460ex.c to sata_dwc_4xx.c
From: Sergei Shtylyov @ 2012-04-10 11:22 UTC (permalink / raw)
  To: Thang Nguyen
  Cc: devicetree-discuss, linux-kernel, Rob Herring, linux-ide,
	Paul Mackerras, Jeff Garzik, linuxppc-dev
In-Reply-To: <8a0ea5bd221ddeb9eded16e180aa8fbb@mail.gmail.com>

Hello.

On 10-04-2012 7:46, Thang Nguyen wrote:

> Hi Sergei,
> Thanks for your review.

> On Maui, there are 2 separate SATA controllers but they share the same
> AHBDMA controller. Each SATA controller is assigned a fixed DMA channel on
> the AHBDMA (channel 0 is assigned to SATA controller 0 and channel 1 is
> assigned to SATA controller 1).
> For the 460EX, there is only 1 SATA controller and it uses channel 0 for
> transferring data.

> In my opinion, in the case of Maui, we can use the same DMA information in
> 2 device nodes as they use the same DMA controller. And in another CPU, if
> they use different DMA controller, the corresponding information will also
> be different.

    No, either the DMA controller should be a separate device node, or both 
ports and DMA controller should be packed into the single device node. The way 
you're doing it is incorrect because it creates memory resource conflict 
between devices when they are instantiated as platfrom devices.

> Regards,
> Thang Nguyen -
> -----Original Message-----
> From: Sergei Shtylyov [mailto:sshtylyov@mvista.com]
> Sent: Monday, April 09, 2012 5:13 PM
> To: Thang Q. Nguyen
> Cc: Benjamin Herrenschmidt; Paul Mackerras; Jeff Garzik; Grant Likely; Rob
> Herring; linuxppc-dev@lists.ozlabs.org; linux-kernel@vger.kernel.org;
> linux-ide@vger.kernel.org; devicetree-discuss@lists.ozlabs.org
> Subject: Re: [PATCH 1/1] Add support 2 SATA ports for Maui and change
> filename from sata_dwc_460ex.c to sata_dwc_4xx.c

> Hello.

> On 03-04-2012 14:12, Thang Q. Nguyen wrote:

>> Signed-off-by: Thang Q. Nguyen<tqnguyen@apm.com>
> [...]

>> diff --git a/arch/powerpc/boot/dts/bluestone.dts
> b/arch/powerpc/boot/dts/bluestone.dts
>> index cfa23bf..803fda6 100644
>> --- a/arch/powerpc/boot/dts/bluestone.dts
>> +++ b/arch/powerpc/boot/dts/bluestone.dts
>> @@ -155,6 +155,27 @@
>>    					/*RXDE*/  0x5 0x4>;
>>    		};
>>
>> +		/* SATA DWC devices */
>> +		SATA0: sata@bffd1000 {
>> +			compatible = "amcc,sata-apm821xx";
>> +			reg =<4 0xbffd1000 0x800   /* SATA0 */
>> +			       4 0xbffd0800 0x400>; /* AHBDMA */
>> +			dma-channel=<0>;
>> +			interrupt-parent =<&UIC0>;
>> +			interrupts =<26 4    /* SATA0 */
>> +			              25 4>;  /* AHBDMA */
>> +		};
>> +
>> +		SATA1: sata@bffd1800 {
>> +			compatible = "amcc,sata-apm821xx";
>> +			reg =<4 0xbffd1800 0x800   /* SATA1 */
>> +			       4 0xbffd0800 0x400>; /* AHBDMA */
>> +			dma-channel=<1>;
>> +			interrupt-parent =<&UIC0>;
>> +			interrupts =<27 4    /* SATA1 */
>> +			              25 4>;  /* AHBDMA */
>> +		};
>> +

>      So, this is dual SATA controller, not dual port SATA controller?
> BTW, it's wrong to have the same AHBDMA resource in two device nodes I
> think.

> MBR, Sergei

    Can you get rid of the following? It looks stupid when you post to the 
maliing list.

> CONFIDENTIALITY NOTICE: This e-mail message, including any attachments,
> is for the sole use of the intended recipient(s) and contains information
> that is confidential and proprietary to AppliedMicro Corporation or its subsidiaries.
> It is to be used solely for the purpose of furthering the parties' business relationship.
> All unauthorized review, use, disclosure or distribution is prohibited.
> If you are not the intended recipient, please contact the sender by reply e-mail
> and destroy all copies of the original message.

WBR, Sergei

^ permalink raw reply

* [PATCH v2 00/17] Platform Facilities Option and crypto accelerators
From: Kent Yoder @ 2012-04-10 15:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: key, rcj, linuxppc-dev, linux-crypto

ChangeLog for v2:
- move crypto driver sysfs stuff to debugfs (Greg K-H)
- Remove CONFIG_ dependencies for the CMO bits (Anton Blanchard)
- move nx driver code to drivers/crypto (Kumar Gala)
- Add inline comment for nx_build_sg_list (Rob Jennings)
- make sure kmalloc'd pointers are aligned (Rob Jennings)
- get rid of bitfields in nx_csbcpb.h (Rob Jennings)
- Compile against Ben Herrenschmidt's ppc device naming patch
- Rebase against latest upstream

Kent Yoder (12):
  powerpc: crypto: AES-CBC mode routines for nx encryption
  powerpc: crypto: AES-CCM mode routines for nx encryption
  powerpc: crypto: AES-CTR mode routines for nx encryption
  powerpc: crypto: AES-ECB mode routines for nx encryption
  powerpc: crypto: AES-GCM mode routines for nx encryption
  powerpc: crypto: AES-XCBC mode routines for nx encryption
  powerpc: crypto: SHA256 hash routines for nx encryption
  powerpc: crypto: SHA512 hash routines for nx encryption
  powerpc: crypto: nx driver code supporting nx encryption
  powerpc: crypto: debugfs routines and docs for the nx device driver
  powerpc: crypto: Build files for the nx device driver
  powerpc: crypto: enable the PFO-based encryption device

Michael Neuling (1):
  hwrng: pseries - PFO-based hwrng driver

Robert Jennings (4):
  powerpc: Add new hvcall constants to support PFO
  powerpc: Add pseries update notifier for OFDT prop changes
  powerpc: Add PFO support to the VIO bus
  pseries: Enabled the PFO-based RNG accelerator

 Documentation/ABI/testing/debugfs-pfo-nx-crypto |   45 ++
 arch/powerpc/Makefile                           |    1 +
 arch/powerpc/include/asm/hvcall.h               |   25 +-
 arch/powerpc/include/asm/pSeries_reconfig.h     |   12 +
 arch/powerpc/include/asm/vio.h                  |   46 ++
 arch/powerpc/kernel/prom_init.c                 |    9 +-
 arch/powerpc/kernel/vio.c                       |  273 ++++++++--
 arch/powerpc/platforms/pseries/reconfig.c       |    7 +
 drivers/char/hw_random/Kconfig                  |   13 +
 drivers/char/hw_random/Makefile                 |    1 +
 drivers/char/hw_random/pseries-rng.c            |   96 +++
 drivers/crypto/Kconfig                          |   17 +
 drivers/crypto/nx/Makefile                      |   11 +
 drivers/crypto/nx/nx-aes-cbc.c                  |  140 +++++
 drivers/crypto/nx/nx-aes-ccm.c                  |  465 +++++++++++++++
 drivers/crypto/nx/nx-aes-ctr.c                  |  177 ++++++
 drivers/crypto/nx/nx-aes-ecb.c                  |  138 +++++
 drivers/crypto/nx/nx-aes-gcm.c                  |  353 +++++++++++
 drivers/crypto/nx/nx-aes-xcbc.c                 |  234 ++++++++
 drivers/crypto/nx/nx-sha256.c                   |  244 ++++++++
 drivers/crypto/nx/nx-sha512.c                   |  263 +++++++++
 drivers/crypto/nx/nx.c                          |  711 +++++++++++++++++++++++
 drivers/crypto/nx/nx.h                          |  192 ++++++
 drivers/crypto/nx/nx_csbcpb.h                   |  205 +++++++
 drivers/crypto/nx/nx_debugfs.c                  |  103 ++++
 25 files changed, 3739 insertions(+), 42 deletions(-)
 create mode 100644 Documentation/ABI/testing/debugfs-pfo-nx-crypto
 create mode 100644 drivers/char/hw_random/pseries-rng.c
 create mode 100644 drivers/crypto/nx/Makefile
 create mode 100644 drivers/crypto/nx/nx-aes-cbc.c
 create mode 100644 drivers/crypto/nx/nx-aes-ccm.c
 create mode 100644 drivers/crypto/nx/nx-aes-ctr.c
 create mode 100644 drivers/crypto/nx/nx-aes-ecb.c
 create mode 100644 drivers/crypto/nx/nx-aes-gcm.c
 create mode 100644 drivers/crypto/nx/nx-aes-xcbc.c
 create mode 100644 drivers/crypto/nx/nx-sha256.c
 create mode 100644 drivers/crypto/nx/nx-sha512.c
 create mode 100644 drivers/crypto/nx/nx.c
 create mode 100644 drivers/crypto/nx/nx.h
 create mode 100644 drivers/crypto/nx/nx_csbcpb.h
 create mode 100644 drivers/crypto/nx/nx_debugfs.c

^ permalink raw reply

* [PATCH v2 02/17] powerpc: Add pseries update notifier for OFDT prop changes
From: Kent Yoder @ 2012-04-10 15:08 UTC (permalink / raw)
  To: linux-kernel; +Cc: key, rcj, linuxppc-dev, linux-crypto
In-Reply-To: <1334070249.16827.1.camel@key-ThinkPad-W510>

This adds an update notifier mechanism for changes to properties in the
device tree.  One use of this would be a device driver that needs to act
on changes to it's properties in the device tree after a live migration
or a dynamic activation that is triggered by updates to ofdt properties.

Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/pSeries_reconfig.h |   12 ++++++++++++
 arch/powerpc/platforms/pseries/reconfig.c   |    7 +++++++
 2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h
index 23cd6cc..c07edfe 100644
--- a/arch/powerpc/include/asm/pSeries_reconfig.h
+++ b/arch/powerpc/include/asm/pSeries_reconfig.h
@@ -13,6 +13,18 @@
 #define PSERIES_RECONFIG_REMOVE		0x0002
 #define PSERIES_DRCONF_MEM_ADD		0x0003
 #define PSERIES_DRCONF_MEM_REMOVE	0x0004
+#define PSERIES_UPDATE_PROPERTY		0x0005
+
+/**
+ * pSeries_reconfig_notify - Notifier value structure for OFDT property updates
+ *
+ * @node: Device tree node which owns the property being updated
+ * @property: Updated property
+ */
+struct pSeries_reconfig_prop_update {
+	struct device_node *node;
+	struct property *property;
+};
 
 #ifdef CONFIG_PPC_PSERIES
 extern int pSeries_reconfig_notifier_register(struct notifier_block *);
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 168651a..7b3bf76 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -103,11 +103,13 @@ int pSeries_reconfig_notifier_register(struct notifier_block *nb)
 {
 	return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
 }
+EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register);
 
 void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
 {
 	blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
 }
+EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister);
 
 int pSeries_reconfig_notify(unsigned long action, void *p)
 {
@@ -426,6 +428,7 @@ static int do_remove_property(char *buf, size_t bufsize)
 static int do_update_property(char *buf, size_t bufsize)
 {
 	struct device_node *np;
+	struct pSeries_reconfig_prop_update upd_value;
 	unsigned char *value;
 	char *name, *end, *next_prop;
 	int rc, length;
@@ -454,6 +457,10 @@ static int do_update_property(char *buf, size_t bufsize)
 		return -ENODEV;
 	}
 
+	upd_value.node = np;
+	upd_value.property = newprop;
+	pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
+
 	rc = prom_update_property(np, newprop, oldprop);
 	if (rc)
 		return rc;
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2 07/17] powerpc: crypto: AES-CCM mode routines for nx encryption
From: Kent Yoder @ 2012-04-10 15:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: key, rcj, linuxppc-dev, linux-crypto
In-Reply-To: <1334070249.16827.1.camel@key-ThinkPad-W510>

These routines add support for AES in CCM mode on the Power7+ CPU's
in-Nest accelerator driver.

Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
---
 drivers/crypto/nx/nx-aes-ccm.c |  465 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 465 insertions(+), 0 deletions(-)
 create mode 100644 drivers/crypto/nx/nx-aes-ccm.c

diff --git a/drivers/crypto/nx/nx-aes-ccm.c b/drivers/crypto/nx/nx-aes-ccm.c
new file mode 100644
index 0000000..e418bef
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-ccm.c
@@ -0,0 +1,465 @@
+/**
+ * AES CCM routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/aead.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int ccm_aes_nx_set_key(struct crypto_aead *tfm,
+			      const u8           *in_key,
+			      unsigned int        key_len)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+	struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
+
+	nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+		NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_128);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	csbcpb->cpb.hdr.mode = NX_MODE_AES_CCM;
+	memcpy(csbcpb->cpb.aes_ccm.key, in_key, key_len);
+
+	csbcpb_aead->cpb.hdr.mode = NX_MODE_AES_CCA;
+	memcpy(csbcpb_aead->cpb.aes_cca.key, in_key, key_len);
+
+	return 0;
+
+}
+
+static int ccm4309_aes_nx_set_key(struct crypto_aead *tfm,
+				  const u8           *in_key,
+				  unsigned int        key_len)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+
+	if (key_len < 3)
+		return -EINVAL;
+
+	key_len -= 3;
+
+	memcpy(nx_ctx->priv.ccm.nonce, in_key + key_len, 3);
+
+	return ccm_aes_nx_set_key(tfm, in_key, key_len);
+}
+
+static int ccm_aes_nx_setauthsize(struct crypto_aead *tfm,
+				  unsigned int authsize)
+{
+	switch (authsize) {
+	case 4:
+	case 6:
+	case 8:
+	case 10:
+	case 12:
+	case 14:
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	crypto_aead_crt(tfm)->authsize = authsize;
+
+	return 0;
+}
+
+static int ccm4309_aes_nx_setauthsize(struct crypto_aead *tfm,
+				      unsigned int authsize)
+{
+	switch (authsize) {
+	case 8:
+	case 12:
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	crypto_aead_crt(tfm)->authsize = authsize;
+
+	return 0;
+}
+
+/* taken from crypto/ccm.c */
+static int set_msg_len(u8 *block, unsigned int msglen, int csize)
+{
+	__be32 data;
+
+	memset(block, 0, csize);
+	block += csize;
+
+	if (csize >= 4)
+		csize = 4;
+	else if (msglen > (unsigned int)(1 << (8 * csize)))
+		return -EOVERFLOW;
+
+	data = cpu_to_be32(msglen);
+	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
+
+	return 0;
+}
+
+/* taken from crypto/ccm.c */
+static inline int crypto_ccm_check_iv(const u8 *iv)
+{
+	/* 2 <= L <= 8, so 1 <= L' <= 7. */
+	if (1 > iv[0] || iv[0] > 7)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* based on code from crypto/ccm.c */
+static int generate_b0(u8 *iv, unsigned int assoclen, unsigned int authsize,
+		       unsigned int cryptlen, u8 *b0)
+{
+	unsigned int l, lp, m = authsize;
+	int rc;
+
+	memcpy(b0, iv, 16);
+
+	lp = b0[0];
+	l = lp + 1;
+
+	/* set m, bits 3-5 */
+	*b0 |= (8 * ((m - 2) / 2));
+
+	/* set adata, bit 6, if associated data is used */
+	if (assoclen)
+		*b0 |= 64;
+
+	rc = set_msg_len(b0 + 16 - l, cryptlen, l);
+
+	return rc;
+}
+
+static int generate_pat(u8                   *iv,
+			struct aead_request  *req,
+			struct nx_crypto_ctx *nx_ctx,
+			unsigned int          authsize,
+			unsigned int          nbytes,
+			u8                   *out)
+{
+	struct nx_sg *nx_insg = nx_ctx->in_sg;
+	struct nx_sg *nx_outsg = nx_ctx->out_sg;
+	unsigned int iauth_len = 0;
+	struct vio_pfo_op *op = NULL;
+	u8 tmp[16], *b1 = NULL, *b0 = NULL, *result = NULL;
+	int rc;
+
+	/* zero the ctr value */
+	memset(iv + 15 - iv[0], 0, iv[0] + 1);
+
+	if (!req->assoclen) {
+		b0 = nx_ctx->csbcpb->cpb.aes_ccm.in_pat_or_b0;
+	} else if (req->assoclen <= 14) {
+		/* if associated data is 14 bytes or less, we do 1 GCM
+		 * operation on 2 AES blocks, B0 (stored in the csbcpb) and B1,
+		 * which is fed in through the source buffers here */
+		b0 = nx_ctx->csbcpb->cpb.aes_ccm.in_pat_or_b0;
+		b1 = nx_ctx->priv.ccm.iauth_tag;
+		iauth_len = req->assoclen;
+
+		nx_insg = nx_build_sg_list(nx_insg, b1, 16, nx_ctx->ap->sglen);
+		nx_outsg = nx_build_sg_list(nx_outsg, tmp, 16,
+					    nx_ctx->ap->sglen);
+
+		/* inlen should be negative, indicating to phyp that its a
+		 * pointer to an sg list */
+		nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) *
+					sizeof(struct nx_sg);
+		nx_ctx->op.outlen = (nx_ctx->out_sg - nx_outsg) *
+					sizeof(struct nx_sg);
+
+		NX_CPB_FDM(nx_ctx->csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+		NX_CPB_FDM(nx_ctx->csbcpb) |= NX_FDM_INTERMEDIATE;
+
+		op = &nx_ctx->op;
+		result = nx_ctx->csbcpb->cpb.aes_ccm.out_pat_or_mac;
+	} else if (req->assoclen <= 65280) {
+		/* if associated data is less than (2^16 - 2^8), we construct
+		 * B1 differently and feed in the associated data to a CCA
+		 * operation */
+		b0 = nx_ctx->csbcpb_aead->cpb.aes_cca.b0;
+		b1 = nx_ctx->csbcpb_aead->cpb.aes_cca.b1;
+		iauth_len = 14;
+
+		/* remaining assoc data must have scatterlist built for it */
+		nx_insg = nx_walk_and_build(nx_insg, nx_ctx->ap->sglen,
+					    req->assoc, iauth_len,
+					    req->assoclen - iauth_len);
+		nx_ctx->op_aead.inlen = (nx_ctx->in_sg - nx_insg) *
+						sizeof(struct nx_sg);
+
+		op = &nx_ctx->op_aead;
+		result = nx_ctx->csbcpb_aead->cpb.aes_cca.out_pat_or_b0;
+	} else {
+		/* if associated data is less than (2^32), we construct B1
+		 * differently yet again and feed in the associated data to a
+		 * CCA operation */
+		pr_err("associated data len is %u bytes (returning -EINVAL)\n",
+		       req->assoclen);
+		rc = -EINVAL;
+	}
+
+	rc = generate_b0(iv, req->assoclen, authsize, nbytes, b0);
+	if (rc)
+		goto done;
+
+	if (b1) {
+		memset(b1, 0, 16);
+		*(u16 *)b1 = (u16)req->assoclen;
+
+		scatterwalk_map_and_copy(b1 + 2, req->assoc, 0,
+					 iauth_len, SCATTERWALK_FROM_SG);
+
+		rc = nx_hcall_sync(nx_ctx, op);
+		if (rc)
+			goto done;
+
+		atomic_inc(&(nx_ctx->stats->aes_ops));
+		atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
+
+		memcpy(out, result, AES_BLOCK_SIZE);
+	}
+done:
+	return rc;
+}
+
+static int ccm_nx_decrypt(struct aead_request   *req,
+			  struct blkcipher_desc *desc)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+	unsigned int nbytes = req->cryptlen;
+	unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
+	struct nx_ccm_priv *priv = &nx_ctx->priv.ccm;
+	int rc = -1;
+
+	if (nbytes > nx_ctx->ap->databytelen)
+		return -EINVAL;
+
+	nbytes -= authsize;
+
+	/* copy out the auth tag to compare with later */
+	scatterwalk_map_and_copy(priv->oauth_tag,
+				 req->src, nbytes, authsize,
+				 SCATTERWALK_FROM_SG);
+
+	rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes,
+			  csbcpb->cpb.aes_ccm.in_pat_or_b0);
+	if (rc)
+		goto out;
+
+	rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src, nbytes,
+			       csbcpb->cpb.aes_ccm.iv_or_ctr);
+	if (rc)
+		goto out;
+
+	NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
+	NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_INTERMEDIATE;
+
+	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op);
+	if (rc)
+		goto out;
+
+	atomic_inc(&(nx_ctx->stats->aes_ops));
+	atomic64_add(csbcpb->csb.processed_byte_count,
+		     &(nx_ctx->stats->aes_bytes));
+
+	rc = memcmp(csbcpb->cpb.aes_ccm.out_pat_or_mac, priv->oauth_tag,
+		    authsize) ? -EBADMSG : 0;
+out:
+	return rc;
+}
+
+static int ccm_nx_encrypt(struct aead_request   *req,
+			  struct blkcipher_desc *desc)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+	unsigned int nbytes = req->cryptlen;
+	unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
+	int rc = -1;
+
+	if (nbytes > nx_ctx->ap->databytelen)
+		return -EINVAL;
+
+	rc = generate_pat(desc->info, req, nx_ctx, authsize, nbytes,
+			  csbcpb->cpb.aes_ccm.in_pat_or_b0);
+	if (rc)
+		goto out;
+
+	rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src, nbytes,
+			       csbcpb->cpb.aes_ccm.iv_or_ctr);
+	if (rc)
+		goto out;
+
+	NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+	NX_CPB_FDM(csbcpb) &= ~NX_FDM_INTERMEDIATE;
+
+	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op);
+	if (rc)
+		goto out;
+
+	atomic_inc(&(nx_ctx->stats->aes_ops));
+	atomic64_add(csbcpb->csb.processed_byte_count,
+		     &(nx_ctx->stats->aes_bytes));
+
+	/* copy out the auth tag */
+	scatterwalk_map_and_copy(csbcpb->cpb.aes_ccm.out_pat_or_mac,
+				 req->dst, nbytes, authsize,
+				 SCATTERWALK_TO_SG);
+out:
+	return rc;
+}
+
+static int ccm4309_aes_nx_encrypt(struct aead_request *req)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	struct blkcipher_desc desc;
+	u8 *iv = nx_ctx->priv.ccm.iv;
+
+	iv[0] = 3;
+	memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
+	memcpy(iv + 4, req->iv, 8);
+
+	desc.info = iv;
+	desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+	return ccm_nx_encrypt(req, &desc);
+}
+
+static int ccm_aes_nx_encrypt(struct aead_request *req)
+{
+	struct blkcipher_desc desc;
+	int rc;
+
+	desc.info = req->iv;
+	desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+	rc = crypto_ccm_check_iv(desc.info);
+	if (rc)
+		return rc;
+
+	return ccm_nx_encrypt(req, &desc);
+}
+
+static int ccm4309_aes_nx_decrypt(struct aead_request *req)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	struct blkcipher_desc desc;
+	u8 *iv = nx_ctx->priv.ccm.iv;
+
+	iv[0] = 3;
+	memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
+	memcpy(iv + 4, req->iv, 8);
+
+	desc.info = iv;
+	desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+	return ccm_nx_decrypt(req, &desc);
+}
+
+static int ccm_aes_nx_decrypt(struct aead_request *req)
+{
+	struct blkcipher_desc desc;
+	int rc;
+
+	desc.info = req->iv;
+	desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+	rc = crypto_ccm_check_iv(desc.info);
+	if (rc)
+		return rc;
+
+	return ccm_nx_decrypt(req, &desc);
+}
+
+/* tell the block cipher walk routines that this is a stream cipher by
+ * setting cra_blocksize to 1. Even using blkcipher_walk_virt_block
+ * during encrypt/decrypt doesn't solve this problem, because it calls
+ * blkcipher_walk_done under the covers, which doesn't use walk->blocksize,
+ * but instead uses this tfm->blocksize. */
+struct crypto_alg nx_ccm_aes_alg = {
+	.cra_name        = "ccm(aes)",
+	.cra_driver_name = "ccm-aes-nx",
+	.cra_priority    = 300,
+	.cra_flags       = CRYPTO_ALG_TYPE_AEAD |
+			   CRYPTO_ALG_NEED_FALLBACK,
+	.cra_blocksize   = 1,
+	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+	.cra_type        = &crypto_aead_type,
+	.cra_module      = THIS_MODULE,
+	.cra_list        = LIST_HEAD_INIT(nx_ccm_aes_alg.cra_list),
+	.cra_init        = nx_crypto_ctx_aes_ccm_init,
+	.cra_exit        = nx_crypto_ctx_exit,
+	.cra_aead = {
+		.ivsize      = AES_BLOCK_SIZE,
+		.maxauthsize = AES_BLOCK_SIZE,
+		.setkey      = ccm_aes_nx_set_key,
+		.setauthsize = ccm_aes_nx_setauthsize,
+		.encrypt     = ccm_aes_nx_encrypt,
+		.decrypt     = ccm_aes_nx_decrypt,
+	}
+};
+
+struct crypto_alg nx_ccm4309_aes_alg = {
+	.cra_name        = "rfc4309(ccm(aes))",
+	.cra_driver_name = "rfc4309-ccm-aes-nx",
+	.cra_priority    = 300,
+	.cra_flags       = CRYPTO_ALG_TYPE_AEAD |
+			   CRYPTO_ALG_NEED_FALLBACK,
+	.cra_blocksize   = 1,
+	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+	.cra_type        = &crypto_nivaead_type,
+	.cra_module      = THIS_MODULE,
+	.cra_list        = LIST_HEAD_INIT(nx_ccm4309_aes_alg.cra_list),
+	.cra_init        = nx_crypto_ctx_aes_ccm_init,
+	.cra_exit        = nx_crypto_ctx_exit,
+	.cra_aead = {
+		.ivsize      = 8,
+		.maxauthsize = AES_BLOCK_SIZE,
+		.setkey      = ccm4309_aes_nx_set_key,
+		.setauthsize = ccm4309_aes_nx_setauthsize,
+		.encrypt     = ccm4309_aes_nx_encrypt,
+		.decrypt     = ccm4309_aes_nx_decrypt,
+		.geniv       = "seqiv",
+	}
+};
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2 06/17] powerpc: crypto: AES-CBC mode routines for nx encryption
From: Kent Yoder @ 2012-04-10 15:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: key, rcj, linuxppc-dev, linux-crypto
In-Reply-To: <1334070249.16827.1.camel@key-ThinkPad-W510>

These routines add support for AES in CBC mode on the Power7+ CPU's
in-Nest accelerator driver.

Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
---
 drivers/crypto/nx/nx-aes-cbc.c |  140 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 140 insertions(+), 0 deletions(-)
 create mode 100644 drivers/crypto/nx/nx-aes-cbc.c

diff --git a/drivers/crypto/nx/nx-aes-cbc.c b/drivers/crypto/nx/nx-aes-cbc.c
new file mode 100644
index 0000000..dc3ea12
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-cbc.c
@@ -0,0 +1,140 @@
+/**
+ * AES CBC routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int cbc_aes_nx_set_key(struct crypto_tfm *tfm,
+			      const u8          *in_key,
+			      unsigned int       key_len)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+
+	nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+		break;
+	case AES_KEYSIZE_192:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
+		break;
+	case AES_KEYSIZE_256:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	csbcpb->cpb.hdr.mode = NX_MODE_AES_CBC;
+	memcpy(csbcpb->cpb.aes_cbc.key, in_key, key_len);
+
+	return 0;
+}
+
+static int cbc_aes_nx_crypt(struct blkcipher_desc *desc,
+			    struct scatterlist    *dst,
+			    struct scatterlist    *src,
+			    unsigned int           nbytes,
+			    int                    enc)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+	int rc;
+
+	if (nbytes > nx_ctx->ap->databytelen)
+		return -EINVAL;
+
+	if (enc)
+		NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+	else
+		NX_CPB_FDM(csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
+
+	rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes,
+			       csbcpb->cpb.aes_cbc.iv);
+	if (rc)
+		goto out;
+
+	if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op);
+	if (rc)
+		goto out;
+
+	atomic_inc(&(nx_ctx->stats->aes_ops));
+	atomic64_add(csbcpb->csb.processed_byte_count,
+		     &(nx_ctx->stats->aes_bytes));
+out:
+	return rc;
+}
+
+static int cbc_aes_nx_encrypt(struct blkcipher_desc *desc,
+			      struct scatterlist    *dst,
+			      struct scatterlist    *src,
+			      unsigned int           nbytes)
+{
+	return cbc_aes_nx_crypt(desc, dst, src, nbytes, 1);
+}
+
+static int cbc_aes_nx_decrypt(struct blkcipher_desc *desc,
+			      struct scatterlist    *dst,
+			      struct scatterlist    *src,
+			      unsigned int           nbytes)
+{
+	return cbc_aes_nx_crypt(desc, dst, src, nbytes, 0);
+}
+
+struct crypto_alg nx_cbc_aes_alg = {
+	.cra_name        = "cbc(aes)",
+	.cra_driver_name = "cbc-aes-nx",
+	.cra_priority    = 300,
+	.cra_flags       = CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize   = AES_BLOCK_SIZE,
+	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+	.cra_type        = &crypto_blkcipher_type,
+	.cra_module      = THIS_MODULE,
+	.cra_list        = LIST_HEAD_INIT(nx_cbc_aes_alg.cra_list),
+	.cra_init        = nx_crypto_ctx_aes_cbc_init,
+	.cra_exit        = nx_crypto_ctx_exit,
+	.cra_blkcipher = {
+		.min_keysize = AES_MIN_KEY_SIZE,
+		.max_keysize = AES_MAX_KEY_SIZE,
+		.ivsize      = AES_BLOCK_SIZE,
+		.setkey      = cbc_aes_nx_set_key,
+		.encrypt     = cbc_aes_nx_encrypt,
+		.decrypt     = cbc_aes_nx_decrypt,
+	}
+};
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2 10/17] powerpc: crypto: AES-GCM mode routines for nx encryption
From: Kent Yoder @ 2012-04-10 15:10 UTC (permalink / raw)
  To: linux-kernel; +Cc: key, rcj, linuxppc-dev, linux-crypto
In-Reply-To: <1334070249.16827.1.camel@key-ThinkPad-W510>

These routines add support for AES in GCM mode on the Power7+ CPU's
in-Nest accelerator driver.

Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
---
 drivers/crypto/nx/nx-aes-gcm.c |  353 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 353 insertions(+), 0 deletions(-)
 create mode 100644 drivers/crypto/nx/nx-aes-gcm.c

diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c
new file mode 100644
index 0000000..3c80b81
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-gcm.c
@@ -0,0 +1,353 @@
+/**
+ * AES GCM routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/aead.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int gcm_aes_nx_set_key(struct crypto_aead *tfm,
+			      const u8           *in_key,
+			      unsigned int        key_len)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+	struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
+
+	nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+		NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_128);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+		break;
+	case AES_KEYSIZE_192:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
+		NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_192);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
+		break;
+	case AES_KEYSIZE_256:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
+		NX_CPB_SET_KEY_SIZE(csbcpb_aead, NX_KS_AES_256);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	csbcpb->cpb.hdr.mode = NX_MODE_AES_GCM;
+	memcpy(csbcpb->cpb.aes_gcm.key, in_key, key_len);
+
+	csbcpb_aead->cpb.hdr.mode = NX_MODE_AES_GCA;
+	memcpy(csbcpb_aead->cpb.aes_gca.key, in_key, key_len);
+
+	return 0;
+}
+
+static int gcm4106_aes_nx_set_key(struct crypto_aead *tfm,
+				  const u8           *in_key,
+				  unsigned int        key_len)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&tfm->base);
+	char *nonce = nx_ctx->priv.gcm.nonce;
+	int rc;
+
+	if (key_len < 4)
+		return -EINVAL;
+
+	key_len -= 4;
+
+	rc = gcm_aes_nx_set_key(tfm, in_key, key_len);
+	if (rc)
+		goto out;
+
+	memcpy(nonce, in_key + key_len, 4);
+out:
+	return rc;
+}
+
+static int gcm_aes_nx_setauthsize(struct crypto_aead *tfm,
+				  unsigned int authsize)
+{
+	if (authsize > crypto_aead_alg(tfm)->maxauthsize)
+		return -EINVAL;
+
+	crypto_aead_crt(tfm)->authsize = authsize;
+
+	return 0;
+}
+
+static int gcm4106_aes_nx_setauthsize(struct crypto_aead *tfm,
+				      unsigned int authsize)
+{
+	switch (authsize) {
+	case 8:
+	case 12:
+	case 16:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	crypto_aead_crt(tfm)->authsize = authsize;
+
+	return 0;
+}
+
+static int nx_gca(struct nx_crypto_ctx  *nx_ctx,
+		  struct scatterlist    *assoc,
+		  unsigned int           assoclen,
+		  u8                    *out)
+{
+	struct nx_csbcpb *csbcpb_aead = nx_ctx->csbcpb_aead;
+	int rc = -EINVAL;
+	struct scatter_walk walk;
+	struct nx_sg *nx_sg = nx_ctx->in_sg;
+
+	if (assoclen > nx_ctx->ap->databytelen)
+		goto out;
+
+	if (assoclen <= AES_BLOCK_SIZE) {
+		scatterwalk_start(&walk, assoc);
+		scatterwalk_copychunks(out, &walk, assoclen,
+				       SCATTERWALK_FROM_SG);
+		scatterwalk_done(&walk, SCATTERWALK_FROM_SG, 0);
+
+		rc = 0;
+		goto out;
+	}
+
+	nx_sg = nx_walk_and_build(nx_sg, nx_ctx->ap->sglen, assoc, 0,
+				  assoclen);
+	nx_ctx->op_aead.inlen = (nx_ctx->in_sg - nx_sg) * sizeof(struct nx_sg);
+
+	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op_aead);
+	if (rc)
+		goto out;
+
+	atomic_inc(&(nx_ctx->stats->aes_ops));
+	atomic64_add(assoclen, &(nx_ctx->stats->aes_bytes));
+
+	memcpy(out, csbcpb_aead->cpb.aes_gca.out_pat, AES_BLOCK_SIZE);
+out:
+	return rc;
+}
+
+static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+	struct blkcipher_desc desc;
+	unsigned int nbytes = req->cryptlen;
+	int rc = -EINVAL;
+
+	if (nbytes > nx_ctx->ap->databytelen)
+		goto out;
+
+	desc.info = nx_ctx->priv.gcm.iv;
+	/* initialize the counter */
+	*(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1;
+
+	/* For scenarios where the input message is zero length, AES CTR mode
+	 * may be used. Set the source data to be a single block (16B) of all
+	 * zeros, and set the input IV value to be the same as the GMAC IV
+	 * value. - nx_wb 4.8.1.3 */
+	if (nbytes == 0) {
+		char src[AES_BLOCK_SIZE] = {};
+		struct scatterlist sg;
+
+		desc.tfm = crypto_alloc_blkcipher("ctr(aes)", 0, 0);
+		if (IS_ERR(desc.tfm)) {
+			rc = -ENOMEM;
+			goto out;
+		}
+
+		crypto_blkcipher_setkey(desc.tfm, csbcpb->cpb.aes_gcm.key,
+			NX_CPB_KEY_SIZE(csbcpb) == NX_KS_AES_128 ? 16 :
+			NX_CPB_KEY_SIZE(csbcpb) == NX_KS_AES_192 ? 24 : 32);
+
+		sg_init_one(&sg, src, AES_BLOCK_SIZE);
+		if (enc)
+			crypto_blkcipher_encrypt_iv(&desc, req->dst, &sg,
+						    AES_BLOCK_SIZE);
+		else
+			crypto_blkcipher_decrypt_iv(&desc, req->dst, &sg,
+						    AES_BLOCK_SIZE);
+		crypto_free_blkcipher(desc.tfm);
+
+		rc = 0;
+		goto out;
+	}
+
+	desc.tfm = (struct crypto_blkcipher *)req->base.tfm;
+
+	csbcpb->cpb.aes_gcm.bit_length_aad = req->assoclen * 8;
+
+	if (req->assoclen) {
+		rc = nx_gca(nx_ctx, req->assoc, req->assoclen,
+			    csbcpb->cpb.aes_gcm.in_pat_or_aad);
+		if (rc)
+			goto out;
+	}
+
+	if (enc)
+		NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+	else
+		nbytes -= AES_BLOCK_SIZE;
+
+	csbcpb->cpb.aes_gcm.bit_length_data = nbytes * 8;
+
+	rc = nx_build_sg_lists(nx_ctx, &desc, req->dst, req->src, nbytes,
+			       csbcpb->cpb.aes_gcm.iv_or_cnt);
+	if (rc)
+		goto out;
+
+	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op);
+	if (rc)
+		goto out;
+
+	atomic_inc(&(nx_ctx->stats->aes_ops));
+	atomic64_add(csbcpb->csb.processed_byte_count,
+		     &(nx_ctx->stats->aes_bytes));
+
+	if (enc) {
+		/* copy out the auth tag */
+		scatterwalk_map_and_copy(csbcpb->cpb.aes_gcm.out_pat_or_mac,
+				 req->dst, nbytes,
+				 crypto_aead_authsize(crypto_aead_reqtfm(req)),
+				 SCATTERWALK_TO_SG);
+	} else if (req->assoclen) {
+		u8 *itag = nx_ctx->priv.gcm.iauth_tag;
+		u8 *otag = csbcpb->cpb.aes_gcm.out_pat_or_mac;
+
+		scatterwalk_map_and_copy(itag, req->dst, nbytes,
+				 crypto_aead_authsize(crypto_aead_reqtfm(req)),
+				 SCATTERWALK_FROM_SG);
+		rc = memcmp(itag, otag,
+			    crypto_aead_authsize(crypto_aead_reqtfm(req))) ?
+		     -EBADMSG : 0;
+	}
+out:
+	return rc;
+}
+
+static int gcm_aes_nx_encrypt(struct aead_request *req)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	char *iv = nx_ctx->priv.gcm.iv;
+
+	memcpy(iv, req->iv, 12);
+
+	return gcm_aes_nx_crypt(req, 1);
+}
+
+static int gcm_aes_nx_decrypt(struct aead_request *req)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	char *iv = nx_ctx->priv.gcm.iv;
+
+	memcpy(iv, req->iv, 12);
+
+	return gcm_aes_nx_crypt(req, 0);
+}
+
+static int gcm4106_aes_nx_encrypt(struct aead_request *req)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	char *iv = nx_ctx->priv.gcm.iv;
+	char *nonce = nx_ctx->priv.gcm.nonce;
+
+	memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
+	memcpy(iv + NX_GCM4106_NONCE_LEN, req->iv, 8);
+
+	return gcm_aes_nx_crypt(req, 1);
+}
+
+static int gcm4106_aes_nx_decrypt(struct aead_request *req)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
+	char *iv = nx_ctx->priv.gcm.iv;
+	char *nonce = nx_ctx->priv.gcm.nonce;
+
+	memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
+	memcpy(iv + NX_GCM4106_NONCE_LEN, req->iv, 8);
+
+	return gcm_aes_nx_crypt(req, 0);
+}
+
+/* tell the block cipher walk routines that this is a stream cipher by
+ * setting cra_blocksize to 1. Even using blkcipher_walk_virt_block
+ * during encrypt/decrypt doesn't solve this problem, because it calls
+ * blkcipher_walk_done under the covers, which doesn't use walk->blocksize,
+ * but instead uses this tfm->blocksize. */
+struct crypto_alg nx_gcm_aes_alg = {
+	.cra_name        = "gcm(aes)",
+	.cra_driver_name = "gcm-aes-nx",
+	.cra_priority    = 300,
+	.cra_flags       = CRYPTO_ALG_TYPE_AEAD,
+	.cra_blocksize   = 1,
+	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+	.cra_type        = &crypto_aead_type,
+	.cra_module      = THIS_MODULE,
+	.cra_list        = LIST_HEAD_INIT(nx_gcm_aes_alg.cra_list),
+	.cra_init        = nx_crypto_ctx_aes_gcm_init,
+	.cra_exit        = nx_crypto_ctx_exit,
+	.cra_aead = {
+		.ivsize      = AES_BLOCK_SIZE,
+		.maxauthsize = AES_BLOCK_SIZE,
+		.setkey      = gcm_aes_nx_set_key,
+		.setauthsize = gcm_aes_nx_setauthsize,
+		.encrypt     = gcm_aes_nx_encrypt,
+		.decrypt     = gcm_aes_nx_decrypt,
+	}
+};
+
+struct crypto_alg nx_gcm4106_aes_alg = {
+	.cra_name        = "rfc4106(gcm(aes))",
+	.cra_driver_name = "rfc4106-gcm-aes-nx",
+	.cra_priority    = 300,
+	.cra_flags       = CRYPTO_ALG_TYPE_AEAD,
+	.cra_blocksize   = 1,
+	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+	.cra_type        = &crypto_nivaead_type,
+	.cra_module      = THIS_MODULE,
+	.cra_list        = LIST_HEAD_INIT(nx_gcm4106_aes_alg.cra_list),
+	.cra_init        = nx_crypto_ctx_aes_gcm_init,
+	.cra_exit        = nx_crypto_ctx_exit,
+	.cra_aead = {
+		.ivsize      = 8,
+		.maxauthsize = AES_BLOCK_SIZE,
+		.geniv       = "seqiv",
+		.setkey      = gcm4106_aes_nx_set_key,
+		.setauthsize = gcm4106_aes_nx_setauthsize,
+		.encrypt     = gcm4106_aes_nx_encrypt,
+		.decrypt     = gcm4106_aes_nx_decrypt,
+	}
+};
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2 08/17] powerpc: crypto: AES-CTR mode routines for nx encryption
From: Kent Yoder @ 2012-04-10 15:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: key, rcj, linuxppc-dev, linux-crypto
In-Reply-To: <1334070249.16827.1.camel@key-ThinkPad-W510>

These routines add support for AES in CTR mode on the Power7+ CPU's
in-Nest accelerator driver.

Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
---
 drivers/crypto/nx/nx-aes-ctr.c |  177 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 177 insertions(+), 0 deletions(-)
 create mode 100644 drivers/crypto/nx/nx-aes-ctr.c

diff --git a/drivers/crypto/nx/nx-aes-ctr.c b/drivers/crypto/nx/nx-aes-ctr.c
new file mode 100644
index 0000000..141079c
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-ctr.c
@@ -0,0 +1,177 @@
+/**
+ * AES CTR routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/aes.h>
+#include <crypto/ctr.h>
+#include <crypto/algapi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int ctr_aes_nx_set_key(struct crypto_tfm *tfm,
+			      const u8          *in_key,
+			      unsigned int       key_len)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+
+	nx_ctx_init(nx_ctx, HCOP_FC_AES);
+
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_128];
+		break;
+	case AES_KEYSIZE_192:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_192];
+		break;
+	case AES_KEYSIZE_256:
+		NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
+		nx_ctx->ap = &nx_ctx->props[NX_PROPS_AES_256];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	csbcpb->cpb.hdr.mode = NX_MODE_AES_CTR;
+	memcpy(csbcpb->cpb.aes_ctr.key, in_key, key_len);
+
+	return 0;
+}
+
+static int ctr3686_aes_nx_set_key(struct crypto_tfm *tfm,
+				  const u8          *in_key,
+				  unsigned int       key_len)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+
+	if (key_len < CTR_RFC3686_NONCE_SIZE)
+		return -EINVAL;
+
+	memcpy(nx_ctx->priv.ctr.iv,
+	       in_key + key_len - CTR_RFC3686_NONCE_SIZE,
+	       CTR_RFC3686_NONCE_SIZE);
+
+	key_len -= CTR_RFC3686_NONCE_SIZE;
+
+	return ctr_aes_nx_set_key(tfm, in_key, key_len);
+}
+
+static int ctr_aes_nx_crypt(struct blkcipher_desc *desc,
+			    struct scatterlist    *dst,
+			    struct scatterlist    *src,
+			    unsigned int           nbytes)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
+	int rc;
+
+	if (nbytes > nx_ctx->ap->databytelen)
+		return -EINVAL;
+
+	rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes,
+			       csbcpb->cpb.aes_ctr.iv);
+	if (rc)
+		goto out;
+
+	if (!nx_ctx->op.inlen || !nx_ctx->op.outlen) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	rc = nx_hcall_sync(nx_ctx, &nx_ctx->op);
+	if (rc)
+		goto out;
+
+	atomic_inc(&(nx_ctx->stats->aes_ops));
+	atomic64_add(csbcpb->csb.processed_byte_count,
+		     &(nx_ctx->stats->aes_bytes));
+out:
+	return rc;
+}
+
+static int ctr3686_aes_nx_crypt(struct blkcipher_desc *desc,
+				struct scatterlist    *dst,
+				struct scatterlist    *src,
+				unsigned int           nbytes)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
+	u8 *iv = nx_ctx->priv.ctr.iv;
+
+	memcpy(iv + CTR_RFC3686_NONCE_SIZE,
+	       desc->info, CTR_RFC3686_IV_SIZE);
+	iv[15] = 1;
+
+	desc->info = nx_ctx->priv.ctr.iv;
+
+	return ctr_aes_nx_crypt(desc, dst, src, nbytes);
+}
+
+struct crypto_alg nx_ctr_aes_alg = {
+	.cra_name        = "ctr(aes)",
+	.cra_driver_name = "ctr-aes-nx",
+	.cra_priority    = 300,
+	.cra_flags       = CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize   = 1,
+	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+	.cra_type        = &crypto_blkcipher_type,
+	.cra_module      = THIS_MODULE,
+	.cra_list        = LIST_HEAD_INIT(nx_ctr_aes_alg.cra_list),
+	.cra_init        = nx_crypto_ctx_aes_ctr_init,
+	.cra_exit        = nx_crypto_ctx_exit,
+	.cra_blkcipher = {
+		.min_keysize = AES_MIN_KEY_SIZE,
+		.max_keysize = AES_MAX_KEY_SIZE,
+		.ivsize      = AES_BLOCK_SIZE,
+		.setkey      = ctr_aes_nx_set_key,
+		.encrypt     = ctr_aes_nx_crypt,
+		.decrypt     = ctr_aes_nx_crypt,
+	}
+};
+
+struct crypto_alg nx_ctr3686_aes_alg = {
+	.cra_name        = "rfc3686(ctr(aes))",
+	.cra_driver_name = "rfc3686-ctr-aes-nx",
+	.cra_priority    = 300,
+	.cra_flags       = CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize   = 1,
+	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+	.cra_type        = &crypto_blkcipher_type,
+	.cra_module      = THIS_MODULE,
+	.cra_list        = LIST_HEAD_INIT(nx_ctr3686_aes_alg.cra_list),
+	.cra_init        = nx_crypto_ctx_aes_ctr_init,
+	.cra_exit        = nx_crypto_ctx_exit,
+	.cra_blkcipher = {
+		.min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
+		.max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE,
+		.ivsize      = CTR_RFC3686_IV_SIZE,
+		.geniv       = "seqiv",
+		.setkey      = ctr3686_aes_nx_set_key,
+		.encrypt     = ctr3686_aes_nx_crypt,
+		.decrypt     = ctr3686_aes_nx_crypt,
+	}
+};
-- 
1.7.1

^ permalink raw reply related

* [PATCH v2 14/17] powerpc: crypto: nx driver code supporting nx encryption
From: Kent Yoder @ 2012-04-10 15:10 UTC (permalink / raw)
  To: linux-kernel; +Cc: key, rcj, linuxppc-dev, linux-crypto
In-Reply-To: <1334070249.16827.1.camel@key-ThinkPad-W510>

These routines add the base device driver code supporting the Power7+
in-Nest encryption accelerator (nx) device.

Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
---
 drivers/crypto/nx/nx.c        |  711 +++++++++++++++++++++++++++++++++++++++++
 drivers/crypto/nx/nx.h        |  192 +++++++++++
 drivers/crypto/nx/nx_csbcpb.h |  205 ++++++++++++
 3 files changed, 1108 insertions(+), 0 deletions(-)
 create mode 100644 drivers/crypto/nx/nx.c
 create mode 100644 drivers/crypto/nx/nx.h
 create mode 100644 drivers/crypto/nx/nx_csbcpb.h

diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
new file mode 100644
index 0000000..9371272
--- /dev/null
+++ b/drivers/crypto/nx/nx.c
@@ -0,0 +1,711 @@
+/**
+ * Routines supporting the Power 7+ Nest Accelerators driver
+ *
+ * Copyright (C) 2011-2012 International Business Machines Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 only.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Kent Yoder <yoder1@us.ibm.com>
+ */
+
+#include <crypto/internal/hash.h>
+#include <crypto/hash.h>
+#include <crypto/aes.h>
+#include <crypto/sha.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <asm/pSeries_reconfig.h>
+#include <asm/abs_addr.h>
+#include <asm/hvcall.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+/**
+ * nx_hcall_sync - make an H_COP_OP hcall for the passed in op structure
+ *
+ * @nx_ctx: the crypto context handle
+ * @op: PFO operation struct to pass in
+ *
+ * Make the hcall, retrying while the hardware is busy
+ */
+int nx_hcall_sync(struct nx_crypto_ctx *nx_ctx, struct vio_pfo_op *op)
+{
+	int rc;
+	struct vio_dev *viodev = nx_driver.viodev;
+
+	atomic_inc(&(nx_ctx->stats->sync_ops));
+
+	do {
+		rc = vio_h_cop_sync(viodev, op);
+	} while (rc == -EBUSY);
+
+	if (rc) {
+		dev_dbg(&viodev->dev, "vio_h_cop_sync failed: rc: %d "
+			"hcall rc: %ld\n", rc, op->hcall_err);
+		atomic_inc(&(nx_ctx->stats->errors));
+		atomic_set(&(nx_ctx->stats->last_error), op->hcall_err);
+		atomic_set(&(nx_ctx->stats->last_error_pid), current->pid);
+	}
+
+	return rc;
+}
+
+/**
+ * nx_build_sg_list - build an NX scatter list describing a single  buffer
+ *
+ * @sg_head: pointer to the first scatter list element to build
+ * @start_addr: pointer to the linear buffer
+ * @len: length of the data at @start_addr
+ * @sgmax: the largest number of scatter list elements we're allowed to create
+ *
+ * This function will start writing nx_sg elements at @sg_head and keep
+ * writing them until all of the data from @start_addr is described or
+ * until sgmax elements have been written. Scatter list elements will be
+ * created such that none of the elements describes a buffer that crosses a 4K
+ * boundary.
+ */
+struct nx_sg *nx_build_sg_list(struct nx_sg *sg_head,
+			       u8           *start_addr,
+			       unsigned int  len,
+			       u32           sgmax)
+{
+	unsigned int sg_len = 0;
+	struct nx_sg *sg;
+	u64 sg_addr = (u64)start_addr;
+	u64 end_addr;
+
+	/* determine the start and end for this address range - slightly
+	 * different if this is in VMALLOC_REGION */
+	if (is_vmalloc_addr(start_addr))
+		sg_addr = phys_to_abs(page_to_phys(vmalloc_to_page(start_addr)))
+			  + offset_in_page(sg_addr);
+	else
+		sg_addr = virt_to_abs(sg_addr);
+
+	end_addr = sg_addr + len;
+
+	/* each iteration will write one struct nx_sg element and add the
+	 * length of data described by that element to sg_len. Once @len bytes
+	 * have been described (or @sgmax elements have been written), the
+	 * loop ends. min_t is used to ensure @end_addr falls on the same page
+	 * as sg_addr, if not, we need to create another nx_sg element for the
+	 * data on the next page */
+	for (sg = sg_head; sg_len < len; sg++) {
+		sg->addr = sg_addr;
+		sg_addr = min_t(u64, NX_PAGE_NUM(sg_addr + NX_PAGE_SIZE), end_addr);
+		sg->len = sg_addr - sg->addr;
+		sg_len += sg->len;
+
+		if ((sg - sg_head) == sgmax) {
+			pr_err("nx: scatter/gather list overflow, pid: %d\n",
+			       current->pid);
+			return NULL;
+		}
+	}
+
+	/* return the moved sg_head pointer */
+	return sg;
+}
+
+/**
+ * nx_walk_and_build - walk a linux scatterlist and build an nx scatterlist
+ *
+ * @nx_dst: pointer to the first nx_sg element to write
+ * @sglen: max number of nx_sg entries we're allowed to write
+ * @sg_src: pointer to the source linux scatterlist to walk
+ * @start: number of bytes to fast-forward past at the beginning of @sg_src
+ * @src_len: number of bytes to walk in @sg_src
+ */
+struct nx_sg *nx_walk_and_build(struct nx_sg       *nx_dst,
+				unsigned int        sglen,
+				struct scatterlist *sg_src,
+				unsigned int        start,
+				unsigned int        src_len)
+{
+	struct scatter_walk walk;
+	struct nx_sg *nx_sg = nx_dst;
+	unsigned int n, offset = 0, len = src_len;
+	char *dst;
+
+	/* we need to fast forward through @start bytes first */
+	for (;;) {
+		scatterwalk_start(&walk, sg_src);
+
+		if (start < offset + sg_src->length)
+			break;
+
+		offset += sg_src->length;
+		sg_src = scatterwalk_sg_next(sg_src);
+	}
+
+	/* start - offset is the number of bytes to advance in the scatterlist
+	 * element we're currently looking at */
+	scatterwalk_advance(&walk, start - offset);
+
+	while (len && nx_sg) {
+		n = scatterwalk_clamp(&walk, len);
+		if (!n) {
+			scatterwalk_start(&walk, sg_next(walk.sg));
+			n = scatterwalk_clamp(&walk, len);
+		}
+		dst = scatterwalk_map(&walk);
+
+		nx_sg = nx_build_sg_list(nx_sg, dst, n, sglen);
+		len -= n;
+
+		scatterwalk_unmap(dst);
+		scatterwalk_advance(&walk, n);
+		scatterwalk_done(&walk, SCATTERWALK_FROM_SG, len);
+	}
+
+	/* return the moved destination pointer */
+	return nx_sg;
+}
+
+/**
+ * nx_build_sg_lists - walk the input scatterlists and build arrays of NX
+ *                     scatterlists based on them.
+ *
+ * @nx_ctx: NX crypto context for the lists we're building
+ * @desc: the block cipher descriptor for the operation
+ * @dst: destination scatterlist
+ * @src: source scatterlist
+ * @nbytes: length of data described in the scatterlists
+ * @iv: destination for the iv data, if the algorithm requires it
+ *
+ * This is common code shared by all the AES algorithms. It uses the block
+ * cipher walk routines to traverse input and output scatterlists, building
+ * corresponding NX scatterlists
+ */
+int nx_build_sg_lists(struct nx_crypto_ctx  *nx_ctx,
+		      struct blkcipher_desc *desc,
+		      struct scatterlist    *dst,
+		      struct scatterlist    *src,
+		      unsigned int           nbytes,
+		      u8                    *iv)
+{
+	struct nx_sg *nx_insg = nx_ctx->in_sg;
+	struct nx_sg *nx_outsg = nx_ctx->out_sg;
+	struct blkcipher_walk walk;
+	int rc;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	rc = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+	if (rc)
+		goto out;
+
+	if (iv)
+		memcpy(iv, walk.iv, AES_BLOCK_SIZE);
+
+	while (walk.nbytes) {
+		nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
+					   walk.nbytes, nx_ctx->ap->sglen);
+		nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
+					    walk.nbytes, nx_ctx->ap->sglen);
+
+		rc = blkcipher_walk_done(desc, &walk, 0);
+		if (rc)
+			break;
+	}
+
+	if (walk.nbytes) {
+		nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
+					   walk.nbytes, nx_ctx->ap->sglen);
+		nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
+					    walk.nbytes, nx_ctx->ap->sglen);
+
+		rc = 0;
+	}
+
+	/* these lengths should be negative, which will indicate to phyp that
+	 * the input and output parameters are scatterlists, not linear
+	 * buffers */
+	nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) * sizeof(struct nx_sg);
+	nx_ctx->op.outlen = (nx_ctx->out_sg - nx_outsg) * sizeof(struct nx_sg);
+out:
+	return rc;
+}
+
+/**
+ * nx_ctx_init - initialize an nx_ctx's vio_pfo_op struct
+ *
+ * @nx_ctx: the nx context to initialize
+ * @function: the function code for the op
+ */
+void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function)
+{
+	memset(nx_ctx->kmem, 0, nx_ctx->kmem_len);
+	nx_ctx->csbcpb->csb.valid |= NX_CSB_VALID_BIT;
+
+	nx_ctx->op.flags = function;
+	nx_ctx->op.csbcpb = virt_to_abs(nx_ctx->csbcpb);
+	nx_ctx->op.in = virt_to_abs(nx_ctx->in_sg);
+	nx_ctx->op.out = virt_to_abs(nx_ctx->out_sg);
+
+	if (nx_ctx->csbcpb_aead) {
+		nx_ctx->csbcpb_aead->csb.valid |= NX_CSB_VALID_BIT;
+
+		nx_ctx->op_aead.flags = function;
+		nx_ctx->op_aead.csbcpb = virt_to_abs(nx_ctx->csbcpb_aead);
+		nx_ctx->op_aead.in = virt_to_abs(nx_ctx->in_sg);
+		nx_ctx->op_aead.out = virt_to_abs(nx_ctx->out_sg);
+	}
+}
+
+static void nx_of_update_status(struct device   *dev,
+			       struct property *p,
+			       struct nx_of    *props)
+{
+	if (!strncmp(p->value, "okay", p->length)) {
+		props->status = NX_WAITING;
+		props->flags |= NX_OF_FLAG_STATUS_SET;
+	} else {
+		dev_info(dev, "%s: status '%s' is not 'okay'\n", __func__,
+			 (char *)p->value);
+	}
+}
+
+static void nx_of_update_sglen(struct device   *dev,
+			       struct property *p,
+			       struct nx_of    *props)
+{
+	if (p->length != sizeof(props->max_sg_len)) {
+		dev_err(dev, "%s: unexpected format for "
+			"ibm,max-sg-len property\n", __func__);
+		dev_dbg(dev, "%s: ibm,max-sg-len is %d bytes "
+			"long, expected %zd bytes\n", __func__,
+			p->length, sizeof(props->max_sg_len));
+		return;
+	}
+
+	props->max_sg_len = *(u32 *)p->value;
+	props->flags |= NX_OF_FLAG_MAXSGLEN_SET;
+}
+
+static void nx_of_update_msc(struct device   *dev,
+			     struct property *p,
+			     struct nx_of    *props)
+{
+	struct msc_triplet *trip;
+	struct max_sync_cop *msc;
+	unsigned int bytes_so_far, i, lenp;
+
+	msc = (struct max_sync_cop *)p->value;
+	lenp = p->length;
+
+	/* You can't tell if the data read in for this property is sane by its
+	 * size alone. This is because there are sizes embedded in the data
+	 * structure. The best we can do is check lengths as we parse and bail
+	 * as soon as a length error is detected. */
+	bytes_so_far = 0;
+
+	while ((bytes_so_far + sizeof(struct max_sync_cop)) <= lenp) {
+		bytes_so_far += sizeof(struct max_sync_cop);
+
+		trip = msc->trip;
+
+		for (i = 0;
+		     ((bytes_so_far + sizeof(struct msc_triplet)) <= lenp) &&
+		     i < msc->triplets;
+		     i++) {
+			if (msc->fc > NX_MAX_FC || msc->mode > NX_MAX_MODE) {
+				dev_err(dev, "unknown function code/mode "
+					"combo: %d/%d (ignored)\n", msc->fc,
+					msc->mode);
+				goto next_loop;
+			}
+
+			switch (trip->keybitlen) {
+			case 128:
+			case 160:
+				props->ap[msc->fc][msc->mode][0].databytelen =
+					trip->databytelen;
+				props->ap[msc->fc][msc->mode][0].sglen =
+					trip->sglen;
+				break;
+			case 192:
+				props->ap[msc->fc][msc->mode][1].databytelen =
+					trip->databytelen;
+				props->ap[msc->fc][msc->mode][1].sglen =
+					trip->sglen;
+				break;
+			case 256:
+				if (msc->fc == NX_FC_AES) {
+					props->ap[msc->fc][msc->mode][2].
+						databytelen = trip->databytelen;
+					props->ap[msc->fc][msc->mode][2].sglen =
+						trip->sglen;
+				} else if (msc->fc == NX_FC_AES_HMAC ||
+					   msc->fc == NX_FC_SHA) {
+					props->ap[msc->fc][msc->mode][1].
+						databytelen = trip->databytelen;
+					props->ap[msc->fc][msc->mode][1].sglen =
+						trip->sglen;
+				} else {
+					dev_warn(dev, "unknown function "
+						"code/key bit len combo"
+						": (%u/256)\n", msc->fc);
+				}
+				break;
+			case 512:
+				props->ap[msc->fc][msc->mode][2].databytelen =
+					trip->databytelen;
+				props->ap[msc->fc][msc->mode][2].sglen =
+					trip->sglen;
+				break;
+			default:
+				dev_warn(dev, "unknown function code/key bit "
+					 "len combo: (%u/%u)\n", msc->fc,
+					 trip->keybitlen);
+				break;
+			}
+next_loop:
+			bytes_so_far += sizeof(struct msc_triplet);
+			trip++;
+		}
+
+		msc = (struct max_sync_cop *)trip;
+	}
+
+	props->flags |= NX_OF_FLAG_MAXSYNCCOP_SET;
+}
+
+/**
+ * nx_of_init - read openFirmware values from the device tree
+ *
+ * @dev: device handle
+ * @props: pointer to struct to hold the properties values
+ *
+ * Called once at driver probe time, this function will read out the
+ * openFirmware properties we use at runtime. If all the OF properties are
+ * acceptable, when we exit this function props->flags will indicate that
+ * we're ready to register our crypto algorithms.
+ */
+static void nx_of_init(struct device *dev, struct nx_of *props)
+{
+	struct device_node *base_node = dev->of_node;
+	struct property *p;
+
+	p = of_find_property(base_node, "status", NULL);
+	if (!p)
+		dev_info(dev, "%s: property 'status' not found\n", __func__);
+	else
+		nx_of_update_status(dev, p, props);
+
+	p = of_find_property(base_node, "ibm,max-sg-len", NULL);
+	if (!p)
+		dev_info(dev, "%s: property 'ibm,max-sg-len' not found\n",
+			 __func__);
+	else
+		nx_of_update_sglen(dev, p, props);
+
+	p = of_find_property(base_node, "ibm,max-sync-cop", NULL);
+	if (!p)
+		dev_info(dev, "%s: property 'ibm,max-sync-cop' not found\n",
+			 __func__);
+	else
+		nx_of_update_msc(dev, p, props);
+}
+
+/**
+ * nx_register_algs - register algorithms with the crypto API
+ *
+ * Called from nx_probe()
+ *
+ * If all OF properties are in an acceptable state, the driver flags will
+ * indicate that we're ready and we'll create our debugfs files and register
+ * out crypto algorithms.
+ */
+static int nx_register_algs(void)
+{
+	int rc = -1;
+
+	if (nx_driver.of.flags != NX_OF_FLAG_MASK_READY)
+		goto out;
+
+	memset(&nx_driver.stats, 0, sizeof(struct nx_stats));
+
+	rc = NX_DEBUGFS_INIT(&nx_driver);
+	if (rc)
+		goto out;
+
+	rc = crypto_register_alg(&nx_ecb_aes_alg);
+	if (rc)
+		goto out;
+
+	rc = crypto_register_alg(&nx_cbc_aes_alg);
+	if (rc)
+		goto out_unreg_ecb;
+
+	rc = crypto_register_alg(&nx_ctr_aes_alg);
+	if (rc)
+		goto out_unreg_cbc;
+
+	rc = crypto_register_alg(&nx_ctr3686_aes_alg);
+	if (rc)
+		goto out_unreg_ctr;
+
+	rc = crypto_register_alg(&nx_gcm_aes_alg);
+	if (rc)
+		goto out_unreg_ctr3686;
+
+	rc = crypto_register_alg(&nx_gcm4106_aes_alg);
+	if (rc)
+		goto out_unreg_gcm;
+
+	rc = crypto_register_alg(&nx_ccm_aes_alg);
+	if (rc)
+		goto out_unreg_gcm4106;
+
+	rc = crypto_register_alg(&nx_ccm4309_aes_alg);
+	if (rc)
+		goto out_unreg_ccm;
+
+	rc = crypto_register_shash(&nx_shash_sha256_alg);
+	if (rc)
+		goto out_unreg_ccm4309;
+
+	rc = crypto_register_shash(&nx_shash_sha512_alg);
+	if (rc)
+		goto out_unreg_s256;
+
+	rc = crypto_register_shash(&nx_shash_aes_xcbc_alg);
+	if (rc)
+		goto out_unreg_s512;
+
+	nx_driver.of.status = NX_OKAY;
+
+	goto out;
+
+out_unreg_s512:
+	crypto_unregister_shash(&nx_shash_sha512_alg);
+out_unreg_s256:
+	crypto_unregister_shash(&nx_shash_sha256_alg);
+out_unreg_ccm4309:
+	crypto_unregister_alg(&nx_ccm4309_aes_alg);
+out_unreg_ccm:
+	crypto_unregister_alg(&nx_ccm_aes_alg);
+out_unreg_gcm4106:
+	crypto_unregister_alg(&nx_gcm4106_aes_alg);
+out_unreg_gcm:
+	crypto_unregister_alg(&nx_gcm_aes_alg);
+out_unreg_ctr3686:
+	crypto_unregister_alg(&nx_ctr3686_aes_alg);
+out_unreg_ctr:
+	crypto_unregister_alg(&nx_ctr_aes_alg);
+out_unreg_cbc:
+	crypto_unregister_alg(&nx_cbc_aes_alg);
+out_unreg_ecb:
+	crypto_unregister_alg(&nx_ecb_aes_alg);
+out:
+	return rc;
+}
+
+/**
+ * nx_crypto_ctx_init - create and initialize a crypto api context
+ *
+ * @nx_ctx: the crypto api context
+ * @fc: function code for the context
+ * @mode: the function code specific mode for this context
+ */
+static int nx_crypto_ctx_init(struct nx_crypto_ctx *nx_ctx, u32 fc, u32 mode)
+{
+	if (nx_driver.of.status != NX_OKAY) {
+		pr_err("Attempt to initialize NX crypto context while device "
+		       "is not available!\n");
+		return -ENODEV;
+	}
+
+	/* we need an extra page for csbcpb_aead for these modes */
+	if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
+		nx_ctx->kmem_len = (4 * NX_PAGE_SIZE) +
+				   sizeof(struct nx_csbcpb);
+	else
+		nx_ctx->kmem_len = (3 * NX_PAGE_SIZE) +
+				   sizeof(struct nx_csbcpb);
+
+	nx_ctx->kmem = kmalloc(nx_ctx->kmem_len, GFP_KERNEL);
+	if (!nx_ctx->kmem)
+		return -ENOMEM;
+
+	/* the csbcpb and scatterlists must be 4K aligned pages */
+	nx_ctx->csbcpb = (struct nx_csbcpb *)(round_up((u64)nx_ctx->kmem,
+						       (u64)NX_PAGE_SIZE));
+	nx_ctx->in_sg = (struct nx_sg *)((u8 *)nx_ctx->csbcpb + NX_PAGE_SIZE);
+	nx_ctx->out_sg = (struct nx_sg *)((u8 *)nx_ctx->in_sg + NX_PAGE_SIZE);
+
+	if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
+		nx_ctx->csbcpb_aead =
+			(struct nx_csbcpb *)((u8 *)nx_ctx->out_sg +
+					     NX_PAGE_SIZE);
+
+	/* give each context a pointer to global stats and their OF
+	 * properties */
+	nx_ctx->stats = &nx_driver.stats;
+	memcpy(nx_ctx->props, nx_driver.of.ap[fc][mode],
+	       sizeof(struct alg_props) * 3);
+
+	return 0;
+}
+
+/* entry points from the crypto tfm initializers */
+int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm)
+{
+	return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+				  NX_MODE_AES_CCM);
+}
+
+int nx_crypto_ctx_aes_gcm_init(struct crypto_tfm *tfm)
+{
+	return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+				  NX_MODE_AES_GCM);
+}
+
+int nx_crypto_ctx_aes_ctr_init(struct crypto_tfm *tfm)
+{
+	return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+				  NX_MODE_AES_CTR);
+}
+
+int nx_crypto_ctx_aes_cbc_init(struct crypto_tfm *tfm)
+{
+	return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+				  NX_MODE_AES_CBC);
+}
+
+int nx_crypto_ctx_aes_ecb_init(struct crypto_tfm *tfm)
+{
+	return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+				  NX_MODE_AES_ECB);
+}
+
+int nx_crypto_ctx_sha_init(struct crypto_tfm *tfm)
+{
+	return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_SHA, NX_MODE_SHA);
+}
+
+int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm)
+{
+	return nx_crypto_ctx_init(crypto_tfm_ctx(tfm), NX_FC_AES,
+				  NX_MODE_AES_XCBC_MAC);
+}
+
+/**
+ * nx_crypto_ctx_exit - destroy a crypto api context
+ *
+ * @tfm: the crypto transform pointer for the context
+ *
+ * As crypto API contexts are destroyed, this exit hook is called to free the
+ * memory associated with it.
+ */
+void nx_crypto_ctx_exit(struct crypto_tfm *tfm)
+{
+	struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+
+	kzfree(nx_ctx->kmem);
+	nx_ctx->csbcpb = NULL;
+	nx_ctx->csbcpb_aead = NULL;
+	nx_ctx->in_sg = NULL;
+	nx_ctx->out_sg = NULL;
+}
+
+static int __devinit nx_probe(struct vio_dev *viodev,
+			      const struct vio_device_id *id)
+{
+	dev_dbg(&viodev->dev, "driver probed: %s resource id: 0x%x\n",
+		viodev->name, viodev->resource_id);
+
+	if (nx_driver.viodev) {
+		dev_err(&viodev->dev, "%s: Attempt to register more than one "
+			"instance of the hardware\n", __func__);
+		return -EINVAL;
+	}
+
+	nx_driver.viodev = viodev;
+
+	nx_of_init(&viodev->dev, &nx_driver.of);
+
+	return nx_register_algs();
+}
+
+static int __devexit nx_remove(struct vio_dev *viodev)
+{
+	dev_dbg(&viodev->dev, "entering nx_remove for UA 0x%x\n",
+		viodev->unit_address);
+
+	if (nx_driver.of.status == NX_OKAY) {
+		NX_DEBUGFS_FINI(&nx_driver);
+
+		crypto_unregister_alg(&nx_ccm_aes_alg);
+		crypto_unregister_alg(&nx_ccm4309_aes_alg);
+		crypto_unregister_alg(&nx_gcm_aes_alg);
+		crypto_unregister_alg(&nx_gcm4106_aes_alg);
+		crypto_unregister_alg(&nx_ctr_aes_alg);
+		crypto_unregister_alg(&nx_ctr3686_aes_alg);
+		crypto_unregister_alg(&nx_cbc_aes_alg);
+		crypto_unregister_alg(&nx_ecb_aes_alg);
+		crypto_unregister_shash(&nx_shash_sha256_alg);
+		crypto_unregister_shash(&nx_shash_sha512_alg);
+		crypto_unregister_shash(&nx_shash_aes_xcbc_alg);
+	}
+
+	return 0;
+}
+
+
+/* module wide initialization/cleanup */
+static int __init nx_init(void)
+{
+	return vio_register_driver(&nx_driver.viodriver);
+}
+
+static void __exit nx_fini(void)
+{
+	vio_unregister_driver(&nx_driver.viodriver);
+}
+
+static struct vio_device_id nx_crypto_driver_ids[] __devinitdata = {
+	{ "ibm,sym-encryption-v1", "ibm,sym-encryption" },
+	{ "", "" }
+};
+MODULE_DEVICE_TABLE(vio, nx_crypto_driver_ids);
+
+/* driver state structure */
+struct nx_crypto_driver nx_driver = {
+	.viodriver = {
+		.id_table = nx_crypto_driver_ids,
+		.probe = nx_probe,
+		.remove = nx_remove,
+		.name  = NX_NAME,
+	},
+};
+
+module_init(nx_init);
+module_exit(nx_fini);
+
+MODULE_AUTHOR("Kent Yoder <yoder1@us.ibm.com>");
+MODULE_DESCRIPTION(NX_STRING);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(NX_VERSION);
diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h
new file mode 100644
index 0000000..e44e68a
--- /dev/null
+++ b/drivers/crypto/nx/nx.h
@@ -0,0 +1,192 @@
+
+#ifndef __NX_H__
+#define __NX_H__
+
+#define NX_NAME		"nx-crypto"
+#define NX_STRING	"IBM Power7+ Nest Accelerator Crypto Driver"
+#define NX_VERSION	"1.0"
+
+static const char nx_driver_string[] = NX_STRING;
+static const char nx_driver_version[] = NX_VERSION;
+
+/* a scatterlist in the format PHYP is expecting */
+struct nx_sg {
+	u64 addr;
+	u32 rsvd;
+	u32 len;
+} __attribute((packed));
+
+#define NX_PAGE_SIZE		(4096)
+#define NX_MAX_SG_ENTRIES	(NX_PAGE_SIZE/(sizeof(struct nx_sg)))
+
+enum nx_status {
+	NX_DISABLED,
+	NX_WAITING,
+	NX_OKAY
+};
+
+/* msc_triplet and max_sync_cop are used only to assist in parsing the
+ * openFirmware property */
+struct msc_triplet {
+	u32 keybitlen;
+	u32 databytelen;
+	u32 sglen;
+} __packed;
+
+struct max_sync_cop {
+	u32 fc;
+	u32 mode;
+	u32 triplets;
+	struct msc_triplet trip[0];
+} __packed;
+
+struct alg_props {
+	u32 databytelen;
+	u32 sglen;
+};
+
+#define NX_OF_FLAG_MAXSGLEN_SET		(1)
+#define NX_OF_FLAG_STATUS_SET		(2)
+#define NX_OF_FLAG_MAXSYNCCOP_SET	(4)
+#define NX_OF_FLAG_MASK_READY		(NX_OF_FLAG_MAXSGLEN_SET | \
+					 NX_OF_FLAG_STATUS_SET |   \
+					 NX_OF_FLAG_MAXSYNCCOP_SET)
+struct nx_of {
+	u32 flags;
+	u32 max_sg_len;
+	enum nx_status status;
+	struct alg_props ap[NX_MAX_FC][NX_MAX_MODE][3];
+};
+
+struct nx_stats {
+	atomic_t aes_ops;
+	atomic64_t aes_bytes;
+	atomic_t sha256_ops;
+	atomic64_t sha256_bytes;
+	atomic_t sha512_ops;
+	atomic64_t sha512_bytes;
+
+	atomic_t sync_ops;
+
+	atomic_t errors;
+	atomic_t last_error;
+	atomic_t last_error_pid;
+};
+
+struct nx_debugfs {
+	struct dentry *dfs_root;
+	struct dentry *dfs_aes_ops, *dfs_aes_bytes;
+	struct dentry *dfs_sha256_ops, *dfs_sha256_bytes;
+	struct dentry *dfs_sha512_ops, *dfs_sha512_bytes;
+	struct dentry *dfs_errors, *dfs_last_error, *dfs_last_error_pid;
+};
+
+struct nx_crypto_driver {
+	struct nx_stats    stats;
+	struct nx_of       of;
+	struct vio_dev    *viodev;
+	struct vio_driver  viodriver;
+	struct nx_debugfs  dfs;
+};
+
+#define NX_GCM4106_NONCE_LEN		(4)
+#define NX_GCM_CTR_OFFSET		(12)
+struct nx_gcm_priv {
+	u8 iv[16];
+	u8 iauth_tag[16];
+	u8 nonce[NX_GCM4106_NONCE_LEN];
+};
+
+#define NX_CCM_AES_KEY_LEN		(16)
+#define NX_CCM4309_AES_KEY_LEN		(19)
+#define NX_CCM4309_NONCE_LEN		(3)
+struct nx_ccm_priv {
+	u8 iv[16];
+	u8 b0[16];
+	u8 iauth_tag[16];
+	u8 oauth_tag[16];
+	u8 nonce[NX_CCM4309_NONCE_LEN];
+};
+
+struct nx_xcbc_priv {
+	u8 key[16];
+};
+
+struct nx_ctr_priv {
+	u8 iv[16];
+};
+
+struct nx_crypto_ctx {
+	void *kmem;		  /* unaligned, kmalloc'd buffer */
+	size_t kmem_len;	  /* length of kmem */
+	struct nx_csbcpb *csbcpb; /* aligned page given to phyp @ hcall time */
+	struct vio_pfo_op op;     /* operation struct with hcall parameters */
+	struct nx_csbcpb *csbcpb_aead; /* secondary csbcpb used by AEAD algs */
+	struct vio_pfo_op op_aead;/* operation struct for csbcpb_aead */
+
+	struct nx_sg *in_sg;      /* aligned pointer into kmem to an sg list */
+	struct nx_sg *out_sg;     /* aligned pointer into kmem to an sg list */
+
+	struct alg_props *ap;	  /* pointer into props based on our key size */
+	struct alg_props props[3];/* openFirmware properties for requests */
+	struct nx_stats *stats;   /* pointer into an nx_crypto_driver for stats
+				     reporting */
+
+	union {
+		struct nx_gcm_priv gcm;
+		struct nx_ccm_priv ccm;
+		struct nx_xcbc_priv xcbc;
+		struct nx_ctr_priv ctr;
+	} priv;
+};
+
+/* prototypes */
+int nx_crypto_ctx_aes_ccm_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_gcm_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_xcbc_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_ctr_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_cbc_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_aes_ecb_init(struct crypto_tfm *tfm);
+int nx_crypto_ctx_sha_init(struct crypto_tfm *tfm);
+void nx_crypto_ctx_exit(struct crypto_tfm *tfm);
+void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function);
+int nx_hcall_sync(struct nx_crypto_ctx *ctx, struct vio_pfo_op *op);
+struct nx_sg *nx_build_sg_list(struct nx_sg *, u8 *, unsigned int, u32);
+int nx_build_sg_lists(struct nx_crypto_ctx *, struct blkcipher_desc *,
+		      struct scatterlist *, struct scatterlist *, unsigned int,
+		      u8 *);
+struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned int,
+				struct scatterlist *, unsigned int,
+				unsigned int);
+
+#ifdef CONFIG_DEBUG_FS
+#define NX_DEBUGFS_INIT(drv)	nx_debugfs_init(drv)
+#define NX_DEBUGFS_FINI(drv)	nx_debugfs_fini(drv)
+
+int nx_debugfs_init(struct nx_crypto_driver *);
+void nx_debugfs_fini(struct nx_crypto_driver *);
+#else
+#define NX_DEBUGFS_INIT(drv)	(0)
+#define NX_DEBUGFS_FINI(drv)	(0)
+#endif
+
+#define NX_PAGE_NUM(x)		((u64)(x) & 0xfffffffffffff000ULL)
+
+extern struct crypto_alg nx_cbc_aes_alg;
+extern struct crypto_alg nx_ecb_aes_alg;
+extern struct crypto_alg nx_gcm_aes_alg;
+extern struct crypto_alg nx_gcm4106_aes_alg;
+extern struct crypto_alg nx_ctr_aes_alg;
+extern struct crypto_alg nx_ctr3686_aes_alg;
+extern struct crypto_alg nx_ccm_aes_alg;
+extern struct crypto_alg nx_ccm4309_aes_alg;
+extern struct shash_alg nx_shash_aes_xcbc_alg;
+extern struct shash_alg nx_shash_sha512_alg;
+extern struct shash_alg nx_shash_sha256_alg;
+
+extern struct nx_crypto_driver nx_driver;
+
+#define SCATTERWALK_TO_SG	1
+#define SCATTERWALK_FROM_SG	0
+
+#endif
diff --git a/drivers/crypto/nx/nx_csbcpb.h b/drivers/crypto/nx/nx_csbcpb.h
new file mode 100644
index 0000000..a304f95
--- /dev/null
+++ b/drivers/crypto/nx/nx_csbcpb.h
@@ -0,0 +1,205 @@
+
+#ifndef __NX_CSBCPB_H__
+#define __NX_CSBCPB_H__
+
+struct cop_symcpb_aes_ecb {
+	u8 key[32];
+	u8 __rsvd[80];
+} __packed;
+
+struct cop_symcpb_aes_cbc {
+	u8 iv[16];
+	u8 key[32];
+	u8 cv[16];
+	u32 spbc;
+	u8 __rsvd[44];
+} __packed;
+
+struct cop_symcpb_aes_gca {
+	u8 in_pat[16];
+	u8 key[32];
+	u8 out_pat[16];
+	u32 spbc;
+	u8 __rsvd[44];
+} __packed;
+
+struct cop_symcpb_aes_gcm {
+	u8 in_pat_or_aad[16];
+	u8 iv_or_cnt[16];
+	u64 bit_length_aad;
+	u64 bit_length_data;
+	u8 in_s0[16];
+	u8 key[32];
+	u8 __rsvd1[16];
+	u8 out_pat_or_mac[16];
+	u8 out_s0[16];
+	u8 out_cnt[16];
+	u32 spbc;
+	u8 __rsvd2[12];
+} __packed;
+
+struct cop_symcpb_aes_ctr {
+	u8 iv[16];
+	u8 key[32];
+	u8 cv[16];
+	u32 spbc;
+	u8 __rsvd2[44];
+} __packed;
+
+struct cop_symcpb_aes_cca {
+	u8 b0[16];
+	u8 b1[16];
+	u8 key[16];
+	u8 out_pat_or_b0[16];
+	u32 spbc;
+	u8 __rsvd[44];
+} __packed;
+
+struct cop_symcpb_aes_ccm {
+	u8 in_pat_or_b0[16];
+	u8 iv_or_ctr[16];
+	u8 in_s0[16];
+	u8 key[16];
+	u8 __rsvd1[48];
+	u8 out_pat_or_mac[16];
+	u8 out_s0[16];
+	u8 out_ctr[16];
+	u32 spbc;
+	u8 __rsvd2[12];
+} __packed;
+
+struct cop_symcpb_aes_xcbc {
+	u8 cv[16];
+	u8 key[16];
+	u8 __rsvd1[16];
+	u8 out_cv_mac[16];
+	u32 spbc;
+	u8 __rsvd2[44];
+} __packed;
+
+struct cop_symcpb_sha256 {
+	u64 message_bit_length;
+	u64 __rsvd1;
+	u8 input_partial_digest[32];
+	u8 message_digest[32];
+	u32 spbc;
+	u8 __rsvd2[44];
+} __packed;
+
+struct cop_symcpb_sha512 {
+	u64 message_bit_length_hi;
+	u64 message_bit_length_lo;
+	u8 input_partial_digest[64];
+	u8 __rsvd1[32];
+	u8 message_digest[64];
+	u32 spbc;
+	u8 __rsvd2[76];
+} __packed;
+
+#define NX_FDM_INTERMEDIATE		0x01
+#define NX_FDM_CONTINUATION		0x02
+#define NX_FDM_ENDE_ENCRYPT		0x80
+
+#define NX_CPB_FDM(c)			((c)->cpb.hdr.fdm)
+#define NX_CPB_KS_DS(c)			((c)->cpb.hdr.ks_ds)
+
+#define NX_CPB_KEY_SIZE(c)		(NX_CPB_KS_DS(c) >> 4)
+#define NX_CPB_SET_KEY_SIZE(c, x)	NX_CPB_KS_DS(c) |= ((x) << 4)
+#define NX_CPB_SET_DIGEST_SIZE(c, x)	NX_CPB_KS_DS(c) |= (x)
+
+struct cop_symcpb_header {
+	u8 mode;
+	u8 fdm;
+	u8 ks_ds;
+	u8 pad_byte;
+	u8 __rsvd[12];
+} __packed;
+
+struct cop_parameter_block {
+	struct cop_symcpb_header hdr;
+	union {
+		struct cop_symcpb_aes_ecb  aes_ecb;
+		struct cop_symcpb_aes_cbc  aes_cbc;
+		struct cop_symcpb_aes_gca  aes_gca;
+		struct cop_symcpb_aes_gcm  aes_gcm;
+		struct cop_symcpb_aes_cca  aes_cca;
+		struct cop_symcpb_aes_ccm  aes_ccm;
+		struct cop_symcpb_aes_ctr  aes_ctr;
+		struct cop_symcpb_aes_xcbc aes_xcbc;
+		struct cop_symcpb_sha256   sha256;
+		struct cop_symcpb_sha512   sha512;
+	};
+} __packed;
+
+#define NX_CSB_VALID_BIT	0x80
+
+/* co-processor status block */
+struct cop_status_block {
+	u8 valid;
+	u8 crb_seq_number;
+	u8 completion_code;
+	u8 completion_extension;
+	u32 processed_byte_count;
+	u64 address;
+} __packed;
+
+/* Nest accelerator workbook section 4.4 */
+struct nx_csbcpb {
+	unsigned char __rsvd[112];
+	struct cop_status_block csb;
+	struct cop_parameter_block cpb;
+} __packed;
+
+/* nx_csbcpb related definitions */
+#define NX_MODE_AES_ECB			0
+#define NX_MODE_AES_CBC			1
+#define NX_MODE_AES_GMAC		2
+#define NX_MODE_AES_GCA			3
+#define NX_MODE_AES_GCM			4
+#define NX_MODE_AES_CCA			5
+#define NX_MODE_AES_CCM			6
+#define NX_MODE_AES_CTR			7
+#define NX_MODE_AES_XCBC_MAC		20
+#define NX_MODE_SHA			0
+#define NX_MODE_SHA_HMAC		1
+#define NX_MODE_AES_CBC_HMAC_ETA	8
+#define NX_MODE_AES_CBC_HMAC_ATE	9
+#define NX_MODE_AES_CBC_HMAC_EAA	10
+#define NX_MODE_AES_CTR_HMAC_ETA	12
+#define NX_MODE_AES_CTR_HMAC_ATE	13
+#define NX_MODE_AES_CTR_HMAC_EAA	14
+
+#define NX_FDM_CI_FULL		0
+#define NX_FDM_CI_FIRST		1
+#define NX_FDM_CI_LAST		2
+#define NX_FDM_CI_MIDDLE	3
+
+#define NX_FDM_PR_NONE		0
+#define NX_FDM_PR_PAD		1
+
+#define NX_KS_AES_128		1
+#define NX_KS_AES_192		2
+#define NX_KS_AES_256		3
+
+#define NX_DS_SHA256		2
+#define NX_DS_SHA512		3
+
+#define NX_FC_AES		0
+#define NX_FC_SHA		2
+#define NX_FC_AES_HMAC		6
+
+#define NX_MAX_FC		(NX_FC_AES_HMAC + 1)
+#define NX_MAX_MODE		(NX_MODE_AES_XCBC_MAC + 1)
+
+#define HCOP_FC_AES          NX_FC_AES
+#define HCOP_FC_SHA          NX_FC_SHA
+#define HCOP_FC_AES_HMAC     NX_FC_AES_HMAC
+
+/* indices into the array of algorithm properties */
+#define NX_PROPS_AES_128		0
+#define NX_PROPS_AES_192		1
+#define NX_PROPS_AES_256		2
+#define NX_PROPS_SHA256			1
+#define NX_PROPS_SHA512			2
+
+#endif
-- 
1.7.1

^ permalink raw reply related


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