<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/">
  <channel rdf:about="http://blog.gmane.org/gmane.linux.kernel.cryptoapi">
    <title>gmane.linux.kernel.cryptoapi</title>
    <link>http://blog.gmane.org/gmane.linux.kernel.cryptoapi</link>
    <description/>
    <syn:updatePeriod>hourly</syn:updatePeriod>
    <syn:updateFrequency>1</syn:updateFrequency>
    <syn:updateBase>1901-01-01T00:00+00:00</syn:updateBase>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7063"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7062"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7061"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7060"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7058"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7057"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7056"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7055"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7054"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7053"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7052"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7051"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7050"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7049"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7048"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7047"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7046"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7045"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7041"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7038"/>
      </rdf:Seq>
    </items>
    <image rdf:resource="http://gmane.org/img/gmane-25t.png"/>
    <textinput rdf:resource=""/>
  </channel>
  <image rdf:about="http://gmane.org/img/gmane-25t.png">
    <title>Gmane</title>
    <url>http://gmane.org/img/gmane-25t.png</url>
    <link>http://gmane.org</link>
  </image>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7063">
    <title>[PATCH 1/4] mv_cesa: add an expiry timer in case anything goes wrong</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7063</link>
    <description>&lt;pre&gt;The timer triggers when 500ms have gone by after triggering the engine
and no completion interrupt was received. The callback then tries to
sanitise things as well as possible.

Signed-off-by: Phil Sutter &amp;lt;phil.sutter&amp;lt; at &amp;gt;viprinet.com&amp;gt;
---
 drivers/crypto/mv_cesa.c |   41 +++++++++++++++++++++++++++++++----------
 1 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index e6ecc5f..8327bed 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -23,6 +23,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 
 #define MV_CESA"MV-CESA:"
 #define MAX_HW_HASH_SIZE0xFFFF
+#define MV_CESA_EXPIRE500 /* msec */
 
 /*
  * STM:
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -85,6 +86,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct crypto_priv {
 spinlock_t lock;
 struct crypto_queue queue;
 enum engine_status eng_st;
+struct timer_list completion_timer;
 struct crypto_async_request *cur_req;
 struct req_progress p;
 int max_req_size;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -136,6 +138,29 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct mv_req_hash_ctx {
 int count_add;
 };
 
+static void mv_completion_timer_callback(unsigned long unused)
+{
+int active = readl(cpg-&amp;gt;reg + SEC_ACCEL_CMD) &amp;amp; SEC_CMD_EN_SEC_ACCL0;
+
+printk(KERN_ERR MV_CESA
+       "completion timer expired (CESA %sactive), cleaning up.\n",
+       active ? "" : "in");
+
+del_timer(&amp;amp;cpg-&amp;gt;completion_timer);
+writel(SEC_CMD_DISABLE_SEC, cpg-&amp;gt;reg + SEC_ACCEL_CMD);
+while(readl(cpg-&amp;gt;reg + SEC_ACCEL_CMD) &amp;amp; SEC_CMD_DISABLE_SEC)
+printk(KERN_INFO MV_CESA "%s: waiting for engine finishing\n", __func__);
+cpg-&amp;gt;eng_st = ENGINE_W_DEQUEUE;
+wake_up_process(cpg-&amp;gt;queue_th);
+}
+
+static void mv_setup_timer(void)
+{
+setup_timer(&amp;amp;cpg-&amp;gt;completion_timer, &amp;amp;mv_completion_timer_callback, 0);
+mod_timer(&amp;amp;cpg-&amp;gt;completion_timer,
+jiffies + msecs_to_jiffies(MV_CESA_EXPIRE));
+}
+
 static void compute_aes_dec_key(struct mv_ctx *ctx)
 {
 struct crypto_aes_ctx gen_aes_key;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -271,12 +296,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void mv_process_current_q(int first_block)
 sizeof(struct sec_accel_config));
 
 /* GO */
+mv_setup_timer();
 writel(SEC_CMD_EN_SEC_ACCL0, cpg-&amp;gt;reg + SEC_ACCEL_CMD);
-
-/*
- * XXX: add timer if the interrupt does not occur for some mystery
- * reason
- */
 }
 
 static void mv_crypto_algo_completion(void)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -355,12 +376,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void mv_process_hash_current(int first_block)
 memcpy(cpg-&amp;gt;sram + SRAM_CONFIG, &amp;amp;op, sizeof(struct sec_accel_config));
 
 /* GO */
+mv_setup_timer();
 writel(SEC_CMD_EN_SEC_ACCL0, cpg-&amp;gt;reg + SEC_ACCEL_CMD);
-
-/*
-* XXX: add timer if the interrupt does not occur for some mystery
-* reason
-*/
 }
 
 static inline int mv_hash_import_sha1_ctx(const struct mv_req_hash_ctx *ctx,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -886,6 +903,10 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; irqreturn_t crypto_int(int irq, void *priv)
 if (!(val &amp;amp; SEC_INT_ACCEL0_DONE))
 return IRQ_NONE;
 
+if (!del_timer(&amp;amp;cpg-&amp;gt;completion_timer)) {
+printk(KERN_WARNING MV_CESA
+       "got an interrupt but no pending timer?\n");
+}
 val &amp;amp;= ~SEC_INT_ACCEL0_DONE;
 writel(val, cpg-&amp;gt;reg + FPGA_INT_STATUS);
 writel(val, cpg-&amp;gt;reg + SEC_ACCEL_INT_STATUS);
&lt;/pre&gt;</description>
    <dc:creator>Phil Sutter</dc:creator>
    <dc:date>2012-05-25T13:54:46</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7062">
    <title>[PATCH 4/4] mv_cesa: fix for hash finalisation with data</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7062</link>
    <description>&lt;pre&gt;Since mv_hash_final_fallback() uses ctx-&amp;gt;state, read out the digest
state register before calling it.

Signed-off-by: Phil Sutter &amp;lt;phil.sutter&amp;lt; at &amp;gt;viprinet.com&amp;gt;
---
 drivers/crypto/mv_cesa.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index d4763fb..3cc9237 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -421,6 +421,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; out:
 return rc;
 }
 
+static void mv_save_digest_state(struct mv_req_hash_ctx *ctx)
+{
+ctx-&amp;gt;state[0] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_A);
+ctx-&amp;gt;state[1] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_B);
+ctx-&amp;gt;state[2] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_C);
+ctx-&amp;gt;state[3] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_D);
+ctx-&amp;gt;state[4] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_E);
+}
+
 static void mv_hash_algo_completion(void)
 {
 struct ahash_request *req = ahash_request_cast(cpg-&amp;gt;cur_req);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -435,14 +444,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void mv_hash_algo_completion(void)
 memcpy(req-&amp;gt;result, cpg-&amp;gt;sram + SRAM_DIGEST_BUF,
        crypto_ahash_digestsize(crypto_ahash_reqtfm
        (req)));
-} else
+} else {
+mv_save_digest_state(ctx);
 mv_hash_final_fallback(req);
+}
 } else {
-ctx-&amp;gt;state[0] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_A);
-ctx-&amp;gt;state[1] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_B);
-ctx-&amp;gt;state[2] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_C);
-ctx-&amp;gt;state[3] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_D);
-ctx-&amp;gt;state[4] = readl(cpg-&amp;gt;reg + DIGEST_INITIAL_VAL_E);
+mv_save_digest_state(ctx);
 }
 }
 
&lt;/pre&gt;</description>
    <dc:creator>Phil Sutter</dc:creator>
    <dc:date>2012-05-25T13:54:49</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7061">
    <title>[PATCH 2/4] mv_cesa: no need to write to that FPGA_INT_STATUS field</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7061</link>
    <description>&lt;pre&gt;Also drop the whole definition, since it's unused otherwise.

Signed-off-by: Phil Sutter &amp;lt;phil.sutter&amp;lt; at &amp;gt;viprinet.com&amp;gt;
---
 drivers/crypto/mv_cesa.c |    1 -
 drivers/crypto/mv_cesa.h |    7 -------
 2 files changed, 0 insertions(+), 8 deletions(-)

diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index 8327bed..4a1f872 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -908,7 +908,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; irqreturn_t crypto_int(int irq, void *priv)
        "got an interrupt but no pending timer?\n");
 }
 val &amp;amp;= ~SEC_INT_ACCEL0_DONE;
-writel(val, cpg-&amp;gt;reg + FPGA_INT_STATUS);
 writel(val, cpg-&amp;gt;reg + SEC_ACCEL_INT_STATUS);
 BUG_ON(cpg-&amp;gt;eng_st != ENGINE_BUSY);
 cpg-&amp;gt;eng_st = ENGINE_W_DEQUEUE;
diff --git a/drivers/crypto/mv_cesa.h b/drivers/crypto/mv_cesa.h
index 08fcb11..81ce109 100644
--- a/drivers/crypto/mv_cesa.h
+++ b/drivers/crypto/mv_cesa.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -29,13 +29,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #define SEC_ST_ACT_0(1 &amp;lt;&amp;lt; 0)
 #define SEC_ST_ACT_1(1 &amp;lt;&amp;lt; 1)
 
-/*
- * FPGA_INT_STATUS looks like a FPGA leftover and is documented only in Errata
- * 4.12. It looks like that it was part of an IRQ-controller in FPGA and
- * someone forgot to remove  it while switching to the core and moving to
- * SEC_ACCEL_INT_STATUS.
- */
-#define FPGA_INT_STATUS0xdd68
 #define SEC_ACCEL_INT_STATUS0xde20
 #define SEC_INT_AUTH_DONE(1 &amp;lt;&amp;lt; 0)
 #define SEC_INT_DES_E_DONE(1 &amp;lt;&amp;lt; 1)
&lt;/pre&gt;</description>
    <dc:creator>Phil Sutter</dc:creator>
    <dc:date>2012-05-25T13:54:47</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7060">
    <title>[PATCH 3/4] mv_cesa: initialise the interrupt status field to zero</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7060</link>
    <description>&lt;pre&gt;
Signed-off-by: Phil Sutter &amp;lt;phil.sutter&amp;lt; at &amp;gt;viprinet.com&amp;gt;
---
 drivers/crypto/mv_cesa.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index 4a1f872..d4763fb 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1073,6 +1073,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int mv_probe(struct platform_device *pdev)
 if (ret)
 goto err_thread;
 
+writel(0, cpg-&amp;gt;reg + SEC_ACCEL_INT_STATUS);
 writel(SEC_INT_ACCEL0_DONE, cpg-&amp;gt;reg + SEC_ACCEL_INT_MASK);
 writel(SEC_CFG_STOP_DIG_ERR, cpg-&amp;gt;reg + SEC_ACCEL_CFG);
 writel(SRAM_CONFIG, cpg-&amp;gt;reg + SEC_ACCEL_DESC_P0);
&lt;/pre&gt;</description>
    <dc:creator>Phil Sutter</dc:creator>
    <dc:date>2012-05-25T13:54:48</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7058">
    <title>[PATCH 2/2] crypto: bfin_crc: CRC hardware accelerator driver for BF60x family processors.</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7058</link>
    <description>&lt;pre&gt;From: Sonic Zhang &amp;lt;sonic.zhang&amp;lt; at &amp;gt;analog.com&amp;gt;

The CRC peripheral is a hardware block used to compute the CRC of the block
of data. This is based on a CRC32 engine which computes the CRC value of 32b
data words presented to it. For data words of &amp;lt; 32b in size, this driver
pack 0 automatically into 32b data units. This driver implements the async
hash crypto framework API.

Signed-off-by: Sonic Zhang &amp;lt;sonic.zhang&amp;lt; at &amp;gt;analog.com&amp;gt;
---
 drivers/crypto/Kconfig    |    7 +
 drivers/crypto/Makefile   |    3 +-
 drivers/crypto/bfin_crc.c |  789 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 798 insertions(+), 1 deletions(-)
 create mode 100644 drivers/crypto/bfin_crc.c

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 69fdf18..a520b93 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -306,4 +306,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; if CRYPTO_DEV_UX500
 source "drivers/crypto/ux500/Kconfig"
 endif # if CRYPTO_DEV_UX500
 
+config CRYPTO_DEV_BFIN_CRC
+tristate "Support for Blackfin CRC hareware accelerator"
+depends on BF60x
+help
+  Blackfin processors have CRC hardware accelerator. Select this if you
+  want to use the Blackfin CRC module.
+
 endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 0139032..d5062bb 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -14,4 +14,5 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
 obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
 obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
-obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
\ No newline at end of file
+obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
+obj-$(CONFIG_CRYPTO_DEV_BFIN_CRC) += bfin_crc.o
diff --git a/drivers/crypto/bfin_crc.c b/drivers/crypto/bfin_crc.c
new file mode 100644
index 0000000..477b6a3
--- /dev/null
+++ b/drivers/crypto/bfin_crc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,789 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * Cryptographic API.
+ *
+ * Support Blackfin CRC HW acceleration.
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include &amp;lt;linux/err.h&amp;gt;
+#include &amp;lt;linux/device.h&amp;gt;
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/init.h&amp;gt;
+#include &amp;lt;linux/errno.h&amp;gt;
+#include &amp;lt;linux/interrupt.h&amp;gt;
+#include &amp;lt;linux/kernel.h&amp;gt;
+#include &amp;lt;linux/irq.h&amp;gt;
+#include &amp;lt;linux/io.h&amp;gt;
+#include &amp;lt;linux/platform_device.h&amp;gt;
+#include &amp;lt;linux/scatterlist.h&amp;gt;
+#include &amp;lt;linux/dma-mapping.h&amp;gt;
+#include &amp;lt;linux/delay.h&amp;gt;
+#include &amp;lt;linux/crypto.h&amp;gt;
+#include &amp;lt;linux/cryptohash.h&amp;gt;
+#include &amp;lt;crypto/scatterwalk.h&amp;gt;
+#include &amp;lt;crypto/algapi.h&amp;gt;
+#include &amp;lt;crypto/hash.h&amp;gt;
+#include &amp;lt;crypto/internal/hash.h&amp;gt;
+
+#include &amp;lt;asm/blackfin.h&amp;gt;
+#include &amp;lt;asm/bfin_crc.h&amp;gt;
+#include &amp;lt;asm/dma.h&amp;gt;
+#include &amp;lt;asm/portmux.h&amp;gt;
+
+#define CRC_CCRYPTO_QUEUE_LENGTH5
+
+#define DRIVER_NAME "bfin-hmac-crc"
+#define CHKSUM_DIGEST_SIZE      4
+#define CHKSUM_BLOCK_SIZE       1
+
+#define CRC_MAX_DMA_DESC100
+
+#define CRC_CRYPTO_STATE_UPDATE1
+#define CRC_CRYPTO_STATE_FINALUPDATE2
+#define CRC_CRYPTO_STATE_FINISH3
+
+struct bfin_crypto_crc {
+struct list_headlist;
+struct device*dev;
+spinlock_tlock;
+
+intirq;
+intdma_ch;
+u32poly;
+volatile struct crc_register *regs;
+
+struct ahash_request*req; /* current request in operation */
+struct dma_desc_array*sg_cpu; /* virt addr of sg dma descriptors */
+dma_addr_tsg_dma; /* phy addr of sg dma descriptors */
+u8*sg_mid_buf;
+
+struct tasklet_structdone_task;
+struct crypto_queuequeue; /* waiting requests */
+
+u8busy:1; /* crc device in operation flag */
+};
+
+struct bfin_crypto_crc_list {
+struct list_headdev_list;
+spinlock_tlock;
+} crc_list;
+
+struct bfin_crypto_crc_reqctx {
+struct bfin_crypto_crc*crc;
+
+unsigned inttotal;/* total request bytes */
+size_tsg_buflen; /* bytes for this update */
+unsigned intsg_nents;
+struct scatterlist*sg; /* sg list head for this update*/
+struct scatterlistbufsl[2]; /* chained sg list */
+
+size_tbufnext_len;
+size_tbuflast_len;
+u8bufnext[CHKSUM_DIGEST_SIZE]; /* extra bytes for next udpate */
+u8buflast[CHKSUM_DIGEST_SIZE]; /* extra bytes from last udpate */
+
+u8flag;
+};
+
+struct bfin_crypto_crc_ctx {
+struct bfin_crypto_crc*crc;
+u32key;
+};
+
+
+/*
+ * derive number of elements in scatterlist
+ */
+static int sg_count(struct scatterlist *sg_list)
+{
+struct scatterlist *sg = sg_list;
+int sg_nents = 1;
+
+if (sg_list == NULL)
+return 0;
+
+while (!sg_is_last(sg)) {
+sg_nents++;
+sg = scatterwalk_sg_next(sg);
+}
+
+return sg_nents;
+}
+
+/*
+ * get element in scatter list by given index
+ */
+static struct scatterlist *sg_get(struct scatterlist *sg_list, unsigned int nents,
+unsigned int index)
+{
+struct scatterlist *sg = NULL;
+int i;
+
+for_each_sg(sg_list, sg, nents, i)
+if (i == index)
+break;
+
+return sg;
+}
+
+static int bfin_crypto_crc_init_hw(struct bfin_crypto_crc *crc, u32 key)
+{
+crc-&amp;gt;regs-&amp;gt;datacntrld = 0;
+crc-&amp;gt;regs-&amp;gt;control = MODE_CALC_CRC &amp;lt;&amp;lt; OPMODE_OFFSET;
+crc-&amp;gt;regs-&amp;gt;curresult = key;
+
+/* setup CRC interrupts */
+crc-&amp;gt;regs-&amp;gt;status = CMPERRI | DCNTEXPI;
+crc-&amp;gt;regs-&amp;gt;intrenset = CMPERRI | DCNTEXPI;
+SSYNC();
+
+return 0;
+}
+
+static int bfin_crypto_crc_init(struct ahash_request *req)
+{
+struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+struct bfin_crypto_crc_ctx *crc_ctx = crypto_ahash_ctx(tfm);
+struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req);
+struct bfin_crypto_crc *crc;
+
+dev_dbg(crc-&amp;gt;dev, "crc_init\n");
+spin_lock_bh(&amp;amp;crc_list.lock);
+list_for_each_entry(crc, &amp;amp;crc_list.dev_list, list) {
+crc_ctx-&amp;gt;crc = crc;
+break;
+}
+spin_unlock_bh(&amp;amp;crc_list.lock);
+
+if (sg_count(req-&amp;gt;src) &amp;gt; CRC_MAX_DMA_DESC) {
+dev_dbg(crc-&amp;gt;dev, "init: requested sg list is too big &amp;gt; %d\n",
+CRC_MAX_DMA_DESC);
+return -EINVAL;
+}
+
+ctx-&amp;gt;crc = crc;
+ctx-&amp;gt;bufnext_len = 0;
+ctx-&amp;gt;buflast_len = 0;
+ctx-&amp;gt;sg_buflen = 0;
+ctx-&amp;gt;total = 0;
+ctx-&amp;gt;flag = 0;
+
+/* init crc results */
+*(__le32 *)req-&amp;gt;result =
+cpu_to_le32p(&amp;amp;crc_ctx-&amp;gt;key);
+
+dev_dbg(crc-&amp;gt;dev, "init: digest size: %d\n",
+crypto_ahash_digestsize(tfm));
+
+return bfin_crypto_crc_init_hw(crc, crc_ctx-&amp;gt;key);
+}
+
+static void bfin_crypto_crc_config_dma(struct bfin_crypto_crc *crc)
+{
+struct scatterlist *sg;
+struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(crc-&amp;gt;req);
+int i = 0, j = 0;
+unsigned long dma_config;
+unsigned int dma_count;
+unsigned int dma_addr;
+unsigned int mid_dma_count = 0;
+int dma_mod;
+
+dma_map_sg(crc-&amp;gt;dev, ctx-&amp;gt;sg, ctx-&amp;gt;sg_nents, DMA_TO_DEVICE);
+
+for_each_sg(ctx-&amp;gt;sg, sg, ctx-&amp;gt;sg_nents, j) {
+dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 | DMAEN | PSIZE_32;
+dma_addr = sg_dma_address(sg);
+/* deduce extra bytes in last sg */
+if (sg_is_last(sg))
+dma_count = sg_dma_len(sg) - ctx-&amp;gt;bufnext_len;
+else
+dma_count = sg_dma_len(sg);
+
+if (mid_dma_count) {
+/* Append last middle dma buffer to 4 bytes with first
+   bytes in current sg buffer. Move addr of current
+   sg and deduce the length of current sg.
+ */
+memcpy(crc-&amp;gt;sg_mid_buf +((i-1) &amp;lt;&amp;lt; 2) + mid_dma_count,
+(void *)dma_addr,
+CHKSUM_DIGEST_SIZE - mid_dma_count);
+dma_addr += CHKSUM_DIGEST_SIZE - mid_dma_count;
+dma_count -= CHKSUM_DIGEST_SIZE - mid_dma_count;
+}
+/* chop current sg dma len to multiply of 32 bits */
+mid_dma_count = dma_count % 4;
+dma_count = (dma_count &amp;gt;&amp;gt; 2) &amp;lt;&amp;lt; 2;
+
+if (dma_addr % 4 == 0) {
+dma_config |= WDSIZE_32;
+dma_count &amp;gt;&amp;gt;= 2;
+dma_mod = 4;
+} else if (dma_addr % 2 == 0) {
+dma_config |= WDSIZE_16;
+dma_count &amp;gt;&amp;gt;= 1;
+dma_mod = 2;
+} else {
+dma_config |= WDSIZE_8;
+dma_mod = 1;
+}
+
+crc-&amp;gt;sg_cpu[i].start_addr = dma_addr;
+crc-&amp;gt;sg_cpu[i].cfg = dma_config;
+crc-&amp;gt;sg_cpu[i].x_count = dma_count;
+crc-&amp;gt;sg_cpu[i].x_modify = dma_mod;
+dev_dbg(crc-&amp;gt;dev, "%d: crc_dma: start_addr:0x%lx, "
+"cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n",
+i, crc-&amp;gt;sg_cpu[i].start_addr,
+crc-&amp;gt;sg_cpu[i].cfg, crc-&amp;gt;sg_cpu[i].x_count,
+crc-&amp;gt;sg_cpu[i].x_modify);
+i++;
+
+if (mid_dma_count) {
+/* copy extra bytes to next middle dma buffer */
+dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 |
+DMAEN | PSIZE_32 | WDSIZE_32;
+memcpy(crc-&amp;gt;sg_mid_buf + (i &amp;lt;&amp;lt; 2),
+(void *)(dma_addr + (dma_count &amp;lt;&amp;lt; 2)),
+mid_dma_count);
+/* setup new dma descriptor for next middle dma */
+crc-&amp;gt;sg_cpu[i].start_addr = dma_map_single(crc-&amp;gt;dev,
+crc-&amp;gt;sg_mid_buf + (i &amp;lt;&amp;lt; 2),
+CHKSUM_DIGEST_SIZE, DMA_TO_DEVICE);
+crc-&amp;gt;sg_cpu[i].cfg = dma_config;
+crc-&amp;gt;sg_cpu[i].x_count = 1;
+crc-&amp;gt;sg_cpu[i].x_modify = CHKSUM_DIGEST_SIZE;
+dev_dbg(crc-&amp;gt;dev, "%d: crc_dma: start_addr:0x%lx, "
+"cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n",
+i, crc-&amp;gt;sg_cpu[i].start_addr,
+crc-&amp;gt;sg_cpu[i].cfg, crc-&amp;gt;sg_cpu[i].x_count,
+crc-&amp;gt;sg_cpu[i].x_modify);
+i++;
+}
+}
+
+dma_config = DMAFLOW_ARRAY | RESTART | NDSIZE_3 | DMAEN | PSIZE_32 | WDSIZE_32;
+/* For final update req, append the buffer for next update as well*/
+if (ctx-&amp;gt;bufnext_len &amp;amp;&amp;amp; (ctx-&amp;gt;flag == CRC_CRYPTO_STATE_FINALUPDATE ||
+ctx-&amp;gt;flag == CRC_CRYPTO_STATE_FINISH)) {
+crc-&amp;gt;sg_cpu[i].start_addr = dma_map_single(crc-&amp;gt;dev, ctx-&amp;gt;bufnext,
+CHKSUM_DIGEST_SIZE, DMA_TO_DEVICE);
+crc-&amp;gt;sg_cpu[i].cfg = dma_config;
+crc-&amp;gt;sg_cpu[i].x_count = 1;
+crc-&amp;gt;sg_cpu[i].x_modify = CHKSUM_DIGEST_SIZE;
+dev_dbg(crc-&amp;gt;dev, "%d: crc_dma: start_addr:0x%lx, "
+"cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n",
+i, crc-&amp;gt;sg_cpu[i].start_addr,
+crc-&amp;gt;sg_cpu[i].cfg, crc-&amp;gt;sg_cpu[i].x_count,
+crc-&amp;gt;sg_cpu[i].x_modify);
+i++;
+}
+
+if (i == 0)
+return ;
+
+flush_dcache_range((unsigned int)crc-&amp;gt;sg_cpu,
+(unsigned int)crc-&amp;gt;sg_cpu +
+i * sizeof(struct dma_desc_array));
+
+/* Set the last descriptor to stop mode */
+crc-&amp;gt;sg_cpu[i - 1].cfg &amp;amp;= ~(DMAFLOW | NDSIZE);
+crc-&amp;gt;sg_cpu[i - 1].cfg |= DI_EN;
+set_dma_curr_desc_addr(crc-&amp;gt;dma_ch, (unsigned long *)crc-&amp;gt;sg_dma);
+set_dma_x_count(crc-&amp;gt;dma_ch, 0);
+set_dma_x_modify(crc-&amp;gt;dma_ch, 0);
+SSYNC();
+set_dma_config(crc-&amp;gt;dma_ch, dma_config);
+}
+
+#define MIN(x,y) ((x) &amp;lt; (y) ? x : y)
+
+static int bfin_crypto_crc_handle_queue(struct bfin_crypto_crc *crc,
+  struct ahash_request *req)
+{
+struct crypto_async_request *async_req, *backlog;
+struct bfin_crypto_crc_reqctx *ctx;
+struct scatterlist *sg;
+int ret = 0;
+int nsg, i, j, nextlen;
+unsigned long flags;
+
+spin_lock_irqsave(&amp;amp;crc-&amp;gt;lock, flags);
+if (req)
+ret = ahash_enqueue_request(&amp;amp;crc-&amp;gt;queue, req);
+if (crc-&amp;gt;busy) {
+spin_unlock_irqrestore(&amp;amp;crc-&amp;gt;lock, flags);
+return ret;
+}
+backlog = crypto_get_backlog(&amp;amp;crc-&amp;gt;queue);
+async_req = crypto_dequeue_request(&amp;amp;crc-&amp;gt;queue);
+if (async_req)
+crc-&amp;gt;busy = 1;
+spin_unlock_irqrestore(&amp;amp;crc-&amp;gt;lock, flags);
+
+if (!async_req)
+return ret;
+
+if (backlog)
+backlog-&amp;gt;complete(backlog, -EINPROGRESS);
+
+req = ahash_request_cast(async_req);
+crc-&amp;gt;req = req;
+ctx = ahash_request_ctx(req);
+ctx-&amp;gt;sg = NULL;
+ctx-&amp;gt;sg_buflen = 0;
+ctx-&amp;gt;sg_nents = 0;
+
+dev_dbg(crc-&amp;gt;dev, "handling new req, flag=%u, nbytes: %d\n",
+ctx-&amp;gt;flag, req-&amp;gt;nbytes);
+
+if (ctx-&amp;gt;flag == CRC_CRYPTO_STATE_FINISH) {
+if (ctx-&amp;gt;bufnext_len == 0) {
+crc-&amp;gt;busy = 0;
+return 0;
+}
+
+/* Pack last crc update buffer to 32bit */
+memset(ctx-&amp;gt;bufnext + ctx-&amp;gt;bufnext_len, 0,
+CHKSUM_DIGEST_SIZE - ctx-&amp;gt;bufnext_len);
+} else {
+/* Pack small data which is less than 32bit to buffer for next update.*/
+if (ctx-&amp;gt;bufnext_len + req-&amp;gt;nbytes &amp;lt; CHKSUM_DIGEST_SIZE) {
+memcpy(ctx-&amp;gt;bufnext + ctx-&amp;gt;bufnext_len,
+sg_virt(req-&amp;gt;src), req-&amp;gt;nbytes);
+ctx-&amp;gt;bufnext_len += req-&amp;gt;nbytes;
+if (ctx-&amp;gt;flag == CRC_CRYPTO_STATE_FINALUPDATE &amp;amp;&amp;amp;
+ctx-&amp;gt;bufnext_len) {
+goto finish_update;
+} else {
+crc-&amp;gt;busy = 0;
+return 0;
+}
+}
+
+if (ctx-&amp;gt;bufnext_len) {
+/* Chain in extra bytes of last update */
+ctx-&amp;gt;buflast_len = ctx-&amp;gt;bufnext_len;
+memcpy(ctx-&amp;gt;buflast, ctx-&amp;gt;bufnext, ctx-&amp;gt;buflast_len);
+
+nsg = ctx-&amp;gt;sg_buflen ? 2 : 1;
+sg_init_table(ctx-&amp;gt;bufsl, nsg);
+sg_set_buf(ctx-&amp;gt;bufsl, ctx-&amp;gt;buflast, ctx-&amp;gt;buflast_len);
+if (nsg &amp;gt; 1)
+scatterwalk_sg_chain(ctx-&amp;gt;bufsl, nsg,
+req-&amp;gt;src);
+ctx-&amp;gt;sg = ctx-&amp;gt;bufsl;
+} else
+ctx-&amp;gt;sg = req-&amp;gt;src;
+
+/* punch crc buffer size to multiply of 32 bit */
+nsg = ctx-&amp;gt;sg_nents = sg_count(ctx-&amp;gt;sg);
+ctx-&amp;gt;sg_buflen = ctx-&amp;gt;buflast_len + req-&amp;gt;nbytes;
+ctx-&amp;gt;bufnext_len = ctx-&amp;gt;sg_buflen % 4;
+ctx-&amp;gt;sg_buflen = (ctx-&amp;gt;sg_buflen &amp;gt;&amp;gt; 2) &amp;lt;&amp;lt; 2;
+
+if (ctx-&amp;gt;bufnext_len) {
+/* copy extra bytes to buffer for next update */
+memset(ctx-&amp;gt;bufnext, 0,CHKSUM_DIGEST_SIZE);
+nextlen = ctx-&amp;gt;bufnext_len;
+for (i = nsg - 1; i &amp;gt;= 0; i--) {
+sg = sg_get(ctx-&amp;gt;sg, nsg, i);
+j = MIN(nextlen, sg_dma_len(sg));
+memcpy(ctx-&amp;gt;bufnext + nextlen - j,
+sg_virt(sg) + sg_dma_len(sg) - j, j);
+if (j == sg_dma_len(sg))
+ctx-&amp;gt;sg_nents--;
+nextlen -= j;
+if (nextlen == 0)
+break;
+}
+}
+}
+
+finish_update:
+if (ctx-&amp;gt;bufnext_len &amp;amp;&amp;amp; (ctx-&amp;gt;flag == CRC_CRYPTO_STATE_FINALUPDATE ||
+ctx-&amp;gt;flag == CRC_CRYPTO_STATE_FINISH))
+ctx-&amp;gt;sg_buflen += CHKSUM_DIGEST_SIZE;
+
+/* set CRC data count before start DMA */
+crc-&amp;gt;regs-&amp;gt;datacnt = ctx-&amp;gt;sg_buflen &amp;gt;&amp;gt; 2;
+
+/* setup and enable CRC DMA */
+bfin_crypto_crc_config_dma(crc);
+
+/* finally kick off CRC operation */
+crc-&amp;gt;regs-&amp;gt;control |= BLKEN;
+SSYNC();
+
+return -EINPROGRESS;
+}
+
+static int bfin_crypto_crc_update(struct ahash_request *req)
+{
+struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req);
+
+if (!req-&amp;gt;nbytes)
+return 0;
+
+dev_dbg(ctx-&amp;gt;crc-&amp;gt;dev, "crc_update\n");
+ctx-&amp;gt;total += req-&amp;gt;nbytes;
+ctx-&amp;gt;flag = CRC_CRYPTO_STATE_UPDATE;
+
+return bfin_crypto_crc_handle_queue(ctx-&amp;gt;crc, req);
+}
+
+static int bfin_crypto_crc_final(struct ahash_request *req)
+{
+struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+struct bfin_crypto_crc_ctx *crc_ctx = crypto_ahash_ctx(tfm);
+struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req);
+
+dev_dbg(ctx-&amp;gt;crc-&amp;gt;dev, "crc_final\n");
+ctx-&amp;gt;flag = CRC_CRYPTO_STATE_FINISH;
+crc_ctx-&amp;gt;key = 0;
+
+return bfin_crypto_crc_handle_queue(ctx-&amp;gt;crc, req);
+}
+
+static int bfin_crypto_crc_finup(struct ahash_request *req)
+{
+struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+struct bfin_crypto_crc_ctx *crc_ctx = crypto_ahash_ctx(tfm);
+struct bfin_crypto_crc_reqctx *ctx = ahash_request_ctx(req);
+
+dev_dbg(ctx-&amp;gt;crc-&amp;gt;dev, "crc_finishupdate\n");
+ctx-&amp;gt;total += req-&amp;gt;nbytes;
+ctx-&amp;gt;flag = CRC_CRYPTO_STATE_FINALUPDATE;
+crc_ctx-&amp;gt;key = 0;
+
+return bfin_crypto_crc_handle_queue(ctx-&amp;gt;crc, req);
+}
+
+static int bfin_crypto_crc_digest(struct ahash_request *req)
+{
+int ret;
+
+ret = bfin_crypto_crc_init(req);
+if (ret)
+return ret;
+
+return bfin_crypto_crc_finup(req);
+}
+
+static int bfin_crypto_crc_setkey(struct crypto_ahash *tfm, const u8 *key,
+      unsigned int keylen)
+{
+struct bfin_crypto_crc_ctx *crc_ctx = crypto_ahash_ctx(tfm);
+
+dev_dbg(crc_ctx-&amp;gt;crc-&amp;gt;dev, "crc_setkey\n");
+        if (keylen != CHKSUM_DIGEST_SIZE) {
+                crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+                return -EINVAL;
+        }
+
+crc_ctx-&amp;gt;key = le32_to_cpu(*(__le32 *)key);
+
+return 0;
+}
+
+static int bfin_crypto_crc_cra_init(struct crypto_tfm *tfm)
+{
+struct bfin_crypto_crc_ctx *crc_ctx = crypto_tfm_ctx(tfm);
+
+crc_ctx-&amp;gt;key = 0;
+crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct bfin_crypto_crc_reqctx));
+
+return 0;
+}
+
+static void bfin_crypto_crc_cra_exit(struct crypto_tfm *tfm)
+{
+}
+
+static struct ahash_alg algs = {
+.init= bfin_crypto_crc_init,
+.update= bfin_crypto_crc_update,
+.final= bfin_crypto_crc_final,
+.finup= bfin_crypto_crc_finup,
+.digest= bfin_crypto_crc_digest,
+.setkey= bfin_crypto_crc_setkey,
+.halg.digestsize= CHKSUM_DIGEST_SIZE,
+.halg.base= {
+.cra_name= "hmac(crc32)",
+.cra_driver_name= DRIVER_NAME,
+.cra_priority= 100,
+.cra_flags= CRYPTO_ALG_TYPE_AHASH |
+CRYPTO_ALG_ASYNC,
+.cra_blocksize= CHKSUM_BLOCK_SIZE,
+.cra_ctxsize= sizeof(struct bfin_crypto_crc_ctx),
+.cra_alignmask= 3,
+.cra_module= THIS_MODULE,
+.cra_init= bfin_crypto_crc_cra_init,
+.cra_exit= bfin_crypto_crc_cra_exit,
+}
+};
+
+static void bfin_crypto_crc_done_task(unsigned long data)
+{
+struct bfin_crypto_crc *crc = (struct bfin_crypto_crc *)data;
+
+bfin_crypto_crc_handle_queue(crc, NULL);
+}
+
+static irqreturn_t bfin_crypto_crc_handler(int irq, void *dev_id)
+{
+struct bfin_crypto_crc *crc = dev_id;
+
+if (crc-&amp;gt;regs-&amp;gt;status &amp;amp; DCNTEXP) {
+crc-&amp;gt;regs-&amp;gt;status = DCNTEXP;
+SSYNC();
+
+/* prepare results */
+*(__le32 *)crc-&amp;gt;req-&amp;gt;result =
+cpu_to_le32p((u32 *)&amp;amp;crc-&amp;gt;regs-&amp;gt;result);
+
+crc-&amp;gt;regs-&amp;gt;control &amp;amp;= ~BLKEN;
+crc-&amp;gt;busy = 0;
+
+if (crc-&amp;gt;req-&amp;gt;base.complete)
+crc-&amp;gt;req-&amp;gt;base.complete(&amp;amp;crc-&amp;gt;req-&amp;gt;base, 0);
+
+tasklet_schedule(&amp;amp;crc-&amp;gt;done_task);
+
+return IRQ_HANDLED;
+} else
+return IRQ_NONE;
+}
+
+#ifdef CONFIG_PM
+/**
+ *bfin_crypto_crc_suspend - suspend crc device
+ *&amp;lt; at &amp;gt;pdev: device being suspended
+ *&amp;lt; at &amp;gt;state: requested suspend state
+ */
+static int bfin_crypto_crc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+struct bfin_crypto_crc *crc = platform_get_drvdata(pdev);
+int i = 100000;
+
+while ((crc-&amp;gt;regs-&amp;gt;control &amp;amp; BLKEN) &amp;amp;&amp;amp; --i)
+cpu_relax();
+
+if (i == 0)
+crc-&amp;gt;regs-&amp;gt;control &amp;amp;= ~BLKEN;
+
+return 0;
+}
+
+/**
+ *bfin_crypto_crc_resume - resume crc device
+ *&amp;lt; at &amp;gt;pdev: device being resumed
+ */
+static int bfin_crypto_crc_resume(struct platform_device *pdev)
+{
+return 0;
+}
+#else
+# define bfin_crypto_crc_suspend NULL
+# define bfin_crypto_crc_resume NULL
+#endif
+
+/**
+ *bfin_crypto_crc_probe - Initialize module
+ *
+ */
+static int __devinit bfin_crypto_crc_probe(struct platform_device *pdev)
+{
+struct device *dev = &amp;amp;pdev-&amp;gt;dev;
+struct resource *res;
+struct bfin_crypto_crc *crc = NULL;
+unsigned int timeout = 100000;
+int ret;
+
+crc = kzalloc(sizeof(*crc), GFP_KERNEL);
+if (!crc) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "fail to malloc bfin_crypto_crc\n");
+return -ENOMEM;
+}
+
+crc-&amp;gt;dev = dev;
+
+INIT_LIST_HEAD(&amp;amp;crc-&amp;gt;list);
+spin_lock_init(&amp;amp;crc-&amp;gt;lock);
+tasklet_init(&amp;amp;crc-&amp;gt;done_task, bfin_crypto_crc_done_task, (unsigned long)crc);
+crypto_init_queue(&amp;amp;crc-&amp;gt;queue, CRC_CCRYPTO_QUEUE_LENGTH);
+
+res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+if (res == NULL) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "Cannot get IORESOURCE_MEM\n");
+ret = -ENOENT;
+goto out_error_free_mem;
+}
+
+crc-&amp;gt;regs = ioremap(res-&amp;gt;start, resource_size(res));
+if (!crc-&amp;gt;regs) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "Cannot map CRC IO\n");
+ret = -ENXIO;
+goto out_error_free_mem;
+}
+
+crc-&amp;gt;irq = platform_get_irq(pdev, 0);
+if (crc-&amp;gt;irq &amp;lt; 0) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "No CRC DCNTEXP IRQ specified\n");
+ret = -ENOENT;
+goto out_error_unmap;
+}
+
+ret = request_irq(crc-&amp;gt;irq, bfin_crypto_crc_handler, IRQF_SHARED, DRIVER_NAME, crc);
+if (ret) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "Unable to request blackfin crc irq\n");
+goto out_error_unmap;
+}
+
+res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+if (res == NULL) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "No CRC DMA channel specified\n");
+ret = -ENOENT;
+goto out_error_irq;
+}
+crc-&amp;gt;dma_ch = res-&amp;gt;start;
+
+ret = request_dma(crc-&amp;gt;dma_ch, DRIVER_NAME);
+if (ret) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "Unable to attach Blackfin CRC DMA channel\n");
+goto out_error_irq;
+}
+
+crc-&amp;gt;sg_cpu = dma_alloc_coherent(&amp;amp;pdev-&amp;gt;dev, PAGE_SIZE, &amp;amp;crc-&amp;gt;sg_dma, GFP_KERNEL);
+if (crc-&amp;gt;sg_cpu == NULL) {
+ret = -ENOMEM;
+goto out_error_dma;
+}
+/* need at most CRC_MAX_DMA_DESC sg + CRC_MAX_DMA_DESC middle  +
+   1 last + 1 next dma descriptors
+ */
+crc-&amp;gt;sg_mid_buf = (u8 *)(crc-&amp;gt;sg_cpu + ((CRC_MAX_DMA_DESC + 1) &amp;lt;&amp;lt; 1));
+
+crc-&amp;gt;regs-&amp;gt;control = 0;
+SSYNC();
+crc-&amp;gt;regs-&amp;gt;poly = crc-&amp;gt;poly = (u32)pdev-&amp;gt;dev.platform_data;
+SSYNC();
+
+while (!(crc-&amp;gt;regs-&amp;gt;status &amp;amp; LUTDONE) &amp;amp;&amp;amp; (--timeout) &amp;gt; 0)
+cpu_relax();
+
+if (timeout == 0)
+dev_info(&amp;amp;pdev-&amp;gt;dev, "init crc poly timeout\n");
+
+spin_lock(&amp;amp;crc_list.lock);
+list_add(&amp;amp;crc-&amp;gt;list, &amp;amp;crc_list.dev_list);
+spin_unlock(&amp;amp;crc_list.lock);
+
+platform_set_drvdata(pdev, crc);
+
+ret = crypto_register_ahash(&amp;amp;algs);
+if (ret) {
+spin_lock(&amp;amp;crc_list.lock);
+list_del(&amp;amp;crc-&amp;gt;list);
+spin_unlock(&amp;amp;crc_list.lock);
+dev_err(&amp;amp;pdev-&amp;gt;dev, "Cann't register crypto ahash device\n");
+goto out_error_dma;
+}
+
+dev_info(&amp;amp;pdev-&amp;gt;dev, "initialized\n");
+
+return 0;
+
+out_error_dma:
+if (crc-&amp;gt;sg_cpu)
+dma_free_coherent(&amp;amp;pdev-&amp;gt;dev, PAGE_SIZE, crc-&amp;gt;sg_cpu, crc-&amp;gt;sg_dma);
+free_dma(crc-&amp;gt;dma_ch);
+out_error_irq:
+free_irq(crc-&amp;gt;irq, crc-&amp;gt;dev);
+out_error_unmap:
+iounmap((void *)crc-&amp;gt;regs);
+out_error_free_mem:
+kfree(crc);
+
+return ret;
+}
+
+/**
+ *bfin_crypto_crc_remove - Initialize module
+ *
+ */
+static int __devexit bfin_crypto_crc_remove(struct platform_device *pdev)
+{
+struct bfin_crypto_crc *crc = platform_get_drvdata(pdev);
+
+if (!crc)
+return -ENODEV;
+
+spin_lock(&amp;amp;crc_list.lock);
+list_del(&amp;amp;crc-&amp;gt;list);
+spin_unlock(&amp;amp;crc_list.lock);
+
+crypto_unregister_ahash(&amp;amp;algs);
+tasklet_kill(&amp;amp;crc-&amp;gt;done_task);
+iounmap((void *)crc-&amp;gt;regs);
+free_dma(crc-&amp;gt;dma_ch);
+if (crc-&amp;gt;irq &amp;gt; 0)
+free_irq(crc-&amp;gt;irq, crc-&amp;gt;dev);
+kfree(crc);
+
+return 0;
+}
+
+static struct platform_driver bfin_crypto_crc_driver = {
+.probe     = bfin_crypto_crc_probe,
+.remove    = __devexit_p(bfin_crypto_crc_remove),
+.suspend   = bfin_crypto_crc_suspend,
+.resume    = bfin_crypto_crc_resume,
+.driver    = {
+.name  = DRIVER_NAME,
+.owner = THIS_MODULE,
+},
+};
+
+/**
+ *bfin_crypto_crc_mod_init - Initialize module
+ *
+ *Checks the module params and registers the platform driver.
+ *Real work is in the platform probe function.
+ */
+static int __init bfin_crypto_crc_mod_init(void)
+{
+int ret;
+
+pr_info("Blackfin hardware CRC crypto driver\n");
+
+INIT_LIST_HEAD(&amp;amp;crc_list.dev_list);
+spin_lock_init(&amp;amp;crc_list.lock);
+
+ret = platform_driver_register(&amp;amp;bfin_crypto_crc_driver);
+if (ret) {
+pr_info(KERN_ERR "unable to register driver\n");
+return ret;
+}
+
+return 0;
+}
+
+/**
+ *bfin_crypto_crc_mod_exit - Deinitialize module
+ */
+static void __exit bfin_crypto_crc_mod_exit(void)
+{
+platform_driver_unregister(&amp;amp;bfin_crypto_crc_driver);
+}
+
+module_init(bfin_crypto_crc_mod_init);
+module_exit(bfin_crypto_crc_mod_exit);
+
+MODULE_AUTHOR("Sonic Zhang &amp;lt;sonic.zhang&amp;lt; at &amp;gt;analog.com&amp;gt;");
+MODULE_DESCRIPTION("Blackfin CRC hardware crypto driver");
+MODULE_LICENSE("GPL");
&lt;/pre&gt;</description>
    <dc:creator>Sonic Zhang</dc:creator>
    <dc:date>2012-05-25T09:54:14</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7057">
    <title>[PATCH] crypto: sha1 - use Kbuild supplied flags for AVX test</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7057</link>
    <description>&lt;pre&gt;Commit ea4d26ae ("raid5: add AVX optimized RAID5 checksumming")
