#include <linux/crypto.h>
 #include <linux/types.h>
 #include <crypto/sha.h>
-
+#include <linux/percpu.h>
 #include <asm/byteorder.h>
 
 struct sha512_ctx {
        u64 state[8];
        u32 count[4];
        u8 buf[128];
-       u64 W[80];
 };
 
+static DEFINE_PER_CPU(u64[80], msg_schedule);
+
 static inline u64 Ch(u64 x, u64 y, u64 z)
 {
         return z ^ (x & (y ^ z));
 }
 
 static void
-sha512_transform(u64 *state, u64 *W, const u8 *input)
+sha512_transform(u64 *state, const u8 *input)
 {
        u64 a, b, c, d, e, f, g, h, t1, t2;
 
        int i;
+       u64 *W = get_cpu_var(msg_schedule);
 
        /* load the input */
         for (i = 0; i < 16; i++)
 
        /* erase our data */
        a = b = c = d = e = f = g = h = t1 = t2 = 0;
+       memset(W, 0, sizeof(__get_cpu_var(msg_schedule)));
+       put_cpu_var(msg_schedule);
 }
 
 static void
        /* Transform as many times as possible. */
        if (len >= part_len) {
                memcpy(&sctx->buf[index], data, part_len);
-               sha512_transform(sctx->state, sctx->W, sctx->buf);
+               sha512_transform(sctx->state, sctx->buf);
 
                for (i = part_len; i + 127 < len; i+=128)
-                       sha512_transform(sctx->state, sctx->W, &data[i]);
+                       sha512_transform(sctx->state, &data[i]);
 
                index = 0;
        } else {
 
        /* Buffer remaining input */
        memcpy(&sctx->buf[index], &data[i], len - i);
-
-       /* erase our data */
-       memset(sctx->W, 0, sizeof(sctx->W));
 }
 
 static void