introduced x86/ arch wide defines for AFLAGS and CFLAGS indicating AVX
support in binutils based on the same test we have in x86/crypto/ right
now. To minimize duplication drop our implementation in favour to the
one in x86/.

Signed-off-by: Mathias Krause &amp;lt;minipli&amp;lt; at &amp;gt;googlemail.com&amp;gt;
---

This should be applied to cryptodev-2.6.git after it contains the above
mentioned commit, e.g. after cryptodev-2.6.git rebased to/merged v3.5-rc1.

 arch/x86/crypto/Makefile          |    7 -------
 arch/x86/crypto/sha1_ssse3_asm.S  |    2 +-
 arch/x86/crypto/sha1_ssse3_glue.c |    6 +++---
 3 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index e191ac0..479f95a 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -34,12 +34,5 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
 serpent-sse2-x86_64-y := serpent-sse2-x86_64-asm_64.o serpent_sse2_glue.o
 
 aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
-
 ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
-
-# enable AVX support only when $(AS) can actually assemble the instructions
-ifeq ($(call as-instr,vpxor %xmm0$(comma)%xmm1$(comma)%xmm2,yes,no),yes)
-AFLAGS_sha1_ssse3_asm.o += -DSHA1_ENABLE_AVX_SUPPORT
-CFLAGS_sha1_ssse3_glue.o += -DSHA1_ENABLE_AVX_SUPPORT
-endif
 sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
diff --git a/arch/x86/crypto/sha1_ssse3_asm.S b/arch/x86/crypto/sha1_ssse3_asm.S
index b2c2f57..49d6987 100644
--- a/arch/x86/crypto/sha1_ssse3_asm.S
+++ b/arch/x86/crypto/sha1_ssse3_asm.S
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -468,7 +468,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; W_PRECALC_SSSE3
  */
 SHA1_VECTOR_ASM     sha1_transform_ssse3
 
-#ifdef SHA1_ENABLE_AVX_SUPPORT
+#ifdef CONFIG_AS_AVX
 
 .macro W_PRECALC_AVX
 
diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c
index f916499..4a11a9d 100644
--- a/arch/x86/crypto/sha1_ssse3_glue.c
+++ b/arch/x86/crypto/sha1_ssse3_glue.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -35,7 +35,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 
 asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data,
      unsigned int rounds);
-#ifdef SHA1_ENABLE_AVX_SUPPORT
+#ifdef CONFIG_AS_AVX
 asmlinkage void sha1_transform_avx(u32 *digest, const char *data,
    unsigned int rounds);
 #endif
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -184,7 +184,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct shash_alg alg = {
 }
 };
 
-#ifdef SHA1_ENABLE_AVX_SUPPORT
+#ifdef CONFIG_AS_AVX
 static bool __init avx_usable(void)
 {
 u64 xcr0;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -209,7 +209,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int __init sha1_ssse3_mod_init(void)
 if (cpu_has_ssse3)
 sha1_transform_asm = sha1_transform_ssse3;
 
-#ifdef SHA1_ENABLE_AVX_SUPPORT
+#ifdef CONFIG_AS_AVX
 /* allow AVX to override SSSE3, it's a little faster */
 if (avx_usable())
 sha1_transform_asm = sha1_transform_avx;
&lt;/pre&gt;</description>
    <dc:creator>Mathias Krause</dc:creator>
    <dc:date>2012-05-24T09:13:42</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7056">
    <title>Re: Crypto Update for 3.5</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7056</link>
    <description>&lt;pre&gt;
It should go. For all I can tell, this was the result of Lee Jones
doing major cleanups to the ux500 platform for this merge window
in parallel with the crypto driver getting added following the
older code pattern. The crypto patch had to be reworked for this
and apparently a hunk from the older version survived.

The entire file in which it was added is going to be removed
in one of the next kernel versions once we can boot all ux500 machines
using only device tree definitions, so it will be taken care of.

Arnd
&lt;/pre&gt;</description>
    <dc:creator>Arnd Bergmann</dc:creator>
    <dc:date>2012-05-24T08:36:24</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7055">
    <title>Re: Crypto Update for 3.5</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7055</link>
    <description>&lt;pre&gt;On Thu, May 24, 2012 at 1:06 AM, Linus Torvalds
&amp;lt;torvalds&amp;lt; at &amp;gt;linux-foundation.org&amp;gt; wrote:


AFAICT this was retrofitted to get a booting kernel on
the cryptodev base which was based on something old like
v3.2 just some weeks back. (Now it's upgraded to mainline, great!)

Greg was pushing for us to allocate all devices dynamically at
one point, but there was no real infrastructure for it and some local
implementations to meet that requirement, that's why these
functions pop up and down. We're working on it with device tree
etc, mea culpa...

Yours,
Linus Walleij
&lt;/pre&gt;</description>
    <dc:creator>Linus Walleij</dc:creator>
    <dc:date>2012-05-24T07:03:52</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7054">
    <title>Re: Crypto Update for 3.5</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7054</link>
    <description>&lt;pre&gt;
I can't see why that was added there either.

Adding Arnd/Linus Walleij to see if they can tell us whether
it should go or stay.

Thanks,
&lt;/pre&gt;</description>
    <dc:creator>Herbert Xu</dc:creator>
    <dc:date>2012-05-24T00:21:26</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7053">
    <title>Re: Crypto Update for 3.5</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7053</link>
    <description>&lt;pre&gt;
I pulled this, but quite frankly, some of it looks like utter garbage.

There's a declaration for dbx500_add_platform_device_noirq() that does
not exist and is not used anywhere. Why? It was added in commit
585d188f8072, and I see no rhyme or reason to it.

I only noticed because I happened to get a conflict due to the
location it was added. I removed it. WTF is going on?

                         Linus
&lt;/pre&gt;</description>
    <dc:creator>Linus Torvalds</dc:creator>
    <dc:date>2012-05-23T23:06:35</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7052">
    <title>Crypto Update for 3.5</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7052</link>
    <description>&lt;pre&gt;Hi Linus:

Here is the crypto update for 3.5:

* New cipher/hash driver for ARM ux500.
* Code clean-up for aesni-intel.
* Misc fixes.


Please pull from

git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git


Andreas Westin (5):
      crypto: ux500 - Add driver for CRYP hardware
      crypto: ux500 - Add driver for HASH hardware
      mach-ux500: crypto - core support for CRYP/HASH module.
      crypto: ux500 - Update DMA handling for 3.4
      crypto: ux500 - Cleanup hardware identification

Borislav Petkov (1):
      crypto, xor: Sanitize checksumming function selection output

Julia Lawall (2):
      crypto: crypto4xx - move up err_request_irq label
      hwrng: omap - use devm_request_and_ioremap

Jussi Kivilinna (2):
      crypto: aesni-intel - use crypto_[un]register_algs
      crypto: aesni-intel - move more common code to ablk_init_common

Nicolas Ferre (1):
      hwrng: Kconfig - modify default state for atmel-rng driver

Shengzhou Liu (1):
      crypto: caam - add backward compatible string sec4.0

 arch/arm/mach-ux500/board-mop500.c              |   48 
 arch/arm/mach-ux500/clock.c                     |   18 
 arch/arm/mach-ux500/devices-common.h            |   54 
 arch/arm/mach-ux500/devices-db8500.c            |    3 
 arch/arm/mach-ux500/devices-db8500.h            |    4 
 arch/arm/mach-ux500/include/mach/crypto-ux500.h |   22 
 arch/arm/mach-ux500/include/mach/devices.h      |    3 
 arch/arm/mach-ux500/include/mach/hardware.h     |    3 
 arch/x86/crypto/aesni-intel_glue.c              |  827 +++------
 crypto/xor.c                                    |    5 
 drivers/char/hw_random/Kconfig                  |    2 
 drivers/char/hw_random/omap-rng.c               |   22 
 drivers/crypto/Kconfig                          |   11 
 drivers/crypto/Makefile                         |    1 
 drivers/crypto/amcc/crypto4xx_core.c            |    2 
 drivers/crypto/caam/caamalg.c                   |   14 
 drivers/crypto/caam/ctrl.c                      |   16 
 drivers/crypto/ux500/Kconfig                    |   30 
 drivers/crypto/ux500/Makefile                   |    8 
 drivers/crypto/ux500/cryp/Makefile              |   13 
 drivers/crypto/ux500/cryp/cryp.c                |  401 ++++
 drivers/crypto/ux500/cryp/cryp.h                |  308 +++
 drivers/crypto/ux500/cryp/cryp_core.c           | 1790 +++++++++++++++++++++
 drivers/crypto/ux500/cryp/cryp_irq.c            |   45 
 drivers/crypto/ux500/cryp/cryp_irq.h            |   31 
 drivers/crypto/ux500/cryp/cryp_irqp.h           |  125 +
 drivers/crypto/ux500/cryp/cryp_p.h              |  125 +
 drivers/crypto/ux500/hash/Makefile              |   11 
 drivers/crypto/ux500/hash/hash_alg.h            |  395 ++++
 drivers/crypto/ux500/hash/hash_core.c           | 2031 +++++++++++++++++++++++-
 30 files changed, 5819 insertions(+), 549 deletions(-)
 
Thanks,
&lt;/pre&gt;</description>
    <dc:creator>Herbert Xu</dc:creator>
    <dc:date>2012-05-23T01:35:28</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7051">
    <title>[RFC/PATCH] crypto: talitos - replace the tasklet implementation with NAPI</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7051</link>
    <description>&lt;pre&gt;Hi,

During performance measurements &amp;amp; optimization phase, we found out that we get
better numbers (in the range of 9-10%) by using the NAPI approach for the
crypto engine interrupt mechanism instead of tasklet.
We found out that for the tasklet-based interrupt mechanism, we were facing
imbalanced processing - NET RX softirq was running more frequently than the
crypto tasklet.

The patch replaces the tasklet-based implementation with NAPI. It is based on
latest crypto-2.6 tree.

I am aware of the fact that using NAPI for anything else than net devices might
be frowned upon, that's why I am adding the netdev folks to comment, advise.

Thanks,
Horia


From 30f6247fa5ada7e53523492ca4e70b61e3f5aeeb Mon Sep 17 00:00:00 2001
From: Horia Geanta &amp;lt;horia.geanta&amp;lt; at &amp;gt;freescale.com&amp;gt;
Date: Wed, 2 May 2012 18:40:03 +0300
Subject: [RFC/PATCH] crypto: talitos - replace the tasklet implementation with NAPI

This patch updates the current tasklet implement to NAPI so as
the system is more balanced in the terms that the packet submission
and the packet forwarding after being processed can be done at
the same priority.

Signed-off-by: Sandeep Malik &amp;lt;Sandeep.Malik&amp;lt; at &amp;gt;freescale.com&amp;gt;
Signed-off-by: Horia Geanta &amp;lt;horia.geanta&amp;lt; at &amp;gt;freescale.com&amp;gt;
---
 drivers/crypto/Kconfig   |    2 +-
 drivers/crypto/talitos.c |  148 +++++++++++++++++++++++++++++++++-------------
 drivers/crypto/talitos.h |    4 +-
 3 files changed, 110 insertions(+), 44 deletions(-)

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index ab9abb4..934fa57 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -209,7 +209,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; config CRYPTO_DEV_TALITOS
 select CRYPTO_ALGAPI
 select CRYPTO_AUTHENC
 select HW_RANDOM
-depends on FSL_SOC
+depends on FSL_SOC &amp;amp;&amp;amp; NET
 help
   Say 'Y' here to use the Freescale Security Engine (SEC)
   to offload cryptographic algorithm computation.
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 921039e..817f74c 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1,7 +1,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 /*
  * talitos - Freescale Integrated Security Engine (SEC) device driver
  *
- * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (c) 2008-2012 Freescale Semiconductor, Inc.
  *
  * Scatterlist Crypto API glue code copied from files with the following:
  * Copyright (c) 2006-2007 Herbert Xu &amp;lt;herbert&amp;lt; at &amp;gt;gondor.apana.org.au&amp;gt;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -37,6 +37,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 #include &amp;lt;linux/io.h&amp;gt;
 #include &amp;lt;linux/spinlock.h&amp;gt;
 #include &amp;lt;linux/rtnetlink.h&amp;gt;
+#include &amp;lt;linux/netdevice.h&amp;gt;
 #include &amp;lt;linux/slab.h&amp;gt;
 
 #include &amp;lt;crypto/algapi.h&amp;gt;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -121,6 +122,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct talitos_channel {
 struct talitos_private {
 struct device *dev;
 struct platform_device *ofdev;
+struct net_device __percpu *netdev;
 void __iomem *reg;
 int irq[2];
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -148,8 +150,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct talitos_private {
 /* next channel to be assigned next incoming descriptor */
 atomic_t last_chan ____cacheline_aligned;
 
-/* request callback tasklet */
-struct tasklet_struct done_task[2];
+/* request callback napi */
+struct napi_struct __percpu *done_task[2];
 
 /* list of registered algorithms */
 struct list_head alg_list;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -352,17 +354,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
 /*
  * process what was done, notify callback of error if not
  */
-static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
+static int flush_channel(struct device *dev, int ch, int error, int reset_ch,
+ int weight)
 {
 struct talitos_private *priv = dev_get_drvdata(dev);
 struct talitos_request *request, saved_req;
 unsigned long flags;
-int tail, status;
+int tail, status, count = 0;
 
 spin_lock_irqsave(&amp;amp;priv-&amp;gt;chan[ch].tail_lock, flags);
 
 tail = priv-&amp;gt;chan[ch].tail;
-while (priv-&amp;gt;chan[ch].fifo[tail].desc) {
+while (priv-&amp;gt;chan[ch].fifo[tail].desc &amp;amp;&amp;amp; (count &amp;lt; weight)) {
 request = &amp;amp;priv-&amp;gt;chan[ch].fifo[tail];
 
 /* descriptors with their done bits set don't get the error */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -399,46 +402,57 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
    status);
 /* channel may resume processing in single desc error case */
 if (error &amp;amp;&amp;amp; !reset_ch &amp;amp;&amp;amp; status == error)
-return;
+return 0;
+count++;
 spin_lock_irqsave(&amp;amp;priv-&amp;gt;chan[ch].tail_lock, flags);
 tail = priv-&amp;gt;chan[ch].tail;
 }
 
 spin_unlock_irqrestore(&amp;amp;priv-&amp;gt;chan[ch].tail_lock, flags);
+
+return count;
 }
 
 /*
  * process completed requests for channels that have done status
  */
-#define DEF_TALITOS_DONE(name, ch_done_mask)\
-static void talitos_done_##name(unsigned long data)\
+#define DEF_TALITOS_DONE(name, ch_done_mask, num_ch)\
+static int talitos_done_##name(struct napi_struct *napi, int budget)\
 {\
-struct device *dev = (struct device *)data;\
+struct device *dev = &amp;amp;napi-&amp;gt;dev-&amp;gt;dev;\
 struct talitos_private *priv = dev_get_drvdata(dev);\
+int budget_per_ch = budget / num_ch, work_done = 0;\
 unsigned long flags;\
 \
 if (ch_done_mask &amp;amp; 1)\
-flush_channel(dev, 0, 0, 0);\
+work_done += flush_channel(dev, 0, 0, 0, budget_per_ch);\
 if (priv-&amp;gt;num_channels == 1)\
 goto out;\
 if (ch_done_mask &amp;amp; (1 &amp;lt;&amp;lt; 2))\
-flush_channel(dev, 1, 0, 0);\
+work_done += flush_channel(dev, 1, 0, 0, budget_per_ch);\
 if (ch_done_mask &amp;amp; (1 &amp;lt;&amp;lt; 4))\
-flush_channel(dev, 2, 0, 0);\
+work_done += flush_channel(dev, 2, 0, 0, budget_per_ch);\
 if (ch_done_mask &amp;amp; (1 &amp;lt;&amp;lt; 6))\
-flush_channel(dev, 3, 0, 0);\
+work_done += flush_channel(dev, 3, 0, 0, budget_per_ch);\
 \
 out:\
-/* At this point, all completed channels have been processed */\
-/* Unmask done interrupts for channels completed later on. */\
-spin_lock_irqsave(&amp;amp;priv-&amp;gt;reg_lock, flags);\
-setbits32(priv-&amp;gt;reg + TALITOS_IMR, ch_done_mask);\
-setbits32(priv-&amp;gt;reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);\
-spin_unlock_irqrestore(&amp;amp;priv-&amp;gt;reg_lock, flags);\
+if (work_done &amp;lt; budget) {\
+napi_complete(napi);\
+/* At this point, all completed channels have been */\
+/* processed. Unmask done interrupts for channels */\
+/* completed later on. */\
+spin_lock_irqsave(&amp;amp;priv-&amp;gt;reg_lock, flags);\
+setbits32(priv-&amp;gt;reg + TALITOS_IMR, ch_done_mask);\
+setbits32(priv-&amp;gt;reg + TALITOS_IMR_LO,\
+  TALITOS_IMR_LO_INIT);\
+spin_unlock_irqrestore(&amp;amp;priv-&amp;gt;reg_lock, flags);\
+}\
+\
+return work_done;\
 }
-DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
-DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
-DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
+DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE, 4)
+DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE, 2)
+DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE, 2)
 
 /*
  * locate current (offending) descriptor
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -588,7 +602,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
 if (v_lo &amp;amp; TALITOS_CCPSR_LO_SRL)
 dev_err(dev, "scatter return/length error\n");
 
-flush_channel(dev, ch, error, reset_ch);
+flush_channel(dev, ch, error, reset_ch, priv-&amp;gt;fifo_len);
 
 if (reset_ch) {
 reset_channel(dev, ch);
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -612,14 +626,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
 
 /* purge request queues */
 for (ch = 0; ch &amp;lt; priv-&amp;gt;num_channels; ch++)
-flush_channel(dev, ch, -EIO, 1);
+flush_channel(dev, ch, -EIO, 1, priv-&amp;gt;fifo_len);
 
 /* reset and reinitialize the device */
 init_device(dev);
 }
 }
 
-#define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet)       \
+#define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, sirq)       \
 static irqreturn_t talitos_interrupt_##name(int irq, void *data)       \
 {       \
 struct device *dev = data;       \
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -643,7 +657,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static irqreturn_t talitos_interrupt_##name(int irq, void *data)       \
 /* mask further done interrupts. */       \
 clrbits32(priv-&amp;gt;reg + TALITOS_IMR, ch_done_mask);      \
 /* done_task will unmask done interrupts at exit */    \
-tasklet_schedule(&amp;amp;priv-&amp;gt;done_task[tlet]);       \
+napi_schedule(per_cpu_ptr(priv-&amp;gt;done_task[sirq],       \
+  smp_processor_id()));       \
 }       \
 spin_unlock_irqrestore(&amp;amp;priv-&amp;gt;reg_lock, flags);       \
 }       \
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2567,7 +2582,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int talitos_remove(struct platform_device *ofdev)
 struct device *dev = &amp;amp;ofdev-&amp;gt;dev;
 struct talitos_private *priv = dev_get_drvdata(dev);
 struct talitos_crypto_alg *t_alg, *n;
-int i;
+int i, j;
 
 list_for_each_entry_safe(t_alg, n, &amp;amp;priv-&amp;gt;alg_list, entry) {
 switch (t_alg-&amp;gt;algt.type) {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2586,25 +2601,32 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int talitos_remove(struct platform_device *ofdev)
 if (hw_supports(dev, DESC_HDR_SEL0_RNG))
 talitos_unregister_rng(dev);
 
-for (i = 0; i &amp;lt; priv-&amp;gt;num_channels; i++)
-kfree(priv-&amp;gt;chan[i].fifo);
-
-kfree(priv-&amp;gt;chan);
-
 for (i = 0; i &amp;lt; 2; i++)
 if (priv-&amp;gt;irq[i]) {
 free_irq(priv-&amp;gt;irq[i], dev);
 irq_dispose_mapping(priv-&amp;gt;irq[i]);
+
+for_each_possible_cpu(j) {
+napi_disable(per_cpu_ptr(priv-&amp;gt;done_task[i],
+ j));
+netif_napi_del(per_cpu_ptr(priv-&amp;gt;done_task[i],
+   j));
+}
+
+free_percpu(priv-&amp;gt;done_task[i]);
 }
 
-tasklet_kill(&amp;amp;priv-&amp;gt;done_task[0]);
-if (priv-&amp;gt;irq[1])
-tasklet_kill(&amp;amp;priv-&amp;gt;done_task[1]);
+for (i = 0; i &amp;lt; priv-&amp;gt;num_channels; i++)
+kfree(priv-&amp;gt;chan[i].fifo);
+
+kfree(priv-&amp;gt;chan);
 
 iounmap(priv-&amp;gt;reg);
 
 dev_set_drvdata(dev, NULL);
 
+free_percpu(priv-&amp;gt;netdev);
+
 kfree(priv);
 
 return 0;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -2730,21 +2752,63 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int talitos_probe(struct platform_device *ofdev)
 dev_set_drvdata(dev, priv);
 
 priv-&amp;gt;ofdev = ofdev;
+priv-&amp;gt;dev = dev;
 
 spin_lock_init(&amp;amp;priv-&amp;gt;reg_lock);
 
+priv-&amp;gt;netdev = alloc_percpu(struct net_device);
+if (!priv-&amp;gt;netdev) {
+dev_err(dev, "failed to allocate netdevice\n");
+err = -ENOMEM;
+goto err_out;
+}
+
+for_each_possible_cpu(i) {
+err = init_dummy_netdev(per_cpu_ptr(priv-&amp;gt;netdev, i));
+if (err) {
+dev_err(dev, "failed to initialize dummy netdevice\n");
+goto err_out;
+}
+(per_cpu_ptr(priv-&amp;gt;netdev, i))-&amp;gt;dev = *dev;
+}
+
 err = talitos_probe_irq(ofdev);
 if (err)
 goto err_out;
 
+priv-&amp;gt;done_task[0] = alloc_percpu(struct napi_struct);
+if (!priv-&amp;gt;done_task[0]) {
+dev_err(dev, "failed to allocate napi for 1st irq\n");
+err = -ENOMEM;
+goto err_out;
+}
+
 if (!priv-&amp;gt;irq[1]) {
-tasklet_init(&amp;amp;priv-&amp;gt;done_task[0], talitos_done_4ch,
-     (unsigned long)dev);
+for_each_possible_cpu(i) {
+netif_napi_add(per_cpu_ptr(priv-&amp;gt;netdev, i),
+       per_cpu_ptr(priv-&amp;gt;done_task[0], i),
+talitos_done_4ch, TALITOS_NAPI_WEIGHT);
+napi_enable(per_cpu_ptr(priv-&amp;gt;done_task[0], i));
+}
 } else {
-tasklet_init(&amp;amp;priv-&amp;gt;done_task[0], talitos_done_ch0_2,
-     (unsigned long)dev);
-tasklet_init(&amp;amp;priv-&amp;gt;done_task[1], talitos_done_ch1_3,
-     (unsigned long)dev);
+priv-&amp;gt;done_task[1] = alloc_percpu(struct napi_struct);
+if (!priv-&amp;gt;done_task[1]) {
+dev_err(dev, "failed to allocate napi for 2nd irq\n");
+err = -ENOMEM;
+goto err_out;
+}
+
+for_each_possible_cpu(i) {
+netif_napi_add(per_cpu_ptr(priv-&amp;gt;netdev, i),
+       per_cpu_ptr(priv-&amp;gt;done_task[0], i),
+       talitos_done_ch0_2, TALITOS_NAPI_WEIGHT);
+napi_enable(per_cpu_ptr(priv-&amp;gt;done_task[0], i));
+
+netif_napi_add(per_cpu_ptr(priv-&amp;gt;netdev, i),
+       per_cpu_ptr(priv-&amp;gt;done_task[1], i),
+       talitos_done_ch1_3, TALITOS_NAPI_WEIGHT);
+napi_enable(per_cpu_ptr(priv-&amp;gt;done_task[1], i));
+}
 }
 
 INIT_LIST_HEAD(&amp;amp;priv-&amp;gt;alg_list);
diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h
index 3c17395..3fe0e36 100644
--- a/drivers/crypto/talitos.h
+++ b/drivers/crypto/talitos.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1,7 +1,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 /*
  * Freescale SEC (talitos) device register and descriptor header defines
  *
- * Copyright (c) 2006-2011 Freescale Semiconductor, Inc.
+ * Copyright (c) 2006-2012 Freescale Semiconductor, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -28,6 +28,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
  *
  */
 
+#define TALITOS_NAPI_WEIGHT22
+
 /*
  * TALITOS_xxx_LO addresses point to the low data bits (32-63) of the register
  */
&lt;/pre&gt;</description>
    <dc:creator>Horia Geanta</dc:creator>
    <dc:date>2012-05-21T16:53:35</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7050">
    <title>免交40万留学保证金，打造平民化的出国留学服务，爱尔兰名校等您来深造</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7050</link>
    <description>&lt;pre&gt;您还在为家庭不够富裕，而不能让品学兼优的孩子出国深造而苦恼吗？
您还在为国内教育资源分配严重不均，而不能让自己的孩子获得理想的教育环境而发愁吗？

免交40万留学保证金，打造平民化的出国留学服务！
让工薪家庭孩子也可以一圆出国留学梦！

爱尔兰名校等您来深造！
想了解详情的请联系QQ: 2636882155   或者立即回复邮箱: 2636882155&amp;lt; at &amp;gt;qq.com
想了解详情的请联系QQ: 2636882155   或者立即回复邮箱: 2636882155&amp;lt; at &amp;gt;qq.com
想了解详情的请联系QQ: 2636882155   或者立即回复邮箱: 2636882155&amp;lt; at &amp;gt;qq.com
 
 
现诚招全国各地出国留学顾问。
零风险！高回报！共享朝阳般的教育产业大蛋糕！
请联系QQ: 2636882155
请联系QQ: 2636882155
请联系QQ: 2636882155
&lt;/pre&gt;</description>
    <dc:creator>平民化的出国留学服务</dc:creator>
    <dc:date>2012-05-21T11:08:24</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7049">
    <title>Streaming Service</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7049</link>
    <description>&lt;pre&gt;Our Streaming Server is powerful and optimized server for live and on-demand audio/ video streaming content delivery. 
Our Streaming Server features with high performance streaming throughput, network &amp;amp; storage I/O and optimized configurations for its high scalability and reliability.
Our server supports latest Windows Media Technologies such as Fast Streaming, Fast Cache, Fast Start, Wireless Streaming as well as feature-rich add-on modules such as sophisticated content management, monitoring, logging reports, billing, authentications, load-balancing &amp;amp; clustering for all needs. 

Pls send us email for further information.Thanks,

Boris 
boris&amp;lt; at &amp;gt;dedicatedserver.com.hk

If you do not wish to further receive this event message, email "borislamsv2&amp;lt; at &amp;gt;gmail.com" to unsubscribe this message or remove your email from the list.


&lt;/pre&gt;</description>
    <dc:creator>boris&lt; at &gt;dedicatedserver.com.hk</dc:creator>
    <dc:date>2012-05-15T19:35:20</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7048">
    <title>Re: [PATCH 1/2] crypto: aesni-intel: use crypto_[un]register_algs</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7048</link>
    <description>&lt;pre&gt;
Both patches applied.  Thanks Jussi.
&lt;/pre&gt;</description>
    <dc:creator>Herbert Xu</dc:creator>
    <dc:date>2012-05-15T07:28:04</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7047">
    <title>Re: [PATCH v2 0/3] Update for ux500 CRYP and HASH</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7047</link>
    <description>&lt;pre&gt;
All applied.  Thanks a lot!
&lt;/pre&gt;</description>
    <dc:creator>Herbert Xu</dc:creator>
    <dc:date>2012-05-15T07:26:11</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7046">
    <title>Will You Be Trusted?</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7046</link>
    <description>&lt;pre&gt;

Dear Friend,

As you read this, I don't want you to feel sorry for me,because, I
believe everyone will die someday,and am contacting you because
I really do need your help and I want you to help me with all your
effort and time for just seven to fourteen workings days of your time.I
want you to be honest and truthful with me that you will help me
with my last wish as a dying man.

Please i need a reliable person who will usethe Money($18 milliondollars)to
build orphanage home or charity organization.

Please kindly reply to my most confidential email if you are really
interested in helping me please: mr.saeed01&amp;lt; at &amp;gt;linuxmail.org


God be with you.

Mr.Saeed Ahmed.

----------------------------------------------------------------
FME Webmail
www.educacao.niteroi.rj.gov.br

&lt;/pre&gt;</description>
    <dc:creator>Mr.Saeed Ahmed.</dc:creator>
    <dc:date>2012-05-09T06:27:58</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7045">
    <title>[PATCH v4 13/17] powerpc: crypto: SHA256 hash routines for nx encryption</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7045</link>
    <description>&lt;pre&gt;These routines add support for SHA-256 hashing on the Power7+ CPU's
in-Nest accelerator driver.

Signed-off-by: Kent Yoder &amp;lt;key&amp;lt; at &amp;gt;linux.vnet.ibm.com&amp;gt;
---
 drivers/crypto/nx/nx-sha256.c |  246 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 246 insertions(+), 0 deletions(-)
 create mode 100644 drivers/crypto/nx/nx-sha256.c

diff --git a/drivers/crypto/nx/nx-sha256.c b/drivers/crypto/nx/nx-sha256.c
new file mode 100644
index 0000000..9767315
--- /dev/null
+++ b/drivers/crypto/nx/nx-sha256.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,246 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/**
+ * SHA-256 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 &amp;lt;yoder1&amp;lt; at &amp;gt;us.ibm.com&amp;gt;
+ */
+
+#include &amp;lt;crypto/internal/hash.h&amp;gt;
+#include &amp;lt;crypto/sha.h&amp;gt;
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;asm/vio.h&amp;gt;
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+static int nx_sha256_init(struct shash_desc *desc)
+{
+struct sha256_state *sctx = shash_desc_ctx(desc);
+struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&amp;amp;desc-&amp;gt;tfm-&amp;gt;base);
+struct nx_sg *out_sg;
+
+nx_ctx_init(nx_ctx, HCOP_FC_SHA);
+
+memset(sctx, 0, sizeof *sctx);
+
+nx_ctx-&amp;gt;ap = &amp;amp;nx_ctx-&amp;gt;props[NX_PROPS_SHA256];
+
+NX_CPB_SET_DIGEST_SIZE(nx_ctx-&amp;gt;csbcpb, NX_DS_SHA256);
+out_sg = nx_build_sg_list(nx_ctx-&amp;gt;out_sg, (u8 *)sctx-&amp;gt;state,
+  SHA256_DIGEST_SIZE, nx_ctx-&amp;gt;ap-&amp;gt;sglen);
+nx_ctx-&amp;gt;op.outlen = (nx_ctx-&amp;gt;out_sg - out_sg) * sizeof(struct nx_sg);
+
+return 0;
+}
+
+static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
+    unsigned int len)
+{
+struct sha256_state *sctx = shash_desc_ctx(desc);
+struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&amp;amp;desc-&amp;gt;tfm-&amp;gt;base);
+struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx-&amp;gt;csbcpb;
+struct nx_sg *in_sg;
+u64 to_process, leftover;
+int rc = 0;
+
+if (NX_CPB_FDM(csbcpb) &amp;amp; NX_FDM_CONTINUATION) {
+/* we've hit the nx chip previously and we're updating again,
+ * so copy over the partial digest */
+memcpy(csbcpb-&amp;gt;cpb.sha256.input_partial_digest,
+       csbcpb-&amp;gt;cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
+}
+
+/* 2 cases for total data len:
+ *  1: &amp;lt;= SHA256_BLOCK_SIZE: copy into state, return 0
+ *  2: &amp;gt; SHA256_BLOCK_SIZE: process X blocks, copy in leftover
+ */
+if (len + sctx-&amp;gt;count &amp;lt;= SHA256_BLOCK_SIZE) {
+memcpy(sctx-&amp;gt;buf + sctx-&amp;gt;count, data, len);
+sctx-&amp;gt;count += len;
+goto out;
+}
+
+/* to_process: the SHA256_BLOCK_SIZE data chunk to process in this
+ * update */
+to_process = (sctx-&amp;gt;count + len) &amp;amp; ~(SHA256_BLOCK_SIZE - 1);
+leftover = (sctx-&amp;gt;count + len) &amp;amp; (SHA256_BLOCK_SIZE - 1);
+
+if (sctx-&amp;gt;count) {
+in_sg = nx_build_sg_list(nx_ctx-&amp;gt;in_sg, (u8 *)sctx-&amp;gt;buf,
+ sctx-&amp;gt;count, nx_ctx-&amp;gt;ap-&amp;gt;sglen);
+in_sg = nx_build_sg_list(in_sg, (u8 *)data,
+ to_process - sctx-&amp;gt;count,
+ nx_ctx-&amp;gt;ap-&amp;gt;sglen);
+nx_ctx-&amp;gt;op.inlen = (nx_ctx-&amp;gt;in_sg - in_sg) *
+sizeof(struct nx_sg);
+} else {
+in_sg = nx_build_sg_list(nx_ctx-&amp;gt;in_sg, (u8 *)data,
+ to_process, nx_ctx-&amp;gt;ap-&amp;gt;sglen);
+nx_ctx-&amp;gt;op.inlen = (nx_ctx-&amp;gt;in_sg - in_sg) *
+sizeof(struct nx_sg);
+}
+
+NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
+
+if (!nx_ctx-&amp;gt;op.inlen || !nx_ctx-&amp;gt;op.outlen) {
+rc = -EINVAL;
+goto out;
+}
+
+rc = nx_hcall_sync(nx_ctx, &amp;amp;nx_ctx-&amp;gt;op,
+   desc-&amp;gt;flags &amp;amp; CRYPTO_TFM_REQ_MAY_SLEEP);
+if (rc)
+goto out;
+
+atomic_inc(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;sha256_ops));
+
+/* copy the leftover back into the state struct */
+memcpy(sctx-&amp;gt;buf, data + len - leftover, leftover);
+sctx-&amp;gt;count = leftover;
+
+csbcpb-&amp;gt;cpb.sha256.message_bit_length += (u64)
+(csbcpb-&amp;gt;cpb.sha256.spbc * 8);
+
+/* everything after the first update is continuation */
+NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
+out:
+return rc;
+}
+
+static int nx_sha256_final(struct shash_desc *desc, u8 *out)
+{
+struct sha256_state *sctx = shash_desc_ctx(desc);
+struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&amp;amp;desc-&amp;gt;tfm-&amp;gt;base);
+struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx-&amp;gt;csbcpb;
+struct nx_sg *in_sg, *out_sg;
+int rc;
+
+if (NX_CPB_FDM(csbcpb) &amp;amp; NX_FDM_CONTINUATION) {
+/* we've hit the nx chip previously, now we're finalizing,
+ * so copy over the partial digest */
+memcpy(csbcpb-&amp;gt;cpb.sha256.input_partial_digest,
+       csbcpb-&amp;gt;cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
+}
+
+/* final is represented by continuing the operation and indicating that
+ * this is not an intermediate operation */
+NX_CPB_FDM(csbcpb) &amp;amp;= ~NX_FDM_INTERMEDIATE;
+
+csbcpb-&amp;gt;cpb.sha256.message_bit_length += (u64)(sctx-&amp;gt;count * 8);
+
+in_sg = nx_build_sg_list(nx_ctx-&amp;gt;in_sg, (u8 *)sctx-&amp;gt;buf,
+ sctx-&amp;gt;count, nx_ctx-&amp;gt;ap-&amp;gt;sglen);
+out_sg = nx_build_sg_list(nx_ctx-&amp;gt;out_sg, out, SHA256_DIGEST_SIZE,
+  nx_ctx-&amp;gt;ap-&amp;gt;sglen);
+nx_ctx-&amp;gt;op.inlen = (nx_ctx-&amp;gt;in_sg - in_sg) * sizeof(struct nx_sg);
+nx_ctx-&amp;gt;op.outlen = (nx_ctx-&amp;gt;out_sg - out_sg) * sizeof(struct nx_sg);
+
+if (!nx_ctx-&amp;gt;op.outlen) {
+rc = -EINVAL;
+goto out;
+}
+
+rc = nx_hcall_sync(nx_ctx, &amp;amp;nx_ctx-&amp;gt;op,
+   desc-&amp;gt;flags &amp;amp; CRYPTO_TFM_REQ_MAY_SLEEP);
+if (rc)
+goto out;
+
+atomic_inc(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;sha256_ops));
+
+atomic64_add(csbcpb-&amp;gt;cpb.sha256.message_bit_length,
+     &amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;sha256_bytes));
+memcpy(out, csbcpb-&amp;gt;cpb.sha256.message_digest, SHA256_DIGEST_SIZE);
+out:
+return rc;
+}
+
+static int nx_sha256_export(struct shash_desc *desc, void *out)
+{
+struct sha256_state *sctx = shash_desc_ctx(desc);
+struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&amp;amp;desc-&amp;gt;tfm-&amp;gt;base);
+struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx-&amp;gt;csbcpb;
+struct sha256_state *octx = out;
+
+octx-&amp;gt;count = sctx-&amp;gt;count +
+      (csbcpb-&amp;gt;cpb.sha256.message_bit_length / 8);
+memcpy(octx-&amp;gt;buf, sctx-&amp;gt;buf, sizeof(octx-&amp;gt;buf));
+
+/* if no data has been processed yet, we need to export SHA256's
+ * initial data, in case this context gets imported into a software
+ * context */
+if (csbcpb-&amp;gt;cpb.sha256.message_bit_length)
+memcpy(octx-&amp;gt;state, csbcpb-&amp;gt;cpb.sha256.message_digest,
+       SHA256_DIGEST_SIZE);
+else {
+octx-&amp;gt;state[0] = SHA256_H0;
+octx-&amp;gt;state[1] = SHA256_H1;
+octx-&amp;gt;state[2] = SHA256_H2;
+octx-&amp;gt;state[3] = SHA256_H3;
+octx-&amp;gt;state[4] = SHA256_H4;
+octx-&amp;gt;state[5] = SHA256_H5;
+octx-&amp;gt;state[6] = SHA256_H6;
+octx-&amp;gt;state[7] = SHA256_H7;
+}
+
+return 0;
+}
+
+static int nx_sha256_import(struct shash_desc *desc, const void *in)
+{
+struct sha256_state *sctx = shash_desc_ctx(desc);
+struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&amp;amp;desc-&amp;gt;tfm-&amp;gt;base);
+struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx-&amp;gt;csbcpb;
+const struct sha256_state *ictx = in;
+
+memcpy(sctx-&amp;gt;buf, ictx-&amp;gt;buf, sizeof(ictx-&amp;gt;buf));
+
+sctx-&amp;gt;count = ictx-&amp;gt;count &amp;amp; 0x3f;
+csbcpb-&amp;gt;cpb.sha256.message_bit_length = (ictx-&amp;gt;count &amp;amp; ~0x3f) * 8;
+
+if (csbcpb-&amp;gt;cpb.sha256.message_bit_length) {
+memcpy(csbcpb-&amp;gt;cpb.sha256.message_digest, ictx-&amp;gt;state,
+       SHA256_DIGEST_SIZE);
+
+NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
+NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
+}
+
+return 0;
+}
+
+struct shash_alg nx_shash_sha256_alg = {
+.digestsize = SHA256_DIGEST_SIZE,
+.init       = nx_sha256_init,
+.update     = nx_sha256_update,
+.final      = nx_sha256_final,
+.export     = nx_sha256_export,
+.import     = nx_sha256_import,
+.descsize   = sizeof(struct sha256_state),
+.statesize  = sizeof(struct sha256_state),
+.base       = {
+.cra_name        = "sha256",
+.cra_driver_name = "sha256-nx",
+.cra_priority    = 300,
+.cra_flags       = CRYPTO_ALG_TYPE_SHASH,
+.cra_blocksize   = SHA256_BLOCK_SIZE,
+.cra_module      = THIS_MODULE,
+.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
+.cra_init        = nx_crypto_ctx_sha_init,
+.cra_exit        = nx_crypto_ctx_exit,
+}
+};
&lt;/pre&gt;</description>
    <dc:creator>Kent Yoder</dc:creator>
    <dc:date>2012-05-14T21:06:20</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7041">
    <title>[PATCH v4 11/17] powerpc: crypto: AES-GCM mode routines for nx encryption</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7041</link>
    <description>&lt;pre&gt;These routines add support for AES in GCM mode on the Power7+ CPU's
in-Nest accelerator driver.

Signed-off-by: Kent Yoder &amp;lt;key&amp;lt; at &amp;gt;linux.vnet.ibm.com&amp;gt;
---
 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..9ab1c73
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-gcm.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,353 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/**
+ * 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 &amp;lt;yoder1&amp;lt; at &amp;gt;us.ibm.com&amp;gt;
+ */
+
+#include &amp;lt;crypto/internal/aead.h&amp;gt;
+#include &amp;lt;crypto/aes.h&amp;gt;
+#include &amp;lt;crypto/algapi.h&amp;gt;
+#include &amp;lt;crypto/scatterwalk.h&amp;gt;
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/types.h&amp;gt;
+#include &amp;lt;linux/crypto.h&amp;gt;
+#include &amp;lt;asm/vio.h&amp;gt;
+
+#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(&amp;amp;tfm-&amp;gt;base);
+struct nx_csbcpb *csbcpb = nx_ctx-&amp;gt;csbcpb;
+struct nx_csbcpb *csbcpb_aead = nx_ctx-&amp;gt;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-&amp;gt;ap = &amp;amp;nx_ctx-&amp;gt;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-&amp;gt;ap = &amp;amp;nx_ctx-&amp;gt;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-&amp;gt;ap = &amp;amp;nx_ctx-&amp;gt;props[NX_PROPS_AES_256];
+break;
+default:
+return -EINVAL;
+}
+
+csbcpb-&amp;gt;cpb.hdr.mode = NX_MODE_AES_GCM;
+memcpy(csbcpb-&amp;gt;cpb.aes_gcm.key, in_key, key_len);
+
+csbcpb_aead-&amp;gt;cpb.hdr.mode = NX_MODE_AES_GCA;
+memcpy(csbcpb_aead-&amp;gt;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(&amp;amp;tfm-&amp;gt;base);
+char *nonce = nx_ctx-&amp;gt;priv.gcm.nonce;
+int rc;
+
+if (key_len &amp;lt; 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 &amp;gt; crypto_aead_alg(tfm)-&amp;gt;maxauthsize)
+return -EINVAL;
+
+crypto_aead_crt(tfm)-&amp;gt;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)-&amp;gt;authsize = authsize;
+
+return 0;
+}
+
+static int nx_gca(struct nx_crypto_ctx  *nx_ctx,
+  struct aead_request   *req,
+  u8                    *out)
+{
+struct nx_csbcpb *csbcpb_aead = nx_ctx-&amp;gt;csbcpb_aead;
+int rc = -EINVAL;
+struct scatter_walk walk;
+struct nx_sg *nx_sg = nx_ctx-&amp;gt;in_sg;
+
+if (req-&amp;gt;assoclen &amp;gt; nx_ctx-&amp;gt;ap-&amp;gt;databytelen)
+goto out;
+
+if (req-&amp;gt;assoclen &amp;lt;= AES_BLOCK_SIZE) {
+scatterwalk_start(&amp;amp;walk, req-&amp;gt;assoc);
+scatterwalk_copychunks(out, &amp;amp;walk, req-&amp;gt;assoclen,
+       SCATTERWALK_FROM_SG);
+scatterwalk_done(&amp;amp;walk, SCATTERWALK_FROM_SG, 0);
+
+rc = 0;
+goto out;
+}
+
+nx_sg = nx_walk_and_build(nx_sg, nx_ctx-&amp;gt;ap-&amp;gt;sglen, req-&amp;gt;assoc, 0,
+  req-&amp;gt;assoclen);
+nx_ctx-&amp;gt;op_aead.inlen = (nx_ctx-&amp;gt;in_sg - nx_sg) * sizeof(struct nx_sg);
+
+rc = nx_hcall_sync(nx_ctx, &amp;amp;nx_ctx-&amp;gt;op_aead,
+   req-&amp;gt;base.flags &amp;amp; CRYPTO_TFM_REQ_MAY_SLEEP);
+if (rc)
+goto out;
+
+atomic_inc(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;aes_ops));
+atomic64_add(req-&amp;gt;assoclen, &amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;aes_bytes));
+
+memcpy(out, csbcpb_aead-&amp;gt;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-&amp;gt;base.tfm);
+struct nx_csbcpb *csbcpb = nx_ctx-&amp;gt;csbcpb;
+struct blkcipher_desc desc;
+unsigned int nbytes = req-&amp;gt;cryptlen;
+int rc = -EINVAL;
+
+if (nbytes &amp;gt; nx_ctx-&amp;gt;ap-&amp;gt;databytelen)
+goto out;
+
+desc.info = nx_ctx-&amp;gt;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-&amp;gt;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(&amp;amp;sg, src, AES_BLOCK_SIZE);
+if (enc)
+crypto_blkcipher_encrypt_iv(&amp;amp;desc, req-&amp;gt;dst, &amp;amp;sg,
+    AES_BLOCK_SIZE);
+else
+crypto_blkcipher_decrypt_iv(&amp;amp;desc, req-&amp;gt;dst, &amp;amp;sg,
+    AES_BLOCK_SIZE);
+crypto_free_blkcipher(desc.tfm);
+
+rc = 0;
+goto out;
+}
+
+desc.tfm = (struct crypto_blkcipher *)req-&amp;gt;base.tfm;
+
+csbcpb-&amp;gt;cpb.aes_gcm.bit_length_aad = req-&amp;gt;assoclen * 8;
+
+if (req-&amp;gt;assoclen) {
+rc = nx_gca(nx_ctx, req, csbcpb-&amp;gt;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-&amp;gt;cpb.aes_gcm.bit_length_data = nbytes * 8;
+
+rc = nx_build_sg_lists(nx_ctx, &amp;amp;desc, req-&amp;gt;dst, req-&amp;gt;src, nbytes,
+       csbcpb-&amp;gt;cpb.aes_gcm.iv_or_cnt);
+if (rc)
+goto out;
+
+rc = nx_hcall_sync(nx_ctx, &amp;amp;nx_ctx-&amp;gt;op,
+   req-&amp;gt;base.flags &amp;amp; CRYPTO_TFM_REQ_MAY_SLEEP);
+if (rc)
+goto out;
+
+atomic_inc(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;aes_ops));
+atomic64_add(csbcpb-&amp;gt;csb.processed_byte_count,
+     &amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;aes_bytes));
+
+if (enc) {
+/* copy out the auth tag */
+scatterwalk_map_and_copy(csbcpb-&amp;gt;cpb.aes_gcm.out_pat_or_mac,
+ req-&amp;gt;dst, nbytes,
+ crypto_aead_authsize(crypto_aead_reqtfm(req)),
+ SCATTERWALK_TO_SG);
+} else if (req-&amp;gt;assoclen) {
+u8 *itag = nx_ctx-&amp;gt;priv.gcm.iauth_tag;
+u8 *otag = csbcpb-&amp;gt;cpb.aes_gcm.out_pat_or_mac;
+
+scatterwalk_map_and_copy(itag, req-&amp;gt;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-&amp;gt;base.tfm);
+char *iv = nx_ctx-&amp;gt;priv.gcm.iv;
+
+memcpy(iv, req-&amp;gt;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-&amp;gt;base.tfm);
+char *iv = nx_ctx-&amp;gt;priv.gcm.iv;
+
+memcpy(iv, req-&amp;gt;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-&amp;gt;base.tfm);
+char *iv = nx_ctx-&amp;gt;priv.gcm.iv;
+char *nonce = nx_ctx-&amp;gt;priv.gcm.nonce;
+
+memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
+memcpy(iv + NX_GCM4106_NONCE_LEN, req-&amp;gt;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-&amp;gt;base.tfm);
+char *iv = nx_ctx-&amp;gt;priv.gcm.iv;
+char *nonce = nx_ctx-&amp;gt;priv.gcm.nonce;
+
+memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
+memcpy(iv + NX_GCM4106_NONCE_LEN, req-&amp;gt;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-&amp;gt;blocksize,
+ * but instead uses this tfm-&amp;gt;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        = &amp;amp;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        = &amp;amp;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,
+}
+};
&lt;/pre&gt;</description>
    <dc:creator>Kent Yoder</dc:creator>
    <dc:date>2012-05-14T21:05:59</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7038">
    <title>[PATCH v4 07/17] powerpc: crypto: AES-CBC mode routines for nx encryption</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7038</link>
    <description>&lt;pre&gt;These routines add support for AES in CBC mode on the Power7+ CPU's
in-Nest accelerator driver.

Signed-off-by: Kent Yoder &amp;lt;key&amp;lt; at &amp;gt;linux.vnet.ibm.com&amp;gt;
---
 drivers/crypto/nx/nx-aes-cbc.c |  141 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 141 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..69ed796
--- /dev/null
+++ b/drivers/crypto/nx/nx-aes-cbc.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,141 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/**
+ * 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 &amp;lt;yoder1&amp;lt; at &amp;gt;us.ibm.com&amp;gt;
+ */
+
+#include &amp;lt;crypto/aes.h&amp;gt;
+#include &amp;lt;crypto/algapi.h&amp;gt;
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/types.h&amp;gt;
+#include &amp;lt;linux/crypto.h&amp;gt;
+#include &amp;lt;asm/vio.h&amp;gt;
+
+#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-&amp;gt;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-&amp;gt;ap = &amp;amp;nx_ctx-&amp;gt;props[NX_PROPS_AES_128];
+break;
+case AES_KEYSIZE_192:
+NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_192);
+nx_ctx-&amp;gt;ap = &amp;amp;nx_ctx-&amp;gt;props[NX_PROPS_AES_192];
+break;
+case AES_KEYSIZE_256:
+NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_256);
+nx_ctx-&amp;gt;ap = &amp;amp;nx_ctx-&amp;gt;props[NX_PROPS_AES_256];
+break;
+default:
+return -EINVAL;
+}
+
+csbcpb-&amp;gt;cpb.hdr.mode = NX_MODE_AES_CBC;
+memcpy(csbcpb-&amp;gt;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-&amp;gt;tfm);
+struct nx_csbcpb *csbcpb = nx_ctx-&amp;gt;csbcpb;
+int rc;
+
+if (nbytes &amp;gt; nx_ctx-&amp;gt;ap-&amp;gt;databytelen)
+return -EINVAL;
+
+if (enc)
+NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
+else
+NX_CPB_FDM(csbcpb) &amp;amp;= ~NX_FDM_ENDE_ENCRYPT;
+
+rc = nx_build_sg_lists(nx_ctx, desc, dst, src, nbytes,
+       csbcpb-&amp;gt;cpb.aes_cbc.iv);
+if (rc)
+goto out;
+
+if (!nx_ctx-&amp;gt;op.inlen || !nx_ctx-&amp;gt;op.outlen) {
+rc = -EINVAL;
+goto out;
+}
+
+rc = nx_hcall_sync(nx_ctx, &amp;amp;nx_ctx-&amp;gt;op,
+   desc-&amp;gt;flags &amp;amp; CRYPTO_TFM_REQ_MAY_SLEEP);
+if (rc)
+goto out;
+
+atomic_inc(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;aes_ops));
+atomic64_add(csbcpb-&amp;gt;csb.processed_byte_count,
+     &amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;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        = &amp;amp;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,
+}
+};
&lt;/pre&gt;</description>
    <dc:creator>Kent Yoder</dc:creator>
    <dc:date>2012-05-14T21:05:12</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7037">
    <title>[PATCH v4 06/17] powerpc: crypto: nx driver code supporting nx encryption</title>
    <link>http://permalink.gmane.org/gmane.linux.kernel.cryptoapi/7037</link>
    <description>&lt;pre&gt;These routines add the base device driver code supporting the Power7+
in-Nest encryption accelerator (nx) device.

Signed-off-by: Kent Yoder &amp;lt;key&amp;lt; at &amp;gt;linux.vnet.ibm.com&amp;gt;
---
 drivers/crypto/nx/nx.c        |  716 +++++++++++++++++++++++++++++++++++++++++
 drivers/crypto/nx/nx.h        |  193 +++++++++++
 drivers/crypto/nx/nx_csbcpb.h |  205 ++++++++++++
 3 files changed, 1114 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..d7f179c
--- /dev/null
+++ b/drivers/crypto/nx/nx.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,716 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/**
+ * 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 &amp;lt;yoder1&amp;lt; at &amp;gt;us.ibm.com&amp;gt;
+ */
+
+#include &amp;lt;crypto/internal/hash.h&amp;gt;
+#include &amp;lt;crypto/hash.h&amp;gt;
+#include &amp;lt;crypto/aes.h&amp;gt;
+#include &amp;lt;crypto/sha.h&amp;gt;
+#include &amp;lt;crypto/algapi.h&amp;gt;
+#include &amp;lt;crypto/scatterwalk.h&amp;gt;
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/moduleparam.h&amp;gt;
+#include &amp;lt;linux/types.h&amp;gt;
+#include &amp;lt;linux/mm.h&amp;gt;
+#include &amp;lt;linux/crypto.h&amp;gt;
+#include &amp;lt;linux/scatterlist.h&amp;gt;
+#include &amp;lt;linux/device.h&amp;gt;
+#include &amp;lt;linux/of.h&amp;gt;
+#include &amp;lt;asm/pSeries_reconfig.h&amp;gt;
+#include &amp;lt;asm/abs_addr.h&amp;gt;
+#include &amp;lt;asm/hvcall.h&amp;gt;
+#include &amp;lt;asm/vio.h&amp;gt;
+
+#include "nx_csbcpb.h"
+#include "nx.h"
+
+
+/**
+ * nx_hcall_sync - make an H_COP_OP hcall for the passed in op structure
+ *
+ * &amp;lt; at &amp;gt;nx_ctx: the crypto context handle
+ * &amp;lt; at &amp;gt;op: PFO operation struct to pass in
+ * &amp;lt; at &amp;gt;may_sleep: flag indicating the request can sleep
+ *
+ * Make the hcall, retrying while the hardware is busy. If we cannot yield
+ * the thread, limit the number of retries to 10 here.
+ */
+int nx_hcall_sync(struct nx_crypto_ctx *nx_ctx,
+  struct vio_pfo_op    *op,
+  u32                   may_sleep)
+{
+int rc, retries = 10;
+struct vio_dev *viodev = nx_driver.viodev;
+
+atomic_inc(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;sync_ops));
+
+do {
+rc = vio_h_cop_sync(viodev, op);
+} while ((rc == -EBUSY &amp;amp;&amp;amp; !may_sleep &amp;amp;&amp;amp; retries--) ||
+         (rc == -EBUSY &amp;amp;&amp;amp; may_sleep &amp;amp;&amp;amp; cond_resched()));
+
+if (rc) {
+dev_dbg(&amp;amp;viodev-&amp;gt;dev, "vio_h_cop_sync failed: rc: %d "
+"hcall rc: %ld\n", rc, op-&amp;gt;hcall_err);
+atomic_inc(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;errors));
+atomic_set(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;last_error), op-&amp;gt;hcall_err);
+atomic_set(&amp;amp;(nx_ctx-&amp;gt;stats-&amp;gt;last_error_pid), current-&amp;gt;pid);
+}
+
+return rc;
+}
+
+/**
+ * nx_build_sg_list - build an NX scatter list describing a single  buffer
+ *
+ * &amp;lt; at &amp;gt;sg_head: pointer to the first scatter list element to build
+ * &amp;lt; at &amp;gt;start_addr: pointer to the linear buffer
+ * &amp;lt; at &amp;gt;len: length of the data at &amp;lt; at &amp;gt;start_addr
+ * &amp;lt; at &amp;gt;sgmax: the largest number of scatter list elements we're allowed to create
+ *
+ * This function will start writing nx_sg elements at &amp;lt; at &amp;gt;sg_head and keep
+ * writing them until all of the data from &amp;lt; at &amp;gt;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 &amp;lt; at &amp;gt;len bytes
+ * have been described (or &amp;lt; at &amp;gt;sgmax elements have been written), the
+ * loop ends. min_t is used to ensure &amp;lt; at &amp;gt;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 &amp;lt; len; sg++) {
+sg-&amp;gt;addr = sg_addr;
+sg_addr = min_t(u64, NX_PAGE_NUM(sg_addr + NX_PAGE_SIZE), end_addr);
+sg-&amp;gt;len = sg_addr - sg-&amp;gt;addr;
+sg_len += sg-&amp;gt;len;
+
+if ((sg - sg_head) == sgmax) {
+pr_err("nx: scatter/gather list overflow, pid: %d\n",
+       current-&amp;gt;pid);
+return NULL;
+}
+}
+
+/* return the moved sg_head pointer */
+return sg;
+}
+
+/**
+ * nx_walk_and_build - walk a linux scatterlist and build an nx scatterlist
+ *
+ * &amp;lt; at &amp;gt;nx_dst: pointer to the first nx_sg element to write
+ * &amp;lt; at &amp;gt;sglen: max number of nx_sg entries we're allowed to write
+ * &amp;lt; at &amp;gt;sg_src: pointer to the source linux scatterlist to walk
+ * &amp;lt; at &amp;gt;start: number of bytes to fast-forward past at the beginning of &amp;lt; at &amp;gt;sg_src
+ * &amp;lt; at &amp;gt;src_len: number of bytes to walk in &amp;lt; at &amp;gt;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 &amp;lt; at &amp;gt;start bytes first */
+for (;;) {
+scatterwalk_start(&amp;amp;walk, sg_src);
+
+if (start &amp;lt; offset + sg_src-&amp;gt;length)
+break;
+
+offset += sg_src-&amp;gt;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(&amp;amp;walk, start - offset);
+
+while (len &amp;amp;&amp;amp; nx_sg) {
+n = scatterwalk_clamp(&amp;amp;walk, len);
+if (!n) {
+scatterwalk_start(&amp;amp;walk, sg_next(walk.sg));
+n = scatterwalk_clamp(&amp;amp;walk, len);
+}
+dst = scatterwalk_map(&amp;amp;walk);
+
+nx_sg = nx_build_sg_list(nx_sg, dst, n, sglen);
+len -= n;
+
+scatterwalk_unmap(dst);
+scatterwalk_advance(&amp;amp;walk, n);
+scatterwalk_done(&amp;amp;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.
+ *
+ * &amp;lt; at &amp;gt;nx_ctx: NX crypto context for the lists we're building
+ * &amp;lt; at &amp;gt;desc: the block cipher descriptor for the operation
+ * &amp;lt; at &amp;gt;dst: destination scatterlist
+ * &amp;lt; at &amp;gt;src: source scatterlist
+ * &amp;lt; at &amp;gt;nbytes: length of data described in the scatterlists
+ * &amp;lt; at &amp;gt;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-&amp;gt;in_sg;
+struct nx_sg *nx_outsg = nx_ctx-&amp;gt;out_sg;
+struct blkcipher_walk walk;
+int rc;
+
+blkcipher_walk_init(&amp;amp;walk, dst, src, nbytes);
+rc = blkcipher_walk_virt_block(desc, &amp;amp;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-&amp;gt;ap-&amp;gt;sglen);
+nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
+    walk.nbytes, nx_ctx-&amp;gt;ap-&amp;gt;sglen);
+
+rc = blkcipher_walk_done(desc, &amp;amp;walk, 0);
+if (rc)
+break;
+}
+
+if (walk.nbytes) {
+nx_insg = nx_build_sg_list(nx_insg, walk.src.virt.addr,
+   walk.nbytes, nx_ctx-&amp;gt;ap-&amp;gt;sglen);
+nx_outsg = nx_build_sg_list(nx_outsg, walk.dst.virt.addr,
+    walk.nbytes, nx_ctx-&amp;gt;ap-&amp;gt;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-&amp;gt;op.inlen = (nx_ctx-&amp;gt;in_sg - nx_insg) * sizeof(struct nx_sg);
+nx_ctx-&amp;gt;op.outlen = (nx_ctx-&amp;gt;out_sg - nx_outsg) * sizeof(struct nx_sg);
+out:
+return rc;
+}
+
+/**
+ * nx_ctx_init - initialize an nx_ctx's vio_pfo_op struct
+ *
+ * &amp;lt; at &amp;gt;nx_ctx: the nx context to initialize
+ * &amp;lt; at &amp;gt;function: the function code for the op
+ */
+void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function)
+{
+memset(nx_ctx-&amp;gt;kmem, 0, nx_ctx-&amp;gt;kmem_len);
+nx_ctx-&amp;gt;csbcpb-&amp;gt;csb.valid |= NX_CSB_VALID_BIT;
+
+nx_ctx-&amp;gt;op.flags = function;
+nx_ctx-&amp;gt;op.csbcpb = virt_to_abs(nx_ctx-&amp;gt;csbcpb);
+nx_ctx-&amp;gt;op.in = virt_to_abs(nx_ctx-&amp;gt;in_sg);
+nx_ctx-&amp;gt;op.out = virt_to_abs(nx_ctx-&amp;gt;out_sg);
+
+if (nx_ctx-&amp;gt;csbcpb_aead) {
+nx_ctx-&amp;gt;csbcpb_aead-&amp;gt;csb.valid |= NX_CSB_VALID_BIT;
+
+nx_ctx-&amp;gt;op_aead.flags = function;
+nx_ctx-&amp;gt;op_aead.csbcpb = virt_to_abs(nx_ctx-&amp;gt;csbcpb_aead);
+nx_ctx-&amp;gt;op_aead.in = virt_to_abs(nx_ctx-&amp;gt;in_sg);
+nx_ctx-&amp;gt;op_aead.out = virt_to_abs(nx_ctx-&amp;gt;out_sg);
+}
+}
+
+static void nx_of_update_status(struct device   *dev,
+       struct property *p,
+       struct nx_of    *props)
+{
+if (!strncmp(p-&amp;gt;value, "okay", p-&amp;gt;length)) {
+props-&amp;gt;status = NX_WAITING;
+props-&amp;gt;flags |= NX_OF_FLAG_STATUS_SET;
+} else {
+dev_info(dev, "%s: status '%s' is not 'okay'\n", __func__,
+ (char *)p-&amp;gt;value);
+}
+}
+
+static void nx_of_update_sglen(struct device   *dev,
+       struct property *p,
+       struct nx_of    *props)
+{
+if (p-&amp;gt;length != sizeof(props-&amp;gt;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-&amp;gt;length, sizeof(props-&amp;gt;max_sg_len));
+return;
+}
+
+props-&amp;gt;max_sg_len = *(u32 *)p-&amp;gt;value;
+props-&amp;gt;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-&amp;gt;value;
+lenp = p-&amp;gt;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)) &amp;lt;= lenp) {
+bytes_so_far += sizeof(struct max_sync_cop);
+
+trip = msc-&amp;gt;trip;
+
+for (i = 0;
+     ((bytes_so_far + sizeof(struct msc_triplet)) &amp;lt;= lenp) &amp;amp;&amp;amp;
+     i &amp;lt; msc-&amp;gt;triplets;
+     i++) {
+if (msc-&amp;gt;fc &amp;gt; NX_MAX_FC || msc-&amp;gt;mode &amp;gt; NX_MAX_MODE) {
+dev_err(dev, "unknown function code/mode "
+"combo: %d/%d (ignored)\n", msc-&amp;gt;fc,
+msc-&amp;gt;mode);
+goto next_loop;
+}
+
+switch (trip-&amp;gt;keybitlen) {
+case 128:
+case 160:
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][0].databytelen =
+trip-&amp;gt;databytelen;
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][0].sglen =
+trip-&amp;gt;sglen;
+break;
+case 192:
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][1].databytelen =
+trip-&amp;gt;databytelen;
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][1].sglen =
+trip-&amp;gt;sglen;
+break;
+case 256:
+if (msc-&amp;gt;fc == NX_FC_AES) {
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][2].
+databytelen = trip-&amp;gt;databytelen;
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][2].sglen =
+trip-&amp;gt;sglen;
+} else if (msc-&amp;gt;fc == NX_FC_AES_HMAC ||
+   msc-&amp;gt;fc == NX_FC_SHA) {
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][1].
+databytelen = trip-&amp;gt;databytelen;
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][1].sglen =
+trip-&amp;gt;sglen;
+} else {
+dev_warn(dev, "unknown function "
+"code/key bit len combo"
+": (%u/256)\n", msc-&amp;gt;fc);
+}
+break;
+case 512:
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][2].databytelen =
+trip-&amp;gt;databytelen;
+props-&amp;gt;ap[msc-&amp;gt;fc][msc-&amp;gt;mode][2].sglen =
+trip-&amp;gt;sglen;
+break;
+default:
+dev_warn(dev, "unknown function code/key bit "
+ "len combo: (%u/%u)\n", msc-&amp;gt;fc,
+ trip-&amp;gt;keybitlen);
+break;
+}
+next_loop:
+bytes_so_far += sizeof(struct msc_triplet);
+trip++;
+}
+
+msc = (struct max_sync_cop *)trip;
+}
+
+props-&amp;gt;flags |= NX_OF_FLAG_MAXSYNCCOP_SET;
+}
+
+/**
+ * nx_of_init - read openFirmware values from the device tree
+ *
+ * &amp;lt; at &amp;gt;dev: device handle
+ * &amp;lt; at &amp;gt;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-&amp;gt;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-&amp;gt;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(&amp;amp;nx_driver.stats, 0, sizeof(struct nx_stats));
+
+rc = NX_DEBUGFS_INIT(&amp;amp;nx_driver);
+if (rc)
+goto out;
+
+rc = crypto_register_alg(&amp;amp;nx_ecb_aes_alg);
+if (rc)
+goto out;
+
+rc = crypto_register_alg(&amp;amp;nx_cbc_aes_alg);
+if (rc)
+goto out_unreg_ecb;
+
+rc = crypto_register_alg(&amp;amp;nx_ctr_aes_alg);
+if (rc)
+goto out_unreg_cbc;
+
+rc = crypto_register_alg(&amp;amp;nx_ctr3686_aes_alg);
+if (rc)
+goto out_unreg_ctr;
+
+rc = crypto_register_alg(&amp;amp;nx_gcm_aes_alg);
+if (rc)
+goto out_unreg_ctr3686;
+
+rc = crypto_register_alg(&amp;amp;nx_gcm4106_aes_alg);
+if (rc)
+goto out_unreg_gcm;
+
+rc = crypto_register_alg(&amp;amp;nx_ccm_aes_alg);
+if (rc)
+goto out_unreg_gcm4106;
+
+rc = crypto_register_alg(&amp;amp;nx_ccm4309_aes_alg);
+if (rc)
+goto out_unreg_ccm;
+
+rc = crypto_register_shash(&amp;amp;nx_shash_sha256_alg);
+if (rc)
+goto out_unreg_ccm4309;
+
+rc = crypto_register_shash(&amp;amp;nx_shash_sha512_alg);
+if (rc)
+goto out_unreg_s256;
+
+rc = crypto_register_shash(&amp;amp;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(&amp;amp;nx_shash_sha512_alg);
+out_unreg_s256:
+crypto_unregister_shash(&amp;amp;nx_shash_sha256_alg);
+out_unreg_ccm4309:
+crypto_unregister_alg(&amp;amp;nx_ccm4309_aes_alg);
+out_unreg_ccm:
+crypto_unregister_alg(&amp;amp;nx_ccm_aes_alg);
+out_unreg_gcm4106:
+crypto_unregister_alg(&amp;amp;nx_gcm4106_aes_alg);
+out_unreg_gcm:
+crypto_unregister_alg(&amp;amp;nx_gcm_aes_alg);
+out_unreg_ctr3686:
+crypto_unregister_alg(&amp;amp;nx_ctr3686_aes_alg);
+out_unreg_ctr:
+crypto_unregister_alg(&amp;amp;nx_ctr_aes_alg);
+out_unreg_cbc:
+crypto_unregister_alg(&amp;amp;nx_cbc_aes_alg);
+out_unreg_ecb:
+crypto_unregister_alg(&amp;amp;nx_ecb_aes_alg);
+out:
+return rc;
+}
+
+/**
+ * nx_crypto_ctx_init - create and initialize a crypto api context
+ *
+ * &amp;lt; at &amp;gt;nx_ctx: the crypto api context
+ * &amp;lt; at &amp;gt;fc: function code for the context
+ * &amp;lt; at &amp;gt;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-&amp;gt;kmem_len = (4 * NX_PAGE_SIZE) +
+   sizeof(struct nx_csbcpb);
+else
+nx_ctx-&amp;gt;kmem_len = (3 * NX_PAGE_SIZE) +
+   sizeof(struct nx_csbcpb);
+
+nx_ctx-&amp;gt;kmem = kmalloc(nx_ctx-&amp;gt;kmem_len, GFP_KERNEL);
+if (!nx_ctx-&amp;gt;kmem)
+return -ENOMEM;
+
+/* the csbcpb and scatterlists must be 4K aligned pages */
+nx_ctx-&amp;gt;csbcpb = (struct nx_csbcpb *)(round_up((u64)nx_ctx-&amp;gt;kmem,
+       (u64)NX_PAGE_SIZE));
+nx_ctx-&amp;gt;in_sg = (struct nx_sg *)((u8 *)nx_ctx-&amp;gt;csbcpb + NX_PAGE_SIZE);
+nx_ctx-&amp;gt;out_sg = (struct nx_sg *)((u8 *)nx_ctx-&amp;gt;in_sg + NX_PAGE_SIZE);
+
+if (mode == NX_MODE_AES_GCM || mode == NX_MODE_AES_CCM)
+nx_ctx-&amp;gt;csbcpb_aead =
+(struct nx_csbcpb *)((u8 *)nx_ctx-&amp;gt;out_sg +
+     NX_PAGE_SIZE);
+
+/* give each context a pointer to global stats and their OF
+ * properties */
+nx_ctx-&amp;gt;stats = &amp;amp;nx_driver.stats;
+memcpy(nx_ctx-&amp;gt;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
+ *
+ * &amp;lt; at &amp;gt;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-&amp;gt;kmem);
+nx_ctx-&amp;gt;csbcpb = NULL;
+nx_ctx-&amp;gt;csbcpb_aead = NULL;
+nx_ctx-&amp;gt;in_sg = NULL;
+nx_ctx-&amp;gt;out_sg = NULL;
+}
+
+static int __devinit nx_probe(struct vio_dev *viodev,
+      const struct vio_device_id *id)
+{
+dev_dbg(&amp;amp;viodev-&amp;gt;dev, "driver probed: %s resource id: 0x%x\n",
+viodev-&amp;gt;name, viodev-&amp;gt;resource_id);
+
+if (nx_driver.viodev) {
+dev_err(&amp;amp;viodev-&amp;gt;dev, "%s: Attempt to register more than one "
+"instance of the hardware\n", __func__);
+return -EINVAL;
+}
+
+nx_driver.viodev = viodev;
+
+nx_of_init(&amp;amp;viodev-&amp;gt;dev, &amp;amp;nx_driver.of);
+
+return nx_register_algs();
+}
+
+static int __devexit nx_remove(struct vio_dev *viodev)
+{
+dev_dbg(&amp;amp;viodev-&amp;gt;dev, "entering nx_remove for UA 0x%x\n",
+viodev-&amp;gt;unit_address);
+
+if (nx_driver.of.status == NX_OKAY) {
+NX_DEBUGFS_FINI(&amp;amp;nx_driver);
+
+crypto_unregister_alg(&amp;amp;nx_ccm_aes_alg);
+crypto_unregister_alg(&amp;amp;nx_ccm4309_aes_alg);
+crypto_unregister_alg(&amp;amp;nx_gcm_aes_alg);
+crypto_unregister_alg(&amp;amp;nx_gcm4106_aes_alg);
+crypto_unregister_alg(&amp;amp;nx_ctr_aes_alg);
+crypto_unregister_alg(&amp;amp;nx_ctr3686_aes_alg);
+crypto_unregister_alg(&amp;amp;nx_cbc_aes_alg);
+crypto_unregister_alg(&amp;amp;nx_ecb_aes_alg);
+crypto_unregister_shash(&amp;amp;nx_shash_sha256_alg);
+crypto_unregister_shash(&amp;amp;nx_shash_sha512_alg);
+crypto_unregister_shash(&amp;amp;nx_shash_aes_xcbc_alg);
+}
+
+return 0;
+}
+
+
+/* module wide initialization/cleanup */
+static int __init nx_init(void)
+{
+return vio_register_driver(&amp;amp;nx_driver.viodriver);
+}
+
+static void __exit nx_fini(void)
+{
+vio_unregister_driver(&amp;amp;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 &amp;lt;yoder1&amp;lt; at &amp;gt;us.ibm.com&amp;gt;");
+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..3232b18
--- /dev/null
+++ b/drivers/crypto/nx/nx.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,193 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+
+#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 &amp;lt; at &amp;gt; 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,
+  u32 may_sleep);
+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) &amp;amp; 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_SG1
+#define SCATTERWALK_FROM_SG0
+
+#endif
diff --git a/drivers/crypto/nx/nx_csbcpb.h b/drivers/crypto/nx/nx_csbcpb.h
new file mode 100644
index 0000000..a304f956
--- /dev/null
+++ b/drivers/crypto/nx/nx_csbcpb.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,205 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+
+#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_INTERMEDIATE0x01
+#define NX_FDM_CONTINUATION0x02
+#define NX_FDM_ENDE_ENCRYPT0x80
+
+#define NX_CPB_FDM(c)((c)-&amp;gt;cpb.hdr.fdm)
+#define NX_CPB_KS_DS(c)((c)-&amp;gt;cpb.hdr.ks_ds)
+
+#define NX_CPB_KEY_SIZE(c)(NX_CPB_KS_DS(c) &amp;gt;&amp;gt; 4)
+#define NX_CPB_SET_KEY_SIZE(c, x)NX_CPB_KS_DS(c) |= ((x) &amp;lt;&amp;lt; 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_BIT0x80
+
+/* 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_ECB0
+#define NX_MODE_AES_CBC1
+#define NX_MODE_AES_GMAC2
+#define NX_MODE_AES_GCA3
+#define NX_MODE_AES_GCM4
+#define NX_MODE_AES_CCA5
+#define NX_MODE_AES_CCM6
+#define NX_MODE_AES_CTR7
+#define NX_MODE_AES_XCBC_MAC20
+#define NX_MODE_SHA0
+#define NX_MODE_SHA_HMAC1
+#define NX_MODE_AES_CBC_HMAC_ETA8
+#define NX_MODE_AES_CBC_HMAC_ATE9
+#define NX_MODE_AES_CBC_HMAC_EAA10
+#define NX_MODE_AES_CTR_HMAC_ETA12
+#define NX_MODE_AES_CTR_HMAC_ATE13
+#define NX_MODE_AES_CTR_HMAC_EAA14
+
+#define NX_FDM_CI_FULL0
+#define NX_FDM_CI_FIRST1
+#define NX_FDM_CI_LAST2
+#define NX_FDM_CI_MIDDLE3
+
+#define NX_FDM_PR_NONE0
+#define NX_FDM_PR_PAD1
+
+#define NX_KS_AES_1281
+#define NX_KS_AES_1922
+#define NX_KS_AES_2563
+
+#define NX_DS_SHA2562
+#define NX_DS_SHA5123
+
+#define NX_FC_AES0
+#define NX_FC_SHA2
+#define NX_FC_AES_HMAC6
+
+#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_1280
+#define NX_PROPS_AES_1921
+#define NX_PROPS_AES_2562
+#define NX_PROPS_SHA2561
+#define NX_PROPS_SHA5122
+
+#endif
&lt;/pre&gt;</description>
    <dc:creator>Kent Yoder</dc:creator>
    <dc:date>2012-05-14T20:59:38</dc:date>
  </item>
  <textinput rdf:about="http://search.gmane.org/?group=$group=gmane.linux.kernel.cryptoapi">
    <title>Search Engine</title>
    <description>Search the mailing list at Gmane</description>
    <name>query</name>
    <link>http://search.gmane.org/?group=$group=gmane.linux.kernel.cryptoapi</link>
  </textinput>
</rdf:RDF>

