Browse Source

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (79 commits)
  [IPX]: Fix NULL pointer dereference on ipx unload
  [ATM]: atmarp.h needs to always include linux/types.h
  [NET]: Fix net/socket.c warnings.
  [NET]: cleanup sock_from_file()
  [NET]: change layout of ehash table
  [S390]: Add AF_IUCV socket support
  [S390]: Adapt special message interface to new IUCV API
  [S390]: Adapt netiucv driver to new IUCV API
  [S390]: Adapt vmlogrdr driver to new IUCV API
  [S390]: Adapt monreader driver to new IUCV API
  [S390]: Rewrite of the IUCV base code, part 2
  [S390]: Rewrite of the IUCV base code, part 1
  [X.25]: Adds /proc/net/x25/forward to view active forwarded calls.
  [X.25]: Adds /proc/sys/net/x25/x25_forward to control forwarding.
  [X.25]: Add call forwarding
  [XFRM]: xfrm_migrate() needs exporting to modules.
  [PFKEYV2]: CONFIG_NET_KEY_MIGRATE option
  [PFKEYV2]: Extension for dynamic update of endpoint address(es)
  [XFRM]: CONFIG_XFRM_MIGRATE option
  [XFRM]: User interface for handling XFRM_MSG_MIGRATE
  ...
Linus Torvalds 18 năm trước cách đây
mục cha
commit
f049274b01
100 tập tin đã thay đổi với 4914 bổ sung5039 xóa
  1. 4 0
      Documentation/crypto/api-intro.txt
  2. 2 1
      arch/s390/defconfig
  3. 31 0
      crypto/Kconfig
  4. 3 0
      crypto/Makefile
  5. 12 3
      crypto/algapi.c
  6. 16 64
      crypto/api.c
  7. 7 2
      crypto/blkcipher.c
  8. 1801 0
      crypto/camellia.c
  9. 5 4
      crypto/cbc.c
  10. 3 444
      crypto/cipher.c
  11. 0 5
      crypto/compress.c
  12. 16 8
      crypto/digest.c
  13. 5 4
      crypto/ecb.c
  14. 423 0
      crypto/fcrypt.c
  15. 3 2
      crypto/hash.c
  16. 5 4
      crypto/hmac.c
  17. 6 21
      crypto/internal.h
  18. 6 5
      crypto/lrw.c
  19. 349 0
      crypto/pcbc.c
  20. 71 2
      crypto/tcrypt.c
  21. 537 1
      crypto/tcrypt.h
  22. 38 22
      crypto/xcbc.c
  23. 1 1
      drivers/crypto/geode-aes.c
  24. 1 3
      drivers/net/bonding/bond_alb.c
  25. 1 3
      drivers/net/bonding/bond_main.c
  26. 1 4
      drivers/net/slip.c
  27. 1 1
      drivers/net/tg3.c
  28. 101 117
      drivers/s390/char/monreader.c
  29. 127 152
      drivers/s390/char/vmlogrdr.c
  30. 0 7
      drivers/s390/net/Kconfig
  31. 0 1
      drivers/s390/net/Makefile
  32. 0 2540
      drivers/s390/net/iucv.c
  33. 0 849
      drivers/s390/net/iucv.h
  34. 343 337
      drivers/s390/net/netiucv.c
  35. 74 73
      drivers/s390/net/smsgiucv.c
  36. 1 3
      fs/ecryptfs/crypto.c
  37. 0 1
      fs/ecryptfs/ecryptfs_kernel.h
  38. 21 3
      include/crypto/algapi.h
  39. 0 2
      include/linux/atmarp.h
  40. 14 134
      include/linux/crypto.h
  41. 10 0
      include/linux/if_packet.h
  42. 1 1
      include/linux/net.h
  43. 1 1
      include/linux/netdevice.h
  44. 1 0
      include/linux/netfilter/Kbuild
  45. 21 0
      include/linux/netfilter/nf_conntrack_sane.h
  46. 3 1
      include/linux/netfilter/nf_conntrack_tcp.h
  47. 10 0
      include/linux/netfilter/xt_TCPMSS.h
  48. 1 0
      include/linux/netfilter_ipv4/ip_nat.h
  49. 3 19
      include/linux/netfilter_ipv4/ip_tables.h
  50. 3 4
      include/linux/netfilter_ipv4/ipt_TCPMSS.h
  51. 22 13
      include/linux/netfilter_ipv6/ip6_tables.h
  52. 15 0
      include/linux/netfilter_ipv6/ip6t_mh.h
  53. 3 1
      include/linux/pfkeyv2.h
  54. 3 1
      include/linux/socket.h
  55. 2 1
      include/linux/sysctl.h
  56. 1 1
      include/linux/tcp.h
  57. 0 8
      include/linux/wanrouter.h
  58. 19 0
      include/linux/xfrm.h
  59. 5 5
      include/net/inet_hashtables.h
  60. 106 0
      include/net/iucv/af_iucv.h
  61. 415 0
      include/net/iucv/iucv.h
  62. 2 0
      include/net/netfilter/nf_conntrack.h
  63. 1 0
      include/net/netfilter/nf_nat.h
  64. 3 2
      include/net/route.h
  65. 2 3
      include/net/tcp.h
  66. 18 0
      include/net/x25.h
  67. 47 0
      include/net/xfrm.h
  68. 1 0
      net/Kconfig
  69. 1 0
      net/Makefile
  70. 2 1
      net/atm/common.c
  71. 7 22
      net/bridge/br_netfilter.c
  72. 9 5
      net/bridge/br_netlink.c
  73. 1 0
      net/bridge/netfilter/ebt_ip.c
  74. 1 0
      net/bridge/netfilter/ebt_log.c
  75. 5 8
      net/core/dev.c
  76. 8 1
      net/core/dst.c
  77. 9 5
      net/core/fib_rules.c
  78. 19 10
      net/core/neighbour.c
  79. 15 8
      net/core/rtnetlink.c
  80. 3 2
      net/dccp/ccids/ccid3.c
  81. 1 1
      net/dccp/ipv4.c
  82. 1 1
      net/dccp/ipv6.c
  83. 2 2
      net/dccp/proto.c
  84. 9 5
      net/decnet/dn_dev.c
  85. 7 4
      net/decnet/dn_table.c
  86. 1 1
      net/ipv4/af_inet.c
  87. 1 1
      net/ipv4/datagram.c
  88. 9 5
      net/ipv4/devinet.c
  89. 9 5
      net/ipv4/fib_semantics.c
  90. 2 0
      net/ipv4/igmp.c
  91. 11 8
      net/ipv4/inet_diag.c
  92. 1 1
      net/ipv4/inet_hashtables.c
  93. 2 2
      net/ipv4/inet_timewait_sock.c
  94. 2 1
      net/ipv4/ip_gre.c
  95. 2 1
      net/ipv4/ipip.c
  96. 0 26
      net/ipv4/netfilter/Kconfig
  97. 0 1
      net/ipv4/netfilter/Makefile
  98. 15 25
      net/ipv4/netfilter/ip_conntrack_proto_tcp.c
  99. 10 2
      net/ipv4/netfilter/ip_nat_core.c
  100. 1 1
      net/ipv4/netfilter/ip_nat_helper.c

+ 4 - 0
Documentation/crypto/api-intro.txt

@@ -193,6 +193,7 @@ Original developers of the crypto algorithms:
   Kartikey Mahendra Bhatt (CAST6)
   Jon Oberheide (ARC4)
   Jouni Malinen (Michael MIC)
+  NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
 
 SHA1 algorithm contributors:
   Jean-Francois Dive
@@ -246,6 +247,9 @@ Tiger algorithm contributors:
 VIA PadLock contributors:
   Michal Ludvig
 
+Camellia algorithm contributors:
+  NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
+
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:

+ 2 - 1
arch/s390/defconfig

@@ -179,6 +179,8 @@ CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_NET_KEY=y
+CONFIG_IUCV=m
+CONFIG_AFIUCV=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -508,7 +510,6 @@ CONFIG_NET_ETHERNET=y
 #
 CONFIG_LCS=m
 CONFIG_CTC=m
-CONFIG_IUCV=m
 # CONFIG_NETIUCV is not set
 # CONFIG_SMSGIUCV is not set
 # CONFIG_CLAW is not set

+ 31 - 0
crypto/Kconfig

@@ -149,6 +149,15 @@ config CRYPTO_CBC
 	  CBC: Cipher Block Chaining mode
 	  This block cipher algorithm is required for IPSec.
 
+config CRYPTO_PCBC
+	tristate "PCBC support"
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_MANAGER
+	default m
+	help
+	  PCBC: Propagating Cipher Block Chaining mode
+	  This block cipher algorithm is required for RxRPC.
+
 config CRYPTO_LRW
 	tristate "LRW support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -168,6 +177,13 @@ config CRYPTO_DES
 	help
 	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 
+config CRYPTO_FCRYPT
+	tristate "FCrypt cipher algorithm"
+	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
+	help
+	  FCrypt algorithm used by RxRPC.
+
 config CRYPTO_BLOWFISH
 	tristate "Blowfish cipher algorithm"
 	select CRYPTO_ALGAPI
@@ -409,6 +425,21 @@ config CRYPTO_CRC32C
 	  See Castagnoli93.  This implementation uses lib/libcrc32c.
           Module will be crc32c.
 
+config CRYPTO_CAMELLIA
+	tristate "Camellia cipher algorithms"
+	depends on CRYPTO
+	select CRYPTO_ALGAPI
+	help
+	  Camellia cipher algorithms module.
+
+	  Camellia is a symmetric key block cipher developed jointly
+	  at NTT and Mitsubishi Electric Corporation.
+
+	  The Camellia specifies three key sizes: 128, 192 and 256 bits.
+
+	  See also:
+	  <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
+
 config CRYPTO_TEST
 	tristate "Testing module"
 	depends on m

+ 3 - 0
crypto/Makefile

@@ -27,13 +27,16 @@ obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
 obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
+obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
 obj-$(CONFIG_CRYPTO_AES) += aes.o
+obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
 obj-$(CONFIG_CRYPTO_ARC4) += arc4.o

+ 12 - 3
crypto/algapi.c

@@ -377,7 +377,8 @@ void crypto_drop_spawn(struct crypto_spawn *spawn)
 }
 EXPORT_SYMBOL_GPL(crypto_drop_spawn);
 
-struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
+struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
+				    u32 mask)
 {
 	struct crypto_alg *alg;
 	struct crypto_alg *alg2;
@@ -396,10 +397,18 @@ struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
 		return ERR_PTR(-EAGAIN);
 	}
 
-	tfm = __crypto_alloc_tfm(alg, 0);
+	tfm = ERR_PTR(-EINVAL);
+	if (unlikely((alg->cra_flags ^ type) & mask))
+		goto out_put_alg;
+
+	tfm = __crypto_alloc_tfm(alg, type, mask);
 	if (IS_ERR(tfm))
-		crypto_mod_put(alg);
+		goto out_put_alg;
+
+	return tfm;
 
+out_put_alg:
+	crypto_mod_put(alg);
 	return tfm;
 }
 EXPORT_SYMBOL_GPL(crypto_spawn_tfm);

+ 16 - 64
crypto/api.c

@@ -212,31 +212,12 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
 }
 EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
 
-static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
+static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 {
-	tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK;
-	flags &= ~CRYPTO_TFM_REQ_MASK;
-	
-	switch (crypto_tfm_alg_type(tfm)) {
-	case CRYPTO_ALG_TYPE_CIPHER:
-		return crypto_init_cipher_flags(tfm, flags);
-		
-	case CRYPTO_ALG_TYPE_DIGEST:
-		return crypto_init_digest_flags(tfm, flags);
-		
-	case CRYPTO_ALG_TYPE_COMPRESS:
-		return crypto_init_compress_flags(tfm, flags);
-	}
-	
-	return 0;
-}
+	const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;
 
-static int crypto_init_ops(struct crypto_tfm *tfm)
-{
-	const struct crypto_type *type = tfm->__crt_alg->cra_type;
-
-	if (type)
-		return type->init(tfm);
+	if (type_obj)
+		return type_obj->init(tfm, type, mask);
 
 	switch (crypto_tfm_alg_type(tfm)) {
 	case CRYPTO_ALG_TYPE_CIPHER:
@@ -285,29 +266,29 @@ static void crypto_exit_ops(struct crypto_tfm *tfm)
 	}
 }
 
-static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags)
+static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
 {
-	const struct crypto_type *type = alg->cra_type;
+	const struct crypto_type *type_obj = alg->cra_type;
 	unsigned int len;
 
 	len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
-	if (type)
-		return len + type->ctxsize(alg);
+	if (type_obj)
+		return len + type_obj->ctxsize(alg, type, mask);
 
 	switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
 	default:
 		BUG();
 
 	case CRYPTO_ALG_TYPE_CIPHER:
-		len += crypto_cipher_ctxsize(alg, flags);
+		len += crypto_cipher_ctxsize(alg);
 		break;
 		
 	case CRYPTO_ALG_TYPE_DIGEST:
-		len += crypto_digest_ctxsize(alg, flags);
+		len += crypto_digest_ctxsize(alg);
 		break;
 		
 	case CRYPTO_ALG_TYPE_COMPRESS:
-		len += crypto_compress_ctxsize(alg, flags);
+		len += crypto_compress_ctxsize(alg);
 		break;
 	}
 
@@ -322,24 +303,21 @@ void crypto_shoot_alg(struct crypto_alg *alg)
 }
 EXPORT_SYMBOL_GPL(crypto_shoot_alg);
 
-struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags)
+struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
+				      u32 mask)
 {
 	struct crypto_tfm *tfm = NULL;
 	unsigned int tfm_size;
 	int err = -ENOMEM;
 
-	tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags);
+	tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
 	tfm = kzalloc(tfm_size, GFP_KERNEL);
 	if (tfm == NULL)
 		goto out_err;
 
 	tfm->__crt_alg = alg;
 
-	err = crypto_init_flags(tfm, flags);
-	if (err)
-		goto out_free_tfm;
-		
-	err = crypto_init_ops(tfm);
+	err = crypto_init_ops(tfm, type, mask);
 	if (err)
 		goto out_free_tfm;
 
@@ -362,31 +340,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
 
-struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
-{
-	struct crypto_tfm *tfm = NULL;
-	int err;
-
-	do {
-		struct crypto_alg *alg;
-
-		alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC);
-		err = PTR_ERR(alg);
-		if (IS_ERR(alg))
-			continue;
-
-		tfm = __crypto_alloc_tfm(alg, flags);
-		err = 0;
-		if (IS_ERR(tfm)) {
-			crypto_mod_put(alg);
-			err = PTR_ERR(tfm);
-			tfm = NULL;
-		}
-	} while (err == -EAGAIN && !signal_pending(current));
-
-	return tfm;
-}
-
 /*
  *	crypto_alloc_base - Locate algorithm and allocate transform
  *	@alg_name: Name of algorithm
@@ -420,7 +373,7 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
 			goto err;
 		}
 
-		tfm = __crypto_alloc_tfm(alg, 0);
+		tfm = __crypto_alloc_tfm(alg, type, mask);
 		if (!IS_ERR(tfm))
 			return tfm;
 
@@ -466,7 +419,6 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
 	kfree(tfm);
 }
 
-EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
 EXPORT_SYMBOL_GPL(crypto_free_tfm);
 
 int crypto_has_alg(const char *name, u32 type, u32 mask)

+ 7 - 2
crypto/blkcipher.c

@@ -16,6 +16,7 @@
 
 #include <linux/crypto.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
@@ -313,6 +314,9 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
 	struct crypto_blkcipher *tfm = desc->tfm;
 	unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
 
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
 	walk->nbytes = walk->total;
 	if (unlikely(!walk->total))
 		return 0;
@@ -345,7 +349,8 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key,
 	return cipher->setkey(tfm, key, keylen);
 }
 
-static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg)
+static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
+					     u32 mask)
 {
 	struct blkcipher_alg *cipher = &alg->cra_blkcipher;
 	unsigned int len = alg->cra_ctxsize;
@@ -358,7 +363,7 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg)
 	return len;
 }
 
-static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm)
+static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 {
 	struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
 	struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;

+ 1801 - 0
crypto/camellia.c

@@ -0,0 +1,1801 @@
+/*
+ * Copyright (C) 2006
+ * NTT (Nippon Telegraph and Telephone Corporation).
+ *
+ * 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; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+/*
+ * Algorithm Specification
+ *  http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ */
+
+/*
+ *
+ * NOTE --- NOTE --- NOTE --- NOTE
+ * This implementation assumes that all memory addresses passed
+ * as parameters are four-byte aligned.
+ *
+ */
+
+#include <linux/crypto.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+
+#define CAMELLIA_MIN_KEY_SIZE        16
+#define CAMELLIA_MAX_KEY_SIZE        32
+#define CAMELLIA_BLOCK_SIZE 16
+#define CAMELLIA_TABLE_BYTE_LEN 272
+#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
+
+typedef u32 KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
+
+
+/* key constants */
+
+#define CAMELLIA_SIGMA1L (0xA09E667FL)
+#define CAMELLIA_SIGMA1R (0x3BCC908BL)
+#define CAMELLIA_SIGMA2L (0xB67AE858L)
+#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
+#define CAMELLIA_SIGMA3L (0xC6EF372FL)
+#define CAMELLIA_SIGMA3R (0xE94F82BEL)
+#define CAMELLIA_SIGMA4L (0x54FF53A5L)
+#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
+#define CAMELLIA_SIGMA5L (0x10E527FAL)
+#define CAMELLIA_SIGMA5R (0xDE682D1DL)
+#define CAMELLIA_SIGMA6L (0xB05688C2L)
+#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
+
+struct camellia_ctx {
+	int key_length;
+	KEY_TABLE_TYPE key_table;
+};
+
+
+/*
+ *  macros
+ */
+
+
+# define GETU32(pt) (((u32)(pt)[0] << 24)	\
+		     ^ ((u32)(pt)[1] << 16)	\
+		     ^ ((u32)(pt)[2] <<  8)	\
+		     ^ ((u32)(pt)[3]))
+
+#define COPY4WORD(dst, src)			\
+    do {					\
+	(dst)[0]=(src)[0];			\
+	(dst)[1]=(src)[1];			\
+	(dst)[2]=(src)[2];			\
+	(dst)[3]=(src)[3];			\
+    }while(0)
+
+#define SWAP4WORD(word)				\
+    do {					\
+	CAMELLIA_SWAP4((word)[0]);		\
+	CAMELLIA_SWAP4((word)[1]);		\
+	CAMELLIA_SWAP4((word)[2]);		\
+	CAMELLIA_SWAP4((word)[3]);		\
+    }while(0)
+
+#define XOR4WORD(a, b)/* a = a ^ b */		\
+    do {					\
+	(a)[0]^=(b)[0];				\
+	(a)[1]^=(b)[1];				\
+	(a)[2]^=(b)[2];				\
+	(a)[3]^=(b)[3];				\
+    }while(0)
+
+#define XOR4WORD2(a, b, c)/* a = b ^ c */	\
+    do {					\
+	(a)[0]=(b)[0]^(c)[0];			\
+	(a)[1]=(b)[1]^(c)[1];			\
+	(a)[2]=(b)[2]^(c)[2];			\
+	(a)[3]=(b)[3]^(c)[3];			\
+    }while(0)
+
+#define CAMELLIA_SUBKEY_L(INDEX) (subkey[(INDEX)*2])
+#define CAMELLIA_SUBKEY_R(INDEX) (subkey[(INDEX)*2 + 1])
+
+/* rotation right shift 1byte */
+#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
+/* rotation left shift 1bit */
+#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
+/* rotation left shift 1byte */
+#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
+
+#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits)	\
+    do {						\
+	w0 = ll;					\
+	ll = (ll << bits) + (lr >> (32 - bits));	\
+	lr = (lr << bits) + (rl >> (32 - bits));	\
+	rl = (rl << bits) + (rr >> (32 - bits));	\
+	rr = (rr << bits) + (w0 >> (32 - bits));	\
+    } while(0)
+
+#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits)	\
+    do {						\
+	w0 = ll;					\
+	w1 = lr;					\
+	ll = (lr << (bits - 32)) + (rl >> (64 - bits));	\
+	lr = (rl << (bits - 32)) + (rr >> (64 - bits));	\
+	rl = (rr << (bits - 32)) + (w0 >> (64 - bits));	\
+	rr = (w0 << (bits - 32)) + (w1 >> (64 - bits));	\
+    } while(0)
+
+#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
+#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
+#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
+#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
+
+#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
+    do {							\
+	il = xl ^ kl;						\
+	ir = xr ^ kr;						\
+	t0 = il >> 16;						\
+	t1 = ir >> 16;						\
+	yl = CAMELLIA_SP1110(ir & 0xff)				\
+	    ^ CAMELLIA_SP0222((t1 >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP3033(t1 & 0xff)			\
+	    ^ CAMELLIA_SP4404((ir >> 8) & 0xff);		\
+	yr = CAMELLIA_SP1110((t0 >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP0222(t0 & 0xff)			\
+	    ^ CAMELLIA_SP3033((il >> 8) & 0xff)			\
+	    ^ CAMELLIA_SP4404(il & 0xff);			\
+	yl ^= yr;						\
+	yr = CAMELLIA_RR8(yr);					\
+	yr ^= yl;						\
+    } while(0)
+
+
+/*
+ * for speed up
+ *
+ */
+#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
+    do {								\
+	t0 = kll;							\
+	t2 = krr;							\
+	t0 &= ll;							\
+	t2 |= rr;							\
+	rl ^= t2;							\
+	lr ^= CAMELLIA_RL1(t0);						\
+	t3 = krl;							\
+	t1 = klr;							\
+	t3 &= rl;							\
+	t1 |= lr;							\
+	ll ^= t1;							\
+	rr ^= CAMELLIA_RL1(t3);						\
+    } while(0)
+
+#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
+    do {								\
+	ir =  CAMELLIA_SP1110(xr & 0xff);				\
+	il =  CAMELLIA_SP1110((xl>>24) & 0xff);				\
+	ir ^= CAMELLIA_SP0222((xr>>24) & 0xff);				\
+	il ^= CAMELLIA_SP0222((xl>>16) & 0xff);				\
+	ir ^= CAMELLIA_SP3033((xr>>16) & 0xff);				\
+	il ^= CAMELLIA_SP3033((xl>>8) & 0xff);				\
+	ir ^= CAMELLIA_SP4404((xr>>8) & 0xff);				\
+	il ^= CAMELLIA_SP4404(xl & 0xff);				\
+	il ^= kl;							\
+	ir ^= il ^ kr;							\
+	yl ^= ir;							\
+	yr ^= CAMELLIA_RR8(il) ^ ir;					\
+    } while(0)
+
+/**
+ * Stuff related to the Camellia key schedule
+ */
+#define SUBL(x) subL[(x)]
+#define SUBR(x) subR[(x)]
+
+
+static const u32 camellia_sp1110[256] = {
+	0x70707000,0x82828200,0x2c2c2c00,0xececec00,
+	0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
+	0xe4e4e400,0x85858500,0x57575700,0x35353500,
+	0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100,
+	0x23232300,0xefefef00,0x6b6b6b00,0x93939300,
+	0x45454500,0x19191900,0xa5a5a500,0x21212100,
+	0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00,
+	0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00,
+	0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00,
+	0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00,
+	0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00,
+	0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00,
+	0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00,
+	0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00,
+	0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600,
+	0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00,
+	0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600,
+	0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00,
+	0x74747400,0x12121200,0x2b2b2b00,0x20202000,
+	0xf0f0f000,0xb1b1b100,0x84848400,0x99999900,
+	0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200,
+	0x34343400,0x7e7e7e00,0x76767600,0x05050500,
+	0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100,
+	0xd1d1d100,0x17171700,0x04040400,0xd7d7d700,
+	0x14141400,0x58585800,0x3a3a3a00,0x61616100,
+	0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00,
+	0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600,
+	0x53535300,0x18181800,0xf2f2f200,0x22222200,
+	0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200,
+	0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100,
+	0x24242400,0x08080800,0xe8e8e800,0xa8a8a800,
+	0x60606000,0xfcfcfc00,0x69696900,0x50505000,
+	0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00,
+	0xa1a1a100,0x89898900,0x62626200,0x97979700,
+	0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500,
+	0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200,
+	0x10101000,0xc4c4c400,0x00000000,0x48484800,
+	0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00,
+	0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00,
+	0x09090900,0x3f3f3f00,0xdddddd00,0x94949400,
+	0x87878700,0x5c5c5c00,0x83838300,0x02020200,
+	0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300,
+	0x73737300,0x67676700,0xf6f6f600,0xf3f3f300,
+	0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200,
+	0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600,
+	0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00,
+	0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00,
+	0x13131300,0xbebebe00,0x63636300,0x2e2e2e00,
+	0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00,
+	0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00,
+	0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600,
+	0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900,
+	0x78787800,0x98989800,0x06060600,0x6a6a6a00,
+	0xe7e7e700,0x46464600,0x71717100,0xbababa00,
+	0xd4d4d400,0x25252500,0xababab00,0x42424200,
+	0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00,
+	0x72727200,0x07070700,0xb9b9b900,0x55555500,
+	0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00,
+	0x36363600,0x49494900,0x2a2a2a00,0x68686800,
+	0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400,
+	0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00,
+	0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100,
+	0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400,
+	0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00,
+};
+
+static const u32 camellia_sp0222[256] = {
+	0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9,
+	0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb,
+	0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a,
+	0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282,
+	0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727,
+	0x008a8a8a,0x00323232,0x004b4b4b,0x00424242,
+	0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c,
+	0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b,
+	0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f,
+	0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d,
+	0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe,
+	0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434,
+	0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595,
+	0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a,
+	0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad,
+	0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a,
+	0x00171717,0x001a1a1a,0x00353535,0x00cccccc,
+	0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a,
+	0x00e8e8e8,0x00242424,0x00565656,0x00404040,
+	0x00e1e1e1,0x00636363,0x00090909,0x00333333,
+	0x00bfbfbf,0x00989898,0x00979797,0x00858585,
+	0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a,
+	0x00dadada,0x006f6f6f,0x00535353,0x00626262,
+	0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf,
+	0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2,
+	0x00bdbdbd,0x00363636,0x00222222,0x00383838,
+	0x00646464,0x001e1e1e,0x00393939,0x002c2c2c,
+	0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444,
+	0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565,
+	0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323,
+	0x00484848,0x00101010,0x00d1d1d1,0x00515151,
+	0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0,
+	0x00555555,0x00a1a1a1,0x00414141,0x00fafafa,
+	0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f,
+	0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b,
+	0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5,
+	0x00202020,0x00898989,0x00000000,0x00909090,
+	0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7,
+	0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5,
+	0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929,
+	0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404,
+	0x009b9b9b,0x00949494,0x00212121,0x00666666,
+	0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7,
+	0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5,
+	0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c,
+	0x00919191,0x006e6e6e,0x008d8d8d,0x00767676,
+	0x00030303,0x002d2d2d,0x00dedede,0x00969696,
+	0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c,
+	0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919,
+	0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d,
+	0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d,
+	0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2,
+	0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4,
+	0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575,
+	0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484,
+	0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5,
+	0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa,
+	0x00f1f1f1,0x00dddddd,0x00595959,0x00141414,
+	0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0,
+	0x00787878,0x00707070,0x00e3e3e3,0x00494949,
+	0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6,
+	0x00777777,0x00939393,0x00868686,0x00838383,
+	0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9,
+	0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d,
+};
+
+static const u32 camellia_sp3033[256] = {
+	0x38003838,0x41004141,0x16001616,0x76007676,
+	0xd900d9d9,0x93009393,0x60006060,0xf200f2f2,
+	0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a,
+	0x75007575,0x06000606,0x57005757,0xa000a0a0,
+	0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9,
+	0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090,
+	0xf600f6f6,0x07000707,0xa700a7a7,0x27002727,
+	0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede,
+	0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7,
+	0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767,
+	0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf,
+	0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d,
+	0x53005353,0xf000f0f0,0x9c009c9c,0x65006565,
+	0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e,
+	0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b,
+	0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6,
+	0xc500c5c5,0x86008686,0x4d004d4d,0x33003333,
+	0xfd00fdfd,0x66006666,0x58005858,0x96009696,
+	0x3a003a3a,0x09000909,0x95009595,0x10001010,
+	0x78007878,0xd800d8d8,0x42004242,0xcc00cccc,
+	0xef00efef,0x26002626,0xe500e5e5,0x61006161,
+	0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282,
+	0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898,
+	0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb,
+	0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0,
+	0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e,
+	0x19001919,0x87008787,0x4e004e4e,0x0b000b0b,
+	0xa900a9a9,0x0c000c0c,0x79007979,0x11001111,
+	0x7f007f7f,0x22002222,0xe700e7e7,0x59005959,
+	0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8,
+	0x12001212,0x04000404,0x74007474,0x54005454,
+	0x30003030,0x7e007e7e,0xb400b4b4,0x28002828,
+	0x55005555,0x68006868,0x50005050,0xbe00bebe,
+	0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb,
+	0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca,
+	0x70007070,0xff00ffff,0x32003232,0x69006969,
+	0x08000808,0x62006262,0x00000000,0x24002424,
+	0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded,
+	0x45004545,0x81008181,0x73007373,0x6d006d6d,
+	0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a,
+	0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101,
+	0xe600e6e6,0x25002525,0x48004848,0x99009999,
+	0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9,
+	0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171,
+	0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313,
+	0x64006464,0x9b009b9b,0x63006363,0x9d009d9d,
+	0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5,
+	0x89008989,0x5f005f5f,0xb100b1b1,0x17001717,
+	0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646,
+	0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747,
+	0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b,
+	0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac,
+	0x3c003c3c,0x4c004c4c,0x03000303,0x35003535,
+	0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d,
+	0x6a006a6a,0x92009292,0xd500d5d5,0x21002121,
+	0x44004444,0x51005151,0xc600c6c6,0x7d007d7d,
+	0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa,
+	0x7c007c7c,0x77007777,0x56005656,0x05000505,
+	0x1b001b1b,0xa400a4a4,0x15001515,0x34003434,
+	0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252,
+	0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd,
+	0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0,
+	0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a,
+	0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f,
+};
+
+static const u32 camellia_sp4404[256] = {
+	0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0,
+	0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae,
+	0x23230023,0x6b6b006b,0x45450045,0xa5a500a5,
+	0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092,
+	0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f,
+	0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b,
+	0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d,
+	0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c,
+	0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0,
+	0x74740074,0x2b2b002b,0xf0f000f0,0x84840084,
+	0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076,
+	0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004,
+	0x14140014,0x3a3a003a,0xdede00de,0x11110011,
+	0x32320032,0x9c9c009c,0x53530053,0xf2f200f2,
+	0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a,
+	0x24240024,0xe8e800e8,0x60600060,0x69690069,
+	0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062,
+	0x54540054,0x1e1e001e,0xe0e000e0,0x64640064,
+	0x10100010,0x00000000,0xa3a300a3,0x75750075,
+	0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd,
+	0x87870087,0x83830083,0xcdcd00cd,0x90900090,
+	0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf,
+	0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6,
+	0x81810081,0x6f6f006f,0x13130013,0x63630063,
+	0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc,
+	0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4,
+	0x78780078,0x06060006,0xe7e700e7,0x71710071,
+	0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d,
+	0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac,
+	0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1,
+	0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043,
+	0x15150015,0xadad00ad,0x77770077,0x80800080,
+	0x82820082,0xecec00ec,0x27270027,0xe5e500e5,
+	0x85850085,0x35350035,0x0c0c000c,0x41410041,
+	0xefef00ef,0x93930093,0x19190019,0x21210021,
+	0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd,
+	0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce,
+	0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a,
+	0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d,
+	0x01010001,0xd6d600d6,0x56560056,0x4d4d004d,
+	0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d,
+	0x12120012,0x20200020,0xb1b100b1,0x99990099,
+	0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005,
+	0xb7b700b7,0x31310031,0x17170017,0xd7d700d7,
+	0x58580058,0x61610061,0x1b1b001b,0x1c1c001c,
+	0x0f0f000f,0x16160016,0x18180018,0x22220022,
+	0x44440044,0xb2b200b2,0xb5b500b5,0x91910091,
+	0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050,
+	0xd0d000d0,0x7d7d007d,0x89890089,0x97970097,
+	0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2,
+	0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db,
+	0x03030003,0xdada00da,0x3f3f003f,0x94940094,
+	0x5c5c005c,0x02020002,0x4a4a004a,0x33330033,
+	0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2,
+	0x9b9b009b,0x26260026,0x37370037,0x3b3b003b,
+	0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e,
+	0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e,
+	0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059,
+	0x98980098,0x6a6a006a,0x46460046,0xbaba00ba,
+	0x25250025,0x42420042,0xa2a200a2,0xfafa00fa,
+	0x07070007,0x55550055,0xeeee00ee,0x0a0a000a,
+	0x49490049,0x68680068,0x38380038,0xa4a400a4,
+	0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1,
+	0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e,
+};
+
+
+
+static void camellia_setup128(const unsigned char *key, u32 *subkey)
+{
+	u32 kll, klr, krl, krr;
+	u32 il, ir, t0, t1, w0, w1;
+	u32 kw4l, kw4r, dw, tl, tr;
+	u32 subL[26];
+	u32 subR[26];
+
+	/**
+	 *  k == kll || klr || krl || krr (|| is concatination)
+	 */
+	kll = GETU32(key     );
+	klr = GETU32(key +  4);
+	krl = GETU32(key +  8);
+	krr = GETU32(key + 12);
+	/**
+	 * generate KL dependent subkeys
+	 */
+	/* kw1 */
+	SUBL(0) = kll; SUBR(0) = klr;
+	/* kw2 */
+	SUBL(1) = krl; SUBR(1) = krr;
+	/* rotation left shift 15bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k3 */
+	SUBL(4) = kll; SUBR(4) = klr;
+	/* k4 */
+	SUBL(5) = krl; SUBR(5) = krr;
+	/* rotation left shift 15+30bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+	/* k7 */
+	SUBL(10) = kll; SUBR(10) = klr;
+	/* k8 */
+	SUBL(11) = krl; SUBR(11) = krr;
+	/* rotation left shift 15+30+15bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k10 */
+	SUBL(13) = krl; SUBR(13) = krr;
+	/* rotation left shift 15+30+15+17 bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* kl3 */
+	SUBL(16) = kll; SUBR(16) = klr;
+	/* kl4 */
+	SUBL(17) = krl; SUBR(17) = krr;
+	/* rotation left shift 15+30+15+17+17 bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* k13 */
+	SUBL(18) = kll; SUBR(18) = klr;
+	/* k14 */
+	SUBL(19) = krl; SUBR(19) = krr;
+	/* rotation left shift 15+30+15+17+17+17 bit */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* k17 */
+	SUBL(22) = kll; SUBR(22) = klr;
+	/* k18 */
+	SUBL(23) = krl; SUBR(23) = krr;
+
+	/* generate KA */
+	kll = SUBL(0); klr = SUBR(0);
+	krl = SUBL(1); krr = SUBR(1);
+	CAMELLIA_F(kll, klr,
+		   CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+		   w0, w1, il, ir, t0, t1);
+	krl ^= w0; krr ^= w1;
+	CAMELLIA_F(krl, krr,
+		   CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
+		   kll, klr, il, ir, t0, t1);
+	/* current status == (kll, klr, w0, w1) */
+	CAMELLIA_F(kll, klr,
+		   CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
+		   krl, krr, il, ir, t0, t1);
+	krl ^= w0; krr ^= w1;
+	CAMELLIA_F(krl, krr,
+		   CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
+		   w0, w1, il, ir, t0, t1);
+	kll ^= w0; klr ^= w1;
+
+	/* generate KA dependent subkeys */
+	/* k1, k2 */
+	SUBL(2) = kll; SUBR(2) = klr;
+	SUBL(3) = krl; SUBR(3) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k5,k6 */
+	SUBL(6) = kll; SUBR(6) = klr;
+	SUBL(7) = krl; SUBR(7) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* kl1, kl2 */
+	SUBL(8) = kll; SUBR(8) = klr;
+	SUBL(9) = krl; SUBR(9) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k9 */
+	SUBL(12) = kll; SUBR(12) = klr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k11, k12 */
+	SUBL(14) = kll; SUBR(14) = klr;
+	SUBL(15) = krl; SUBR(15) = krr;
+	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+	/* k15, k16 */
+	SUBL(20) = kll; SUBR(20) = klr;
+	SUBL(21) = krl; SUBR(21) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* kw3, kw4 */
+	SUBL(24) = kll; SUBR(24) = klr;
+	SUBL(25) = krl; SUBR(25) = krr;
+
+
+	/* absorb kw2 to other subkeys */
+	/* round 2 */
+	SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
+	/* round 4 */
+	SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
+	/* round 6 */
+	SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(9);
+	dw = SUBL(1) & SUBL(9),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
+	/* round 8 */
+	SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
+	/* round 10 */
+	SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
+	/* round 12 */
+	SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(17);
+	dw = SUBL(1) & SUBL(17),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
+	/* round 14 */
+	SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
+	/* round 16 */
+	SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
+	/* round 18 */
+	SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
+	/* kw3 */
+	SUBL(24) ^= SUBL(1); SUBR(24) ^= SUBR(1);
+
+	/* absorb kw4 to other subkeys */
+	kw4l = SUBL(25); kw4r = SUBR(25);
+	/* round 17 */
+	SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
+	/* round 15 */
+	SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
+	/* round 13 */
+	SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(16);
+	dw = kw4l & SUBL(16),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
+	/* round 11 */
+	SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
+	/* round 9 */
+	SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
+	/* round 7 */
+	SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(8);
+	dw = kw4l & SUBL(8),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
+	/* round 5 */
+	SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
+	/* round 3 */
+	SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
+	/* round 1 */
+	SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
+	/* kw1 */
+	SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
+
+
+	/* key XOR is end of F-function */
+	CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
+	CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
+	CAMELLIA_SUBKEY_L(2) = SUBL(3);       /* round 1 */
+	CAMELLIA_SUBKEY_R(2) = SUBR(3);
+	CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
+	CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
+	CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
+	CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
+	CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
+	CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
+	CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
+	CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
+	tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
+	dw = tl & SUBL(8),  /* FL(kl1) */
+		tr = SUBR(10) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
+	CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
+	CAMELLIA_SUBKEY_L(8) = SUBL(8);       /* FL(kl1) */
+	CAMELLIA_SUBKEY_R(8) = SUBR(8);
+	CAMELLIA_SUBKEY_L(9) = SUBL(9);       /* FLinv(kl2) */
+	CAMELLIA_SUBKEY_R(9) = SUBR(9);
+	tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
+	dw = tl & SUBL(9),  /* FLinv(kl2) */
+		tr = SUBR(7) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
+	CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
+	CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
+	CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
+	CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
+	CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
+	CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
+	CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
+	CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
+	CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
+	tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
+	dw = tl & SUBL(16), /* FL(kl3) */
+		tr = SUBR(18) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
+	CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
+	CAMELLIA_SUBKEY_L(16) = SUBL(16);     /* FL(kl3) */
+	CAMELLIA_SUBKEY_R(16) = SUBR(16);
+	CAMELLIA_SUBKEY_L(17) = SUBL(17);     /* FLinv(kl4) */
+	CAMELLIA_SUBKEY_R(17) = SUBR(17);
+	tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
+	dw = tl & SUBL(17), /* FLinv(kl4) */
+		tr = SUBR(15) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
+	CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
+	CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
+	CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
+	CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
+	CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
+	CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
+	CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
+	CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
+	CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
+	CAMELLIA_SUBKEY_L(23) = SUBL(22);     /* round 18 */
+	CAMELLIA_SUBKEY_R(23) = SUBR(22);
+	CAMELLIA_SUBKEY_L(24) = SUBL(24) ^ SUBL(23); /* kw3 */
+	CAMELLIA_SUBKEY_R(24) = SUBR(24) ^ SUBR(23);
+
+	/* apply the inverse of the last half of P-function */
+	dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
+		dw = CAMELLIA_RL8(dw);/* round 1 */
+	CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
+		CAMELLIA_SUBKEY_L(2) = dw;
+	dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
+		dw = CAMELLIA_RL8(dw);/* round 2 */
+	CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
+		CAMELLIA_SUBKEY_L(3) = dw;
+	dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
+		dw = CAMELLIA_RL8(dw);/* round 3 */
+	CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
+		CAMELLIA_SUBKEY_L(4) = dw;
+	dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
+		dw = CAMELLIA_RL8(dw);/* round 4 */
+	CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
+		CAMELLIA_SUBKEY_L(5) = dw;
+	dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
+		dw = CAMELLIA_RL8(dw);/* round 5 */
+	CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
+		CAMELLIA_SUBKEY_L(6) = dw;
+	dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
+		dw = CAMELLIA_RL8(dw);/* round 6 */
+	CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
+		CAMELLIA_SUBKEY_L(7) = dw;
+	dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
+		dw = CAMELLIA_RL8(dw);/* round 7 */
+	CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
+		CAMELLIA_SUBKEY_L(10) = dw;
+	dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
+		dw = CAMELLIA_RL8(dw);/* round 8 */
+	CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
+		CAMELLIA_SUBKEY_L(11) = dw;
+	dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
+		dw = CAMELLIA_RL8(dw);/* round 9 */
+	CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
+		CAMELLIA_SUBKEY_L(12) = dw;
+	dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
+		dw = CAMELLIA_RL8(dw);/* round 10 */
+	CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
+		CAMELLIA_SUBKEY_L(13) = dw;
+	dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
+		dw = CAMELLIA_RL8(dw);/* round 11 */
+	CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
+		CAMELLIA_SUBKEY_L(14) = dw;
+	dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
+		dw = CAMELLIA_RL8(dw);/* round 12 */
+	CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
+		CAMELLIA_SUBKEY_L(15) = dw;
+	dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
+		dw = CAMELLIA_RL8(dw);/* round 13 */
+	CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
+		CAMELLIA_SUBKEY_L(18) = dw;
+	dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
+		dw = CAMELLIA_RL8(dw);/* round 14 */
+	CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
+		CAMELLIA_SUBKEY_L(19) = dw;
+	dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
+		dw = CAMELLIA_RL8(dw);/* round 15 */
+	CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
+		CAMELLIA_SUBKEY_L(20) = dw;
+	dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
+		dw = CAMELLIA_RL8(dw);/* round 16 */
+	CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
+		CAMELLIA_SUBKEY_L(21) = dw;
+	dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
+		dw = CAMELLIA_RL8(dw);/* round 17 */
+	CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
+		CAMELLIA_SUBKEY_L(22) = dw;
+	dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
+		dw = CAMELLIA_RL8(dw);/* round 18 */
+	CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
+		CAMELLIA_SUBKEY_L(23) = dw;
+
+	return;
+}
+
+
+static void camellia_setup256(const unsigned char *key, u32 *subkey)
+{
+	u32 kll,klr,krl,krr;           /* left half of key */
+	u32 krll,krlr,krrl,krrr;       /* right half of key */
+	u32 il, ir, t0, t1, w0, w1;    /* temporary variables */
+	u32 kw4l, kw4r, dw, tl, tr;
+	u32 subL[34];
+	u32 subR[34];
+
+	/**
+	 *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
+	 *  (|| is concatination)
+	 */
+
+	kll  = GETU32(key     );
+	klr  = GETU32(key +  4);
+	krl  = GETU32(key +  8);
+	krr  = GETU32(key + 12);
+	krll = GETU32(key + 16);
+	krlr = GETU32(key + 20);
+	krrl = GETU32(key + 24);
+	krrr = GETU32(key + 28);
+
+	/* generate KL dependent subkeys */
+	/* kw1 */
+	SUBL(0) = kll; SUBR(0) = klr;
+	/* kw2 */
+	SUBL(1) = krl; SUBR(1) = krr;
+	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
+	/* k9 */
+	SUBL(12) = kll; SUBR(12) = klr;
+	/* k10 */
+	SUBL(13) = krl; SUBR(13) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* kl3 */
+	SUBL(16) = kll; SUBR(16) = klr;
+	/* kl4 */
+	SUBL(17) = krl; SUBR(17) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+	/* k17 */
+	SUBL(22) = kll; SUBR(22) = klr;
+	/* k18 */
+	SUBL(23) = krl; SUBR(23) = krr;
+	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+	/* k23 */
+	SUBL(30) = kll; SUBR(30) = klr;
+	/* k24 */
+	SUBL(31) = krl; SUBR(31) = krr;
+
+	/* generate KR dependent subkeys */
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+	/* k3 */
+	SUBL(4) = krll; SUBR(4) = krlr;
+	/* k4 */
+	SUBL(5) = krrl; SUBR(5) = krrr;
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+	/* kl1 */
+	SUBL(8) = krll; SUBR(8) = krlr;
+	/* kl2 */
+	SUBL(9) = krrl; SUBR(9) = krrr;
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+	/* k13 */
+	SUBL(18) = krll; SUBR(18) = krlr;
+	/* k14 */
+	SUBL(19) = krrl; SUBR(19) = krrr;
+	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+	/* k19 */
+	SUBL(26) = krll; SUBR(26) = krlr;
+	/* k20 */
+	SUBL(27) = krrl; SUBR(27) = krrr;
+	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+
+	/* generate KA */
+	kll = SUBL(0) ^ krll; klr = SUBR(0) ^ krlr;
+	krl = SUBL(1) ^ krrl; krr = SUBR(1) ^ krrr;
+	CAMELLIA_F(kll, klr,
+		   CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+		   w0, w1, il, ir, t0, t1);
+	krl ^= w0; krr ^= w1;
+	CAMELLIA_F(krl, krr,
+		   CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R,
+		   kll, klr, il, ir, t0, t1);
+	kll ^= krll; klr ^= krlr;
+	CAMELLIA_F(kll, klr,
+		   CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R,
+		   krl, krr, il, ir, t0, t1);
+	krl ^= w0 ^ krrl; krr ^= w1 ^ krrr;
+	CAMELLIA_F(krl, krr,
+		   CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R,
+		   w0, w1, il, ir, t0, t1);
+	kll ^= w0; klr ^= w1;
+
+	/* generate KB */
+	krll ^= kll; krlr ^= klr;
+	krrl ^= krl; krrr ^= krr;
+	CAMELLIA_F(krll, krlr,
+		   CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R,
+		   w0, w1, il, ir, t0, t1);
+	krrl ^= w0; krrr ^= w1;
+	CAMELLIA_F(krrl, krrr,
+		   CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R,
+		   w0, w1, il, ir, t0, t1);
+	krll ^= w0; krlr ^= w1;
+
+	/* generate KA dependent subkeys */
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+	/* k5 */
+	SUBL(6) = kll; SUBR(6) = klr;
+	/* k6 */
+	SUBL(7) = krl; SUBR(7) = krr;
+	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+	/* k11 */
+	SUBL(14) = kll; SUBR(14) = klr;
+	/* k12 */
+	SUBL(15) = krl; SUBR(15) = krr;
+	/* rotation left shift 32bit */
+	/* kl5 */
+	SUBL(24) = klr; SUBR(24) = krl;
+	/* kl6 */
+	SUBL(25) = krr; SUBR(25) = kll;
+	/* rotation left shift 49 from k11,k12 -> k21,k22 */
+	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
+	/* k21 */
+	SUBL(28) = kll; SUBR(28) = klr;
+	/* k22 */
+	SUBL(29) = krl; SUBR(29) = krr;
+
+	/* generate KB dependent subkeys */
+	/* k1 */
+	SUBL(2) = krll; SUBR(2) = krlr;
+	/* k2 */
+	SUBL(3) = krrl; SUBR(3) = krrr;
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+	/* k7 */
+	SUBL(10) = krll; SUBR(10) = krlr;
+	/* k8 */
+	SUBL(11) = krrl; SUBR(11) = krrr;
+	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+	/* k15 */
+	SUBL(20) = krll; SUBR(20) = krlr;
+	/* k16 */
+	SUBL(21) = krrl; SUBR(21) = krrr;
+	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
+	/* kw3 */
+	SUBL(32) = krll; SUBR(32) = krlr;
+	/* kw4 */
+	SUBL(33) = krrl; SUBR(33) = krrr;
+
+	/* absorb kw2 to other subkeys */
+	/* round 2 */
+	SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
+	/* round 4 */
+	SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
+	/* round 6 */
+	SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(9);
+	dw = SUBL(1) & SUBL(9),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
+	/* round 8 */
+	SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
+	/* round 10 */
+	SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
+	/* round 12 */
+	SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(17);
+	dw = SUBL(1) & SUBL(17),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
+	/* round 14 */
+	SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
+	/* round 16 */
+	SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
+	/* round 18 */
+	SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
+	SUBL(1) ^= SUBR(1) & ~SUBR(25);
+	dw = SUBL(1) & SUBL(25),
+		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl6) */
+	/* round 20 */
+	SUBL(27) ^= SUBL(1); SUBR(27) ^= SUBR(1);
+	/* round 22 */
+	SUBL(29) ^= SUBL(1); SUBR(29) ^= SUBR(1);
+	/* round 24 */
+	SUBL(31) ^= SUBL(1); SUBR(31) ^= SUBR(1);
+	/* kw3 */
+	SUBL(32) ^= SUBL(1); SUBR(32) ^= SUBR(1);
+
+
+	/* absorb kw4 to other subkeys */
+	kw4l = SUBL(33); kw4r = SUBR(33);
+	/* round 23 */
+	SUBL(30) ^= kw4l; SUBR(30) ^= kw4r;
+	/* round 21 */
+	SUBL(28) ^= kw4l; SUBR(28) ^= kw4r;
+	/* round 19 */
+	SUBL(26) ^= kw4l; SUBR(26) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(24);
+	dw = kw4l & SUBL(24),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl5) */
+	/* round 17 */
+	SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
+	/* round 15 */
+	SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
+	/* round 13 */
+	SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(16);
+	dw = kw4l & SUBL(16),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
+	/* round 11 */
+	SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
+	/* round 9 */
+	SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
+	/* round 7 */
+	SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
+	kw4l ^= kw4r & ~SUBR(8);
+	dw = kw4l & SUBL(8),
+		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
+	/* round 5 */
+	SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
+	/* round 3 */
+	SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
+	/* round 1 */
+	SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
+	/* kw1 */
+	SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
+
+	/* key XOR is end of F-function */
+	CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
+	CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
+	CAMELLIA_SUBKEY_L(2) = SUBL(3);       /* round 1 */
+	CAMELLIA_SUBKEY_R(2) = SUBR(3);
+	CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
+	CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
+	CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
+	CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
+	CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
+	CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
+	CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
+	CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
+	tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
+	dw = tl & SUBL(8),  /* FL(kl1) */
+		tr = SUBR(10) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
+	CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
+	CAMELLIA_SUBKEY_L(8) = SUBL(8);       /* FL(kl1) */
+	CAMELLIA_SUBKEY_R(8) = SUBR(8);
+	CAMELLIA_SUBKEY_L(9) = SUBL(9);       /* FLinv(kl2) */
+	CAMELLIA_SUBKEY_R(9) = SUBR(9);
+	tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
+	dw = tl & SUBL(9),  /* FLinv(kl2) */
+		tr = SUBR(7) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
+	CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
+	CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
+	CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
+	CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
+	CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
+	CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
+	CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
+	CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
+	CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
+	tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
+	dw = tl & SUBL(16), /* FL(kl3) */
+		tr = SUBR(18) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
+	CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
+	CAMELLIA_SUBKEY_L(16) = SUBL(16);     /* FL(kl3) */
+	CAMELLIA_SUBKEY_R(16) = SUBR(16);
+	CAMELLIA_SUBKEY_L(17) = SUBL(17);     /* FLinv(kl4) */
+	CAMELLIA_SUBKEY_R(17) = SUBR(17);
+	tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
+	dw = tl & SUBL(17), /* FLinv(kl4) */
+		tr = SUBR(15) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
+	CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
+	CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
+	CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
+	CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
+	CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
+	CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
+	CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
+	CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
+	CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
+	tl = SUBL(26) ^ (SUBR(26)
+			 & ~SUBR(24));
+	dw = tl & SUBL(24), /* FL(kl5) */
+		tr = SUBR(26) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(23) = SUBL(22) ^ tl; /* round 18 */
+	CAMELLIA_SUBKEY_R(23) = SUBR(22) ^ tr;
+	CAMELLIA_SUBKEY_L(24) = SUBL(24);     /* FL(kl5) */
+	CAMELLIA_SUBKEY_R(24) = SUBR(24);
+	CAMELLIA_SUBKEY_L(25) = SUBL(25);     /* FLinv(kl6) */
+	CAMELLIA_SUBKEY_R(25) = SUBR(25);
+	tl = SUBL(23) ^ (SUBR(23) &
+			 ~SUBR(25));
+	dw = tl & SUBL(25), /* FLinv(kl6) */
+		tr = SUBR(23) ^ CAMELLIA_RL1(dw);
+	CAMELLIA_SUBKEY_L(26) = tl ^ SUBL(27); /* round 19 */
+	CAMELLIA_SUBKEY_R(26) = tr ^ SUBR(27);
+	CAMELLIA_SUBKEY_L(27) = SUBL(26) ^ SUBL(28); /* round 20 */
+	CAMELLIA_SUBKEY_R(27) = SUBR(26) ^ SUBR(28);
+	CAMELLIA_SUBKEY_L(28) = SUBL(27) ^ SUBL(29); /* round 21 */
+	CAMELLIA_SUBKEY_R(28) = SUBR(27) ^ SUBR(29);
+	CAMELLIA_SUBKEY_L(29) = SUBL(28) ^ SUBL(30); /* round 22 */
+	CAMELLIA_SUBKEY_R(29) = SUBR(28) ^ SUBR(30);
+	CAMELLIA_SUBKEY_L(30) = SUBL(29) ^ SUBL(31); /* round 23 */
+	CAMELLIA_SUBKEY_R(30) = SUBR(29) ^ SUBR(31);
+	CAMELLIA_SUBKEY_L(31) = SUBL(30);     /* round 24 */
+	CAMELLIA_SUBKEY_R(31) = SUBR(30);
+	CAMELLIA_SUBKEY_L(32) = SUBL(32) ^ SUBL(31); /* kw3 */
+	CAMELLIA_SUBKEY_R(32) = SUBR(32) ^ SUBR(31);
+
+	/* apply the inverse of the last half of P-function */
+	dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
+		dw = CAMELLIA_RL8(dw);/* round 1 */
+	CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
+		CAMELLIA_SUBKEY_L(2) = dw;
+	dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
+		dw = CAMELLIA_RL8(dw);/* round 2 */
+	CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
+		CAMELLIA_SUBKEY_L(3) = dw;
+	dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
+		dw = CAMELLIA_RL8(dw);/* round 3 */
+	CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
+		CAMELLIA_SUBKEY_L(4) = dw;
+	dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
+		dw = CAMELLIA_RL8(dw);/* round 4 */
+	CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
+	CAMELLIA_SUBKEY_L(5) = dw;
+	dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
+		dw = CAMELLIA_RL8(dw);/* round 5 */
+	CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
+		CAMELLIA_SUBKEY_L(6) = dw;
+	dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
+		dw = CAMELLIA_RL8(dw);/* round 6 */
+	CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
+		CAMELLIA_SUBKEY_L(7) = dw;
+	dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
+		dw = CAMELLIA_RL8(dw);/* round 7 */
+	CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
+		CAMELLIA_SUBKEY_L(10) = dw;
+	dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
+	    dw = CAMELLIA_RL8(dw);/* round 8 */
+	CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
+		CAMELLIA_SUBKEY_L(11) = dw;
+	dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
+		dw = CAMELLIA_RL8(dw);/* round 9 */
+	CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
+		CAMELLIA_SUBKEY_L(12) = dw;
+	dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
+		dw = CAMELLIA_RL8(dw);/* round 10 */
+	CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
+		CAMELLIA_SUBKEY_L(13) = dw;
+	dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
+		dw = CAMELLIA_RL8(dw);/* round 11 */
+	CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
+		CAMELLIA_SUBKEY_L(14) = dw;
+	dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
+		dw = CAMELLIA_RL8(dw);/* round 12 */
+	CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
+		CAMELLIA_SUBKEY_L(15) = dw;
+	dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
+		dw = CAMELLIA_RL8(dw);/* round 13 */
+	CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
+		CAMELLIA_SUBKEY_L(18) = dw;
+	dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
+		dw = CAMELLIA_RL8(dw);/* round 14 */
+	CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
+		CAMELLIA_SUBKEY_L(19) = dw;
+	dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
+		dw = CAMELLIA_RL8(dw);/* round 15 */
+	CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
+		CAMELLIA_SUBKEY_L(20) = dw;
+	dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
+		dw = CAMELLIA_RL8(dw);/* round 16 */
+	CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
+		CAMELLIA_SUBKEY_L(21) = dw;
+	dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
+		dw = CAMELLIA_RL8(dw);/* round 17 */
+	CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
+		CAMELLIA_SUBKEY_L(22) = dw;
+	dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
+		dw = CAMELLIA_RL8(dw);/* round 18 */
+	CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
+		CAMELLIA_SUBKEY_L(23) = dw;
+	dw = CAMELLIA_SUBKEY_L(26) ^ CAMELLIA_SUBKEY_R(26),
+		dw = CAMELLIA_RL8(dw);/* round 19 */
+	CAMELLIA_SUBKEY_R(26) = CAMELLIA_SUBKEY_L(26) ^ dw,
+		CAMELLIA_SUBKEY_L(26) = dw;
+	dw = CAMELLIA_SUBKEY_L(27) ^ CAMELLIA_SUBKEY_R(27),
+		dw = CAMELLIA_RL8(dw);/* round 20 */
+	CAMELLIA_SUBKEY_R(27) = CAMELLIA_SUBKEY_L(27) ^ dw,
+		CAMELLIA_SUBKEY_L(27) = dw;
+	dw = CAMELLIA_SUBKEY_L(28) ^ CAMELLIA_SUBKEY_R(28),
+		dw = CAMELLIA_RL8(dw);/* round 21 */
+	CAMELLIA_SUBKEY_R(28) = CAMELLIA_SUBKEY_L(28) ^ dw,
+		CAMELLIA_SUBKEY_L(28) = dw;
+	dw = CAMELLIA_SUBKEY_L(29) ^ CAMELLIA_SUBKEY_R(29),
+		dw = CAMELLIA_RL8(dw);/* round 22 */
+	CAMELLIA_SUBKEY_R(29) = CAMELLIA_SUBKEY_L(29) ^ dw,
+		CAMELLIA_SUBKEY_L(29) = dw;
+	dw = CAMELLIA_SUBKEY_L(30) ^ CAMELLIA_SUBKEY_R(30),
+		dw = CAMELLIA_RL8(dw);/* round 23 */
+	CAMELLIA_SUBKEY_R(30) = CAMELLIA_SUBKEY_L(30) ^ dw,
+		CAMELLIA_SUBKEY_L(30) = dw;
+	dw = CAMELLIA_SUBKEY_L(31) ^ CAMELLIA_SUBKEY_R(31),
+		dw = CAMELLIA_RL8(dw);/* round 24 */
+	CAMELLIA_SUBKEY_R(31) = CAMELLIA_SUBKEY_L(31) ^ dw,
+		CAMELLIA_SUBKEY_L(31) = dw;
+
+	return;
+}
+
+static void camellia_setup192(const unsigned char *key, u32 *subkey)
+{
+	unsigned char kk[32];
+	u32 krll, krlr, krrl,krrr;
+
+	memcpy(kk, key, 24);
+	memcpy((unsigned char *)&krll, key+16,4);
+	memcpy((unsigned char *)&krlr, key+20,4);
+	krrl = ~krll;
+	krrr = ~krlr;
+	memcpy(kk+24, (unsigned char *)&krrl, 4);
+	memcpy(kk+28, (unsigned char *)&krrr, 4);
+	camellia_setup256(kk, subkey);
+	return;
+}
+
+
+/**
+ * Stuff related to camellia encryption/decryption
+ */
+static void camellia_encrypt128(const u32 *subkey, __be32 *io_text)
+{
+	u32 il,ir,t0,t1;               /* temporary valiables */
+
+	u32 io[4];
+
+	io[0] = be32_to_cpu(io_text[0]);
+	io[1] = be32_to_cpu(io_text[1]);
+	io[2] = be32_to_cpu(io_text[2]);
+	io[3] = be32_to_cpu(io_text[3]);
+
+	/* pre whitening but absorb kw2*/
+	io[0] ^= CAMELLIA_SUBKEY_L(0);
+	io[1] ^= CAMELLIA_SUBKEY_R(0);
+	/* main iteration */
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+			 io[0],io[1],il,ir,t0,t1);
+
+	/* post whitening but kw4 */
+	io[2] ^= CAMELLIA_SUBKEY_L(24);
+	io[3] ^= CAMELLIA_SUBKEY_R(24);
+
+	t0 = io[0];
+	t1 = io[1];
+	io[0] = io[2];
+	io[1] = io[3];
+	io[2] = t0;
+	io[3] = t1;
+
+	io_text[0] = cpu_to_be32(io[0]);
+	io_text[1] = cpu_to_be32(io[1]);
+	io_text[2] = cpu_to_be32(io[2]);
+	io_text[3] = cpu_to_be32(io[3]);
+
+	return;
+}
+
+static void camellia_decrypt128(const u32 *subkey, __be32 *io_text)
+{
+	u32 il,ir,t0,t1;               /* temporary valiables */
+
+	u32 io[4];
+
+	io[0] = be32_to_cpu(io_text[0]);
+	io[1] = be32_to_cpu(io_text[1]);
+	io[2] = be32_to_cpu(io_text[2]);
+	io[3] = be32_to_cpu(io_text[3]);
+
+	/* pre whitening but absorb kw2*/
+	io[0] ^= CAMELLIA_SUBKEY_L(24);
+	io[1] ^= CAMELLIA_SUBKEY_R(24);
+
+	/* main iteration */
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+			 io[0],io[1],il,ir,t0,t1);
+
+	/* post whitening but kw4 */
+	io[2] ^= CAMELLIA_SUBKEY_L(0);
+	io[3] ^= CAMELLIA_SUBKEY_R(0);
+
+	t0 = io[0];
+	t1 = io[1];
+	io[0] = io[2];
+	io[1] = io[3];
+	io[2] = t0;
+	io[3] = t1;
+
+	io_text[0] = cpu_to_be32(io[0]);
+	io_text[1] = cpu_to_be32(io[1]);
+	io_text[2] = cpu_to_be32(io[2]);
+	io_text[3] = cpu_to_be32(io[3]);
+
+	return;
+}
+
+
+/**
+ * stuff for 192 and 256bit encryption/decryption
+ */
+static void camellia_encrypt256(const u32 *subkey, __be32 *io_text)
+{
+	u32 il,ir,t0,t1;           /* temporary valiables */
+
+	u32 io[4];
+
+	io[0] = be32_to_cpu(io_text[0]);
+	io[1] = be32_to_cpu(io_text[1]);
+	io[2] = be32_to_cpu(io_text[2]);
+	io[3] = be32_to_cpu(io_text[3]);
+
+	/* pre whitening but absorb kw2*/
+	io[0] ^= CAMELLIA_SUBKEY_L(0);
+	io[1] ^= CAMELLIA_SUBKEY_R(0);
+
+	/* main iteration */
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
+		     CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
+			 io[0],io[1],il,ir,t0,t1);
+
+	/* post whitening but kw4 */
+	io[2] ^= CAMELLIA_SUBKEY_L(32);
+	io[3] ^= CAMELLIA_SUBKEY_R(32);
+
+	t0 = io[0];
+	t1 = io[1];
+	io[0] = io[2];
+	io[1] = io[3];
+	io[2] = t0;
+	io[3] = t1;
+
+	io_text[0] = cpu_to_be32(io[0]);
+	io_text[1] = cpu_to_be32(io[1]);
+	io_text[2] = cpu_to_be32(io[2]);
+	io_text[3] = cpu_to_be32(io[3]);
+
+	return;
+}
+
+
+static void camellia_decrypt256(const u32 *subkey, __be32 *io_text)
+{
+	u32 il,ir,t0,t1;           /* temporary valiables */
+
+	u32 io[4];
+
+	io[0] = be32_to_cpu(io_text[0]);
+	io[1] = be32_to_cpu(io_text[1]);
+	io[2] = be32_to_cpu(io_text[2]);
+	io[3] = be32_to_cpu(io_text[3]);
+
+	/* pre whitening but absorb kw2*/
+	io[0] ^= CAMELLIA_SUBKEY_L(32);
+	io[1] ^= CAMELLIA_SUBKEY_R(32);
+
+	/* main iteration */
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
+		     CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+			 io[0],io[1],il,ir,t0,t1);
+
+	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+		     t0,t1,il,ir);
+
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+			 io[0],io[1],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[0],io[1],
+			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+			 io[2],io[3],il,ir,t0,t1);
+	CAMELLIA_ROUNDSM(io[2],io[3],
+			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+			 io[0],io[1],il,ir,t0,t1);
+
+	/* post whitening but kw4 */
+	io[2] ^= CAMELLIA_SUBKEY_L(0);
+	io[3] ^= CAMELLIA_SUBKEY_R(0);
+
+	t0 = io[0];
+	t1 = io[1];
+	io[0] = io[2];
+	io[1] = io[3];
+	io[2] = t0;
+	io[3] = t1;
+
+	io_text[0] = cpu_to_be32(io[0]);
+	io_text[1] = cpu_to_be32(io[1]);
+	io_text[2] = cpu_to_be32(io[2]);
+	io_text[3] = cpu_to_be32(io[3]);
+
+	return;
+}
+
+
+static int
+camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		 unsigned int key_len)
+{
+	struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
+	const unsigned char *key = (const unsigned char *)in_key;
+	u32 *flags = &tfm->crt_flags;
+
+	if (key_len != 16 && key_len != 24 && key_len != 32) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	cctx->key_length = key_len;
+
+	switch(key_len) {
+	case 16:
+		camellia_setup128(key, cctx->key_table);
+		break;
+	case 24:
+		camellia_setup192(key, cctx->key_table);
+		break;
+	case 32:
+		camellia_setup256(key, cctx->key_table);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+
+static void camellia_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+	const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
+	const __be32 *src = (const __be32 *)in;
+	__be32 *dst = (__be32 *)out;
+
+	__be32 tmp[4];
+
+	memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
+
+	switch (cctx->key_length) {
+	case 16:
+		camellia_encrypt128(cctx->key_table, tmp);
+		break;
+	case 24:
+		/* fall through */
+	case 32:
+		camellia_encrypt256(cctx->key_table, tmp);
+		break;
+	default:
+		break;
+	}
+
+	memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
+}
+
+
+static void camellia_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+{
+	const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
+	const __be32 *src = (const __be32 *)in;
+	__be32 *dst = (__be32 *)out;
+
+	__be32 tmp[4];
+
+	memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
+
+	switch (cctx->key_length) {
+	case 16:
+		camellia_decrypt128(cctx->key_table, tmp);
+		break;
+	case 24:
+		/* fall through */
+	case 32:
+		camellia_decrypt256(cctx->key_table, tmp);
+		break;
+	default:
+		break;
+	}
+
+	memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
+}
+
+
+static struct crypto_alg camellia_alg = {
+	.cra_name		=	"camellia",
+	.cra_driver_name	=	"camellia-generic",
+	.cra_priority		=	100,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct camellia_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(camellia_alg.cra_list),
+	.cra_u			=	{
+		.cipher = {
+			.cia_min_keysize	=	CAMELLIA_MIN_KEY_SIZE,
+			.cia_max_keysize	=	CAMELLIA_MAX_KEY_SIZE,
+			.cia_setkey		=	camellia_set_key,
+			.cia_encrypt		=	camellia_encrypt,
+			.cia_decrypt		=	camellia_decrypt
+		}
+	}
+};
+
+static int __init camellia_init(void)
+{
+	return crypto_register_alg(&camellia_alg);
+}
+
+
+static void __exit camellia_fini(void)
+{
+	crypto_unregister_alg(&camellia_alg);
+}
+
+
+module_init(camellia_init);
+module_exit(camellia_fini);
+
+
+MODULE_DESCRIPTION("Camellia Cipher Algorithm");
+MODULE_LICENSE("GPL");

+ 5 - 4
crypto/cbc.c

@@ -243,6 +243,7 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_cipher *cipher;
 
 	switch (crypto_tfm_alg_blocksize(tfm)) {
 	case 8:
@@ -260,11 +261,11 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
 			ctx->xor = xor_quad;
 	}
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	return 0;
 }
 

+ 3 - 444
crypto/cipher.c

@@ -12,274 +12,13 @@
  * any later version.
  *
  */
-#include <linux/compiler.h>
+
 #include <linux/kernel.h>
 #include <linux/crypto.h>
 #include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
+#include <linux/scatterlist.h>
 #include <linux/string.h>
-#include <asm/scatterlist.h>
 #include "internal.h"
-#include "scatterwalk.h"
-
-struct cipher_alg_compat {
-	unsigned int cia_min_keysize;
-	unsigned int cia_max_keysize;
-	int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key,
-	                  unsigned int keylen);
-	void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-	void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-
-	unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes);
-	unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes);
-	unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes);
-	unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes);
-};
-
-static inline void xor_64(u8 *a, const u8 *b)
-{
-	((u32 *)a)[0] ^= ((u32 *)b)[0];
-	((u32 *)a)[1] ^= ((u32 *)b)[1];
-}
-
-static inline void xor_128(u8 *a, const u8 *b)
-{
-	((u32 *)a)[0] ^= ((u32 *)b)[0];
-	((u32 *)a)[1] ^= ((u32 *)b)[1];
-	((u32 *)a)[2] ^= ((u32 *)b)[2];
-	((u32 *)a)[3] ^= ((u32 *)b)[3];
-}
-
-static unsigned int crypt_slow(const struct cipher_desc *desc,
-			       struct scatter_walk *in,
-			       struct scatter_walk *out, unsigned int bsize)
-{
-	unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
-	u8 buffer[bsize * 2 + alignmask];
-	u8 *src = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
-	u8 *dst = src + bsize;
-
-	scatterwalk_copychunks(src, in, bsize, 0);
-	desc->prfn(desc, dst, src, bsize);
-	scatterwalk_copychunks(dst, out, bsize, 1);
-
-	return bsize;
-}
-
-static inline unsigned int crypt_fast(const struct cipher_desc *desc,
-				      struct scatter_walk *in,
-				      struct scatter_walk *out,
-				      unsigned int nbytes, u8 *tmp)
-{
-	u8 *src, *dst;
-	u8 *real_src, *real_dst;
-
-	real_src = scatterwalk_map(in, 0);
-	real_dst = scatterwalk_map(out, 1);
-
-	src = real_src;
-	dst = scatterwalk_samebuf(in, out) ? src : real_dst;
-
-	if (tmp) {
-		memcpy(tmp, src, nbytes);
-		src = tmp;
-		dst = tmp;
-	}
-
-	nbytes = desc->prfn(desc, dst, src, nbytes);
-
-	if (tmp)
-		memcpy(real_dst, tmp, nbytes);
-
-	scatterwalk_unmap(real_src, 0);
-	scatterwalk_unmap(real_dst, 1);
-
-	scatterwalk_advance(in, nbytes);
-	scatterwalk_advance(out, nbytes);
-
-	return nbytes;
-}
-
-/* 
- * Generic encrypt/decrypt wrapper for ciphers, handles operations across
- * multiple page boundaries by using temporary blocks.  In user context,
- * the kernel is given a chance to schedule us once per page.
- */
-static int crypt(const struct cipher_desc *desc,
-		 struct scatterlist *dst,
-		 struct scatterlist *src,
-		 unsigned int nbytes)
-{
-	struct scatter_walk walk_in, walk_out;
-	struct crypto_tfm *tfm = desc->tfm;
-	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
-	unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
-	unsigned long buffer = 0;
-
-	if (!nbytes)
-		return 0;
-
-	if (nbytes % bsize) {
-		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
-		return -EINVAL;
-	}
-
-	scatterwalk_start(&walk_in, src);
-	scatterwalk_start(&walk_out, dst);
-
-	for(;;) {
-		unsigned int n = nbytes;
-		u8 *tmp = NULL;
-
-		if (!scatterwalk_aligned(&walk_in, alignmask) ||
-		    !scatterwalk_aligned(&walk_out, alignmask)) {
-			if (!buffer) {
-				buffer = __get_free_page(GFP_ATOMIC);
-				if (!buffer)
-					n = 0;
-			}
-			tmp = (u8 *)buffer;
-		}
-
-		n = scatterwalk_clamp(&walk_in, n);
-		n = scatterwalk_clamp(&walk_out, n);
-
-		if (likely(n >= bsize))
-			n = crypt_fast(desc, &walk_in, &walk_out, n, tmp);
-		else
-			n = crypt_slow(desc, &walk_in, &walk_out, bsize);
-
-		nbytes -= n;
-
-		scatterwalk_done(&walk_in, 0, nbytes);
-		scatterwalk_done(&walk_out, 1, nbytes);
-
-		if (!nbytes)
-			break;
-
-		crypto_yield(tfm->crt_flags);
-	}
-
-	if (buffer)
-		free_page(buffer);
-
-	return 0;
-}
-
-static int crypt_iv_unaligned(struct cipher_desc *desc,
-			      struct scatterlist *dst,
-			      struct scatterlist *src,
-			      unsigned int nbytes)
-{
-	struct crypto_tfm *tfm = desc->tfm;
-	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
-	u8 *iv = desc->info;
-
-	if (unlikely(((unsigned long)iv & alignmask))) {
-		unsigned int ivsize = tfm->crt_cipher.cit_ivsize;
-		u8 buffer[ivsize + alignmask];
-		u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
-		int err;
-
-		desc->info = memcpy(tmp, iv, ivsize);
-		err = crypt(desc, dst, src, nbytes);
-		memcpy(iv, tmp, ivsize);
-
-		return err;
-	}
-
-	return crypt(desc, dst, src, nbytes);
-}
-
-static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes)
-{
-	struct crypto_tfm *tfm = desc->tfm;
-	void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
-	int bsize = crypto_tfm_alg_blocksize(tfm);
-
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
-	u8 *iv = desc->info;
-	unsigned int done = 0;
-
-	nbytes -= bsize;
-
-	do {
-		xor(iv, src);
-		fn(tfm, dst, iv);
-		memcpy(iv, dst, bsize);
-
-		src += bsize;
-		dst += bsize;
-	} while ((done += bsize) <= nbytes);
-
-	return done;
-}
-
-static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes)
-{
-	struct crypto_tfm *tfm = desc->tfm;
-	void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
-	int bsize = crypto_tfm_alg_blocksize(tfm);
-	unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
-
-	u8 stack[src == dst ? bsize + alignmask : 0];
-	u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
-	u8 **dst_p = src == dst ? &buf : &dst;
-
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
-	u8 *iv = desc->info;
-	unsigned int done = 0;
-
-	nbytes -= bsize;
-
-	do {
-		u8 *tmp_dst = *dst_p;
-
-		fn(tfm, tmp_dst, src);
-		xor(tmp_dst, iv);
-		memcpy(iv, src, bsize);
-		if (tmp_dst != dst)
-			memcpy(dst, tmp_dst, bsize);
-
-		src += bsize;
-		dst += bsize;
-	} while ((done += bsize) <= nbytes);
-
-	return done;
-}
-
-static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst,
-				const u8 *src, unsigned int nbytes)
-{
-	struct crypto_tfm *tfm = desc->tfm;
-	int bsize = crypto_tfm_alg_blocksize(tfm);
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
-	unsigned int done = 0;
-
-	nbytes -= bsize;
-
-	do {
-		fn(tfm, dst, src);
-
-		src += bsize;
-		dst += bsize;
-	} while ((done += bsize) <= nbytes);
-
-	return done;
-}
 
 static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
 {
@@ -293,122 +32,6 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
 		return cia->cia_setkey(tfm, key, keylen);
 }
 
-static int ecb_encrypt(struct crypto_tfm *tfm,
-		       struct scatterlist *dst,
-                       struct scatterlist *src, unsigned int nbytes)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_encrypt;
-	desc.prfn = cipher->cia_encrypt_ecb ?: ecb_process;
-
-	return crypt(&desc, dst, src, nbytes);
-}
-
-static int ecb_decrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_decrypt;
-	desc.prfn = cipher->cia_decrypt_ecb ?: ecb_process;
-
-	return crypt(&desc, dst, src, nbytes);
-}
-
-static int cbc_encrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_encrypt;
-	desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
-	desc.info = tfm->crt_cipher.cit_iv;
-
-	return crypt(&desc, dst, src, nbytes);
-}
-
-static int cbc_encrypt_iv(struct crypto_tfm *tfm,
-                          struct scatterlist *dst,
-                          struct scatterlist *src,
-                          unsigned int nbytes, u8 *iv)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_encrypt;
-	desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
-	desc.info = iv;
-
-	return crypt_iv_unaligned(&desc, dst, src, nbytes);
-}
-
-static int cbc_decrypt(struct crypto_tfm *tfm,
-                       struct scatterlist *dst,
-                       struct scatterlist *src,
-		       unsigned int nbytes)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_decrypt;
-	desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
-	desc.info = tfm->crt_cipher.cit_iv;
-
-	return crypt(&desc, dst, src, nbytes);
-}
-
-static int cbc_decrypt_iv(struct crypto_tfm *tfm,
-                          struct scatterlist *dst,
-                          struct scatterlist *src,
-                          unsigned int nbytes, u8 *iv)
-{
-	struct cipher_desc desc;
-	struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
-
-	desc.tfm = tfm;
-	desc.crfn = cipher->cia_decrypt;
-	desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
-	desc.info = iv;
-
-	return crypt_iv_unaligned(&desc, dst, src, nbytes);
-}
-
-static int nocrypt(struct crypto_tfm *tfm,
-                   struct scatterlist *dst,
-                   struct scatterlist *src,
-		   unsigned int nbytes)
-{
-	return -ENOSYS;
-}
-
-static int nocrypt_iv(struct crypto_tfm *tfm,
-                      struct scatterlist *dst,
-                      struct scatterlist *src,
-                      unsigned int nbytes, u8 *iv)
-{
-	return -ENOSYS;
-}
-
-int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	u32 mode = flags & CRYPTO_TFM_MODE_MASK;
-	tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
-	return 0;
-}
-
 static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
 					      const u8 *),
 				   struct crypto_tfm *tfm,
@@ -454,7 +77,6 @@ static void cipher_decrypt_unaligned(struct crypto_tfm *tfm,
 
 int crypto_init_cipher_ops(struct crypto_tfm *tfm)
 {
-	int ret = 0;
 	struct cipher_tfm *ops = &tfm->crt_cipher;
 	struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
 
@@ -464,70 +86,7 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
 	ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ?
 		cipher_decrypt_unaligned : cipher->cia_decrypt;
 
-	switch (tfm->crt_cipher.cit_mode) {
-	case CRYPTO_TFM_MODE_ECB:
-		ops->cit_encrypt = ecb_encrypt;
-		ops->cit_decrypt = ecb_decrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
-		break;
-		
-	case CRYPTO_TFM_MODE_CBC:
-		ops->cit_encrypt = cbc_encrypt;
-		ops->cit_decrypt = cbc_decrypt;
-		ops->cit_encrypt_iv = cbc_encrypt_iv;
-		ops->cit_decrypt_iv = cbc_decrypt_iv;
-		break;
-		
-	case CRYPTO_TFM_MODE_CFB:
-		ops->cit_encrypt = nocrypt;
-		ops->cit_decrypt = nocrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
-		break;
-	
-	case CRYPTO_TFM_MODE_CTR:
-		ops->cit_encrypt = nocrypt;
-		ops->cit_decrypt = nocrypt;
-		ops->cit_encrypt_iv = nocrypt_iv;
-		ops->cit_decrypt_iv = nocrypt_iv;
-		break;
-
-	default:
-		BUG();
-	}
-	
-	if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
-		unsigned long align;
-		unsigned long addr;
-	    	
-	    	switch (crypto_tfm_alg_blocksize(tfm)) {
-	    	case 8:
-	    		ops->cit_xor_block = xor_64;
-	    		break;
-	    		
-	    	case 16:
-	    		ops->cit_xor_block = xor_128;
-	    		break;
-	    		
-	    	default:
-	    		printk(KERN_WARNING "%s: block size %u not supported\n",
-	    		       crypto_tfm_alg_name(tfm),
-	    		       crypto_tfm_alg_blocksize(tfm));
-	    		ret = -EINVAL;
-	    		goto out;
-	    	}
-	    	
-		ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
-		align = crypto_tfm_alg_alignmask(tfm) + 1;
-		addr = (unsigned long)crypto_tfm_ctx(tfm);
-		addr = ALIGN(addr, align);
-		addr += ALIGN(tfm->__crt_alg->cra_ctxsize, align);
-		ops->cit_iv = (void *)addr;
-	}
-
-out:	
-	return ret;
+	return 0;
 }
 
 void crypto_exit_cipher_ops(struct crypto_tfm *tfm)

+ 0 - 5
crypto/compress.c

@@ -34,11 +34,6 @@ static int crypto_decompress(struct crypto_tfm *tfm,
 	                                                   dlen);
 }
 
-int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	return flags ? -EINVAL : 0;
-}
-
 int crypto_init_compress_ops(struct crypto_tfm *tfm)
 {
 	struct compress_tfm *ops = &tfm->crt_compress;

+ 16 - 8
crypto/digest.c

@@ -14,7 +14,9 @@
 
 #include <linux/mm.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/highmem.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
 
@@ -29,8 +31,8 @@ static int init(struct hash_desc *desc)
 	return 0;
 }
 
-static int update(struct hash_desc *desc,
-		  struct scatterlist *sg, unsigned int nbytes)
+static int update2(struct hash_desc *desc,
+		   struct scatterlist *sg, unsigned int nbytes)
 {
 	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
 	unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
@@ -81,6 +83,14 @@ static int update(struct hash_desc *desc,
 	return 0;
 }
 
+static int update(struct hash_desc *desc,
+		  struct scatterlist *sg, unsigned int nbytes)
+{
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+	return update2(desc, sg, nbytes);
+}
+
 static int final(struct hash_desc *desc, u8 *out)
 {
 	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
@@ -118,16 +128,14 @@ static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen)
 static int digest(struct hash_desc *desc,
 		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
 {
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
 	init(desc);
-	update(desc, sg, nbytes);
+	update2(desc, sg, nbytes);
 	return final(desc, out);
 }
 
-int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
-{
-	return flags ? -EINVAL : 0;
-}
-
 int crypto_init_digest_ops(struct crypto_tfm *tfm)
 {
 	struct hash_tfm *ops = &tfm->crt_hash;

+ 5 - 4
crypto/ecb.c

@@ -99,12 +99,13 @@ static int crypto_ecb_init_tfm(struct crypto_tfm *tfm)
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_cipher *cipher;
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	return 0;
 }
 

+ 423 - 0
crypto/fcrypt.c

@@ -0,0 +1,423 @@
+/* FCrypt encryption algorithm
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Based on code:
+ *
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+
+#define ROUNDS 16
+
+struct fcrypt_ctx {
+	u32 sched[ROUNDS];
+};
+
+/* Rotate right two 32 bit numbers as a 56 bit number */
+#define ror56(hi, lo, n)					\
+do {								\
+	u32 t = lo & ((1 << n) - 1);				\
+	lo = (lo >> n) | ((hi & ((1 << n) - 1)) << (32 - n));	\
+	hi = (hi >> n) | (t << (24-n));				\
+} while(0)
+
+/* Rotate right one 64 bit number as a 56 bit number */
+#define ror56_64(k, n)						\
+do {								\
+	k = (k >> n) | ((k & ((1 << n) - 1)) << (56 - n));	\
+} while(0)
+
+/*
+ * Sboxes for Feistel network derived from
+ * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
+ */
+#undef Z
+#define Z(x) __constant_be32_to_cpu(x << 3)
+static const u32 sbox0[256] = {
+	Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11),
+	Z(0xcd), Z(0x86), Z(0x86), Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06),
+	Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), Z(0x28), Z(0x60),
+	Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3),
+	Z(0xd2), Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a),
+	Z(0x35), Z(0xac), Z(0xaa), Z(0x5f), Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53),
+	Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32), Z(0x10),
+	Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd),
+	Z(0x3b), Z(0x95), Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80),
+	Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f), Z(0x26), Z(0x76), Z(0x15),
+	Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7),
+	Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24),
+	Z(0x0b), Z(0x8a), Z(0x83), Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8),
+	Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64), Z(0xf0), Z(0x51),
+	Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef),
+	Z(0x10), Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44),
+	Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b), Z(0xae), Z(0xd5), Z(0xad), Z(0x1d),
+	Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2), Z(0xb7),
+	Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44),
+	Z(0xb6), Z(0x69), Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0),
+	Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f), Z(0x36), Z(0xba), Z(0x71),
+	Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6),
+	Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95),
+	Z(0x22), Z(0x99), Z(0xfd), Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1),
+	Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70), Z(0xff), Z(0xc6),
+	Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5),
+	Z(0x36), Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6),
+	Z(0x93), Z(0xc4), Z(0xaa), Z(0x26), Z(0x49), Z(0xe0), Z(0x21), Z(0x64),
+	Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9), Z(0xd1),
+	Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03),
+	Z(0xe4), Z(0xb0), Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39),
+	Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c), Z(0x0d), Z(0x42), Z(0x2e)
+};
+
+#undef Z
+#define Z(x) __constant_be32_to_cpu((x << 27) | (x >> 5))
+static const u32 sbox1[256] = {
+	Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e),
+	Z(0x67), Z(0x6c), Z(0xa1), Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85),
+	Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), Z(0xf2), Z(0x89),
+	Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39),
+	Z(0x31), Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6),
+	Z(0x23), Z(0x83), Z(0x98), Z(0x7d), Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99),
+	Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f), Z(0xad),
+	Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6),
+	Z(0xb8), Z(0xa1), Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b),
+	Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23), Z(0x17), Z(0x04), Z(0xfa),
+	Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e),
+	Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc),
+	Z(0xe2), Z(0xaf), Z(0x45), Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd),
+	Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18), Z(0x60), Z(0x3d),
+	Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b),
+	Z(0x06), Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17),
+	Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1), Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5),
+	Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28), Z(0x0a),
+	Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a),
+	Z(0x31), Z(0xf7), Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5),
+	Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57), Z(0x25), Z(0xbe), Z(0x89),
+	Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52),
+	Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8),
+	Z(0x69), Z(0x10), Z(0x9d), Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30),
+	Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19), Z(0xbd), Z(0x45),
+	Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96),
+	Z(0xef), Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad),
+	Z(0x80), Z(0x48), Z(0x81), Z(0xb7), Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7),
+	Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57), Z(0xc1),
+	Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78),
+	Z(0x16), Z(0x06), Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4),
+	Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96), Z(0x91), Z(0x82), Z(0x80)
+};
+
+#undef Z
+#define Z(x) __constant_be32_to_cpu(x << 11)
+static const u32 sbox2[256] = {
+	Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86),
+	Z(0xd1), Z(0xec), Z(0x50), Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d),
+	Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), Z(0xc5), Z(0x5d),
+	Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24),
+	Z(0xc8), Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9),
+	Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9), Z(0x45), Z(0x20), Z(0x1b), Z(0xce),
+	Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3), Z(0xa9),
+	Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68),
+	Z(0x84), Z(0xbc), Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6),
+	Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95), Z(0x02), Z(0xc0), Z(0xd0),
+	Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17),
+	Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d),
+	Z(0x6d), Z(0x1c), Z(0x6c), Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e),
+	Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12), Z(0x19), Z(0x34),
+	Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae),
+	Z(0x2a), Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc),
+	Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b), Z(0xb1), Z(0x85), Z(0x59), Z(0x80),
+	Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48), Z(0x40),
+	Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e),
+	Z(0xb7), Z(0x5e), Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15),
+	Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9), Z(0xc7), Z(0x40), Z(0x45),
+	Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99),
+	Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f),
+	Z(0xdc), Z(0xff), Z(0xfd), Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a),
+	Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e), Z(0x3d), Z(0xfd),
+	Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f),
+	Z(0x56), Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5),
+	Z(0xf3), Z(0x8e), Z(0xde), Z(0xae), Z(0x37), Z(0x49), Z(0xb7), Z(0xfa),
+	Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15), Z(0xd1),
+	Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59),
+	Z(0x56), Z(0x68), Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f),
+	Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76), Z(0xb4), Z(0x10), Z(0x86)
+};
+
+#undef Z
+#define Z(x) __constant_be32_to_cpu(x << 19)
+static const u32 sbox3[256] = {
+	Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2),
+	Z(0xb5), Z(0xb7), Z(0x42), Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12),
+	Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), Z(0x6d), Z(0x57),
+	Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b),
+	Z(0x53), Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66),
+	Z(0xa1), Z(0x01), Z(0xa5), Z(0x41), Z(0x97), Z(0x41), Z(0x31), Z(0x82),
+	Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10), Z(0xcc),
+	Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16),
+	Z(0x47), Z(0xf6), Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a),
+	Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01), Z(0x54), Z(0x70), Z(0xa4),
+	Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23),
+	Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2),
+	Z(0x2a), Z(0x41), Z(0xb2), Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d),
+	Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc), Z(0x60), Z(0x65),
+	Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87),
+	Z(0x96), Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4),
+	Z(0x5a), Z(0x83), Z(0xbf), Z(0x92), Z(0x1b), Z(0x94), Z(0x00), Z(0x42),
+	Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76), Z(0x5f),
+	Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95),
+	Z(0x17), Z(0xe4), Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85),
+	Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b), Z(0x66), Z(0xa1), Z(0x34),
+	Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05),
+	Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a),
+	Z(0x19), Z(0xf1), Z(0xa1), Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0),
+	Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a), Z(0x2d), Z(0x20),
+	Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f),
+	Z(0x47), Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79),
+	Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd), Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3),
+	Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0), Z(0x11),
+	Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f),
+	Z(0xd8), Z(0xe1), Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9),
+	Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba), Z(0xfc), Z(0x0e), Z(0x25)
+};
+
+/*
+ * This is a 16 round Feistel network with permutation F_ENCRYPT
+ */
+#define F_ENCRYPT(R, L, sched)						\
+do {									\
+	union lc4 { u32 l; u8 c[4]; } u;				\
+	u.l = sched ^ R;						\
+	L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; \
+} while(0)
+
+/*
+ * encryptor
+ */
+static void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct {
+		u32 l, r;
+	} X;
+
+	memcpy(&X, src, sizeof(X));
+
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
+
+	memcpy(dst, &X, sizeof(X));
+}
+
+/*
+ * decryptor
+ */
+static void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct {
+		u32 l, r;
+	} X;
+
+	memcpy(&X, src, sizeof(X));
+
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
+	F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
+	F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
+
+	memcpy(dst, &X, sizeof(X));
+}
+
+/*
+ * Generate a key schedule from key, the least significant bit in each key byte
+ * is parity and shall be ignored. This leaves 56 significant bits in the key
+ * to scatter over the 16 key schedules. For each schedule extract the low
+ * order 32 bits and use as schedule, then rotate right by 11 bits.
+ */
+static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
+
+#if BITS_PER_LONG == 64  /* the 64-bit version can also be used for 32-bit
+			  * kernels - it seems to be faster but the code is
+			  * larger */
+
+	u64 k;	/* k holds all 56 non-parity bits */
+
+	/* discard the parity bits */
+	k = (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key++) >> 1;
+	k <<= 7;
+	k |= (*key) >> 1;
+
+	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
+	ctx->sched[0x0] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x1] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x2] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x3] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x4] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x5] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x6] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x7] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x8] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0x9] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xa] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xb] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xc] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xd] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xe] = be32_to_cpu(k); ror56_64(k, 11);
+	ctx->sched[0xf] = be32_to_cpu(k);
+
+	return 0;
+#else
+	u32 hi, lo;		/* hi is upper 24 bits and lo lower 32, total 56 */
+
+	/* discard the parity bits */
+	lo = (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	hi = lo >> 4;
+	lo &= 0xf;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key++) >> 1;
+	lo <<= 7;
+	lo |= (*key) >> 1;
+
+	/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
+	ctx->sched[0x0] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x1] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x2] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x3] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x4] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x5] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x6] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x7] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x8] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0x9] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xa] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xb] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xc] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xd] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xe] = be32_to_cpu(lo); ror56(hi, lo, 11);
+	ctx->sched[0xf] = be32_to_cpu(lo);
+	return 0;
+#endif
+}
+
+static struct crypto_alg fcrypt_alg = {
+	.cra_name		=	"fcrypt",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	8,
+	.cra_ctxsize		=	sizeof(struct fcrypt_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_alignmask		=	3,
+	.cra_list		=	LIST_HEAD_INIT(fcrypt_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	8,
+	.cia_max_keysize	=	8,
+	.cia_setkey		=	fcrypt_setkey,
+	.cia_encrypt		=	fcrypt_encrypt,
+	.cia_decrypt		=	fcrypt_decrypt } }
+};
+
+static int __init init(void)
+{
+	return crypto_register_alg(&fcrypt_alg);
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&fcrypt_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
+MODULE_AUTHOR("David Howells <dhowells@redhat.com>");

+ 3 - 2
crypto/hash.c

@@ -16,12 +16,13 @@
 
 #include "internal.h"
 
-static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg)
+static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg, u32 type,
+					u32 mask)
 {
 	return alg->cra_ctxsize;
 }
 
-static int crypto_init_hash_ops(struct crypto_tfm *tfm)
+static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 {
 	struct hash_tfm *crt = &tfm->crt_hash;
 	struct hash_alg *alg = &tfm->__crt_alg->cra_hash;

+ 5 - 4
crypto/hmac.c

@@ -172,15 +172,16 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
 
 static int hmac_init_tfm(struct crypto_tfm *tfm)
 {
+	struct crypto_hash *hash;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	hash = crypto_spawn_hash(spawn);
+	if (IS_ERR(hash))
+		return PTR_ERR(hash);
 
-	ctx->child = crypto_hash_cast(tfm);
+	ctx->child = hash;
 	return 0;
 }
 

+ 6 - 21
crypto/internal.h

@@ -83,8 +83,7 @@ static inline void crypto_exit_proc(void)
 { }
 #endif
 
-static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
-						 int flags)
+static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg)
 {
 	unsigned int len = alg->cra_ctxsize;
 
@@ -96,23 +95,12 @@ static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
 	return len;
 }
 
-static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg,
-						 int flags)
+static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg)
 {
-	unsigned int len = alg->cra_ctxsize;
-	
-	switch (flags & CRYPTO_TFM_MODE_MASK) {
-	case CRYPTO_TFM_MODE_CBC:
-		len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
-		len += alg->cra_blocksize;
-		break;
-	}
-
-	return len;
+	return alg->cra_ctxsize;
 }
 
-static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg,
-						   int flags)
+static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg)
 {
 	return alg->cra_ctxsize;
 }
@@ -121,10 +109,6 @@ struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
 struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask);
 struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
 
-int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags);
-int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags);
-int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
-
 int crypto_init_digest_ops(struct crypto_tfm *tfm);
 int crypto_init_cipher_ops(struct crypto_tfm *tfm);
 int crypto_init_compress_ops(struct crypto_tfm *tfm);
@@ -136,7 +120,8 @@ void crypto_exit_compress_ops(struct crypto_tfm *tfm);
 void crypto_larval_error(const char *name, u32 type, u32 mask);
 
 void crypto_shoot_alg(struct crypto_alg *alg);
-struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags);
+struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
+				      u32 mask);
 
 int crypto_register_instance(struct crypto_template *tmpl,
 			     struct crypto_instance *inst);

+ 6 - 5
crypto/lrw.c

@@ -201,21 +201,22 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
 
 static int init_tfm(struct crypto_tfm *tfm)
 {
+	struct crypto_cipher *cipher;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct priv *ctx = crypto_tfm_ctx(tfm);
 	u32 *flags = &tfm->crt_flags;
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
 
-	if (crypto_tfm_alg_blocksize(tfm) != 16) {
+	if (crypto_cipher_blocksize(cipher) != 16) {
 		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
 		return -EINVAL;
 	}
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	return 0;
 }
 

+ 349 - 0
crypto/pcbc.c

@@ -0,0 +1,349 @@
+/*
+ * PCBC: Propagating Cipher Block Chaining mode
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * Derived from cbc.c
+ * - Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+struct crypto_pcbc_ctx {
+	struct crypto_cipher *child;
+	void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
+};
+
+static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
+			      unsigned int keylen)
+{
+	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(parent);
+	struct crypto_cipher *child = ctx->child;
+	int err;
+
+	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
+				CRYPTO_TFM_REQ_MASK);
+	err = crypto_cipher_setkey(child, key, keylen);
+	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
+			     CRYPTO_TFM_RES_MASK);
+	return err;
+}
+
+static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
+				       struct blkcipher_walk *walk,
+				       struct crypto_cipher *tfm,
+				       void (*xor)(u8 *, const u8 *,
+						   unsigned int))
+{
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+		crypto_cipher_alg(tfm)->cia_encrypt;
+	int bsize = crypto_cipher_blocksize(tfm);
+	unsigned int nbytes = walk->nbytes;
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	u8 *iv = walk->iv;
+
+	do {
+		xor(iv, src, bsize);
+		fn(crypto_cipher_tfm(tfm), dst, iv);
+		memcpy(iv, dst, bsize);
+		xor(iv, src, bsize);
+
+		src += bsize;
+		dst += bsize;
+	} while ((nbytes -= bsize) >= bsize);
+
+	return nbytes;
+}
+
+static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
+				       struct blkcipher_walk *walk,
+				       struct crypto_cipher *tfm,
+				       void (*xor)(u8 *, const u8 *,
+						   unsigned int))
+{
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+		crypto_cipher_alg(tfm)->cia_encrypt;
+	int bsize = crypto_cipher_blocksize(tfm);
+	unsigned int nbytes = walk->nbytes;
+	u8 *src = walk->src.virt.addr;
+	u8 *iv = walk->iv;
+	u8 tmpbuf[bsize];
+
+	do {
+		memcpy(tmpbuf, src, bsize);
+		xor(iv, tmpbuf, bsize);
+		fn(crypto_cipher_tfm(tfm), src, iv);
+		memcpy(iv, src, bsize);
+		xor(iv, tmpbuf, bsize);
+
+		src += bsize;
+	} while ((nbytes -= bsize) >= bsize);
+
+	memcpy(walk->iv, iv, bsize);
+
+	return nbytes;
+}
+
+static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
+			       struct scatterlist *dst, struct scatterlist *src,
+			       unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	struct crypto_blkcipher *tfm = desc->tfm;
+	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+	struct crypto_cipher *child = ctx->child;
+	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		if (walk.src.virt.addr == walk.dst.virt.addr)
+			nbytes = crypto_pcbc_encrypt_inplace(desc, &walk, child,
+							     xor);
+		else
+			nbytes = crypto_pcbc_encrypt_segment(desc, &walk, child,
+							     xor);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
+				       struct blkcipher_walk *walk,
+				       struct crypto_cipher *tfm,
+				       void (*xor)(u8 *, const u8 *,
+						   unsigned int))
+{
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+		crypto_cipher_alg(tfm)->cia_decrypt;
+	int bsize = crypto_cipher_blocksize(tfm);
+	unsigned int nbytes = walk->nbytes;
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	u8 *iv = walk->iv;
+
+	do {
+		fn(crypto_cipher_tfm(tfm), dst, src);
+		xor(dst, iv, bsize);
+		memcpy(iv, src, bsize);
+		xor(iv, dst, bsize);
+
+		src += bsize;
+		dst += bsize;
+	} while ((nbytes -= bsize) >= bsize);
+
+	memcpy(walk->iv, iv, bsize);
+
+	return nbytes;
+}
+
+static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
+				       struct blkcipher_walk *walk,
+				       struct crypto_cipher *tfm,
+				       void (*xor)(u8 *, const u8 *,
+						   unsigned int))
+{
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+		crypto_cipher_alg(tfm)->cia_decrypt;
+	int bsize = crypto_cipher_blocksize(tfm);
+	unsigned int nbytes = walk->nbytes;
+	u8 *src = walk->src.virt.addr;
+	u8 *iv = walk->iv;
+	u8 tmpbuf[bsize];
+
+	do {
+		memcpy(tmpbuf, src, bsize);
+		fn(crypto_cipher_tfm(tfm), src, src);
+		xor(src, iv, bsize);
+		memcpy(iv, tmpbuf, bsize);
+		xor(iv, src, bsize);
+
+		src += bsize;
+	} while ((nbytes -= bsize) >= bsize);
+
+	memcpy(walk->iv, iv, bsize);
+
+	return nbytes;
+}
+
+static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
+			       struct scatterlist *dst, struct scatterlist *src,
+			       unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	struct crypto_blkcipher *tfm = desc->tfm;
+	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+	struct crypto_cipher *child = ctx->child;
+	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		if (walk.src.virt.addr == walk.dst.virt.addr)
+			nbytes = crypto_pcbc_decrypt_inplace(desc, &walk, child,
+							     xor);
+		else
+			nbytes = crypto_pcbc_decrypt_segment(desc, &walk, child,
+							     xor);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static void xor_byte(u8 *a, const u8 *b, unsigned int bs)
+{
+	do {
+		*a++ ^= *b++;
+	} while (--bs);
+}
+
+static void xor_quad(u8 *dst, const u8 *src, unsigned int bs)
+{
+	u32 *a = (u32 *)dst;
+	u32 *b = (u32 *)src;
+
+	do {
+		*a++ ^= *b++;
+	} while ((bs -= 4));
+}
+
+static void xor_64(u8 *a, const u8 *b, unsigned int bs)
+{
+	((u32 *)a)[0] ^= ((u32 *)b)[0];
+	((u32 *)a)[1] ^= ((u32 *)b)[1];
+}
+
+static void xor_128(u8 *a, const u8 *b, unsigned int bs)
+{
+	((u32 *)a)[0] ^= ((u32 *)b)[0];
+	((u32 *)a)[1] ^= ((u32 *)b)[1];
+	((u32 *)a)[2] ^= ((u32 *)b)[2];
+	((u32 *)a)[3] ^= ((u32 *)b)[3];
+}
+
+static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_cipher *cipher;
+
+	switch (crypto_tfm_alg_blocksize(tfm)) {
+	case 8:
+		ctx->xor = xor_64;
+		break;
+
+	case 16:
+		ctx->xor = xor_128;
+		break;
+
+	default:
+		if (crypto_tfm_alg_blocksize(tfm) % 4)
+			ctx->xor = xor_byte;
+		else
+			ctx->xor = xor_quad;
+	}
+
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
+
+	ctx->child = cipher;
+	return 0;
+}
+
+static void crypto_pcbc_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	crypto_free_cipher(ctx->child);
+}
+
+static struct crypto_instance *crypto_pcbc_alloc(void *param, unsigned int len)
+{
+	struct crypto_instance *inst;
+	struct crypto_alg *alg;
+
+	alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
+				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
+	if (IS_ERR(alg))
+		return ERR_PTR(PTR_ERR(alg));
+
+	inst = crypto_alloc_instance("pcbc", alg);
+	if (IS_ERR(inst))
+		goto out_put_alg;
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+	inst->alg.cra_priority = alg->cra_priority;
+	inst->alg.cra_blocksize = alg->cra_blocksize;
+	inst->alg.cra_alignmask = alg->cra_alignmask;
+	inst->alg.cra_type = &crypto_blkcipher_type;
+
+	if (!(alg->cra_blocksize % 4))
+		inst->alg.cra_alignmask |= 3;
+	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+
+	inst->alg.cra_ctxsize = sizeof(struct crypto_pcbc_ctx);
+
+	inst->alg.cra_init = crypto_pcbc_init_tfm;
+	inst->alg.cra_exit = crypto_pcbc_exit_tfm;
+
+	inst->alg.cra_blkcipher.setkey = crypto_pcbc_setkey;
+	inst->alg.cra_blkcipher.encrypt = crypto_pcbc_encrypt;
+	inst->alg.cra_blkcipher.decrypt = crypto_pcbc_decrypt;
+
+out_put_alg:
+	crypto_mod_put(alg);
+	return inst;
+}
+
+static void crypto_pcbc_free(struct crypto_instance *inst)
+{
+	crypto_drop_spawn(crypto_instance_ctx(inst));
+	kfree(inst);
+}
+
+static struct crypto_template crypto_pcbc_tmpl = {
+	.name = "pcbc",
+	.alloc = crypto_pcbc_alloc,
+	.free = crypto_pcbc_free,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_pcbc_module_init(void)
+{
+	return crypto_register_template(&crypto_pcbc_tmpl);
+}
+
+static void __exit crypto_pcbc_module_exit(void)
+{
+	crypto_unregister_template(&crypto_pcbc_tmpl);
+}
+
+module_init(crypto_pcbc_module_init);
+module_exit(crypto_pcbc_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PCBC block cipher algorithm");

+ 71 - 2
crypto/tcrypt.c

@@ -12,6 +12,7 @@
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
+ * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
  * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
  * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
  *
@@ -71,7 +72,8 @@ static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
 	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
-	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", NULL
+	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
+	"camellia", NULL
 };
 
 static void hexdump(unsigned char *buf, unsigned int len)
@@ -765,7 +767,7 @@ static void test_deflate(void)
 	memcpy(tvmem, deflate_comp_tv_template, tsize);
 	tv = (void *)tvmem;
 
-	tfm = crypto_alloc_tfm("deflate", 0);
+	tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC);
 	if (tfm == NULL) {
 		printk("failed to load transform for deflate\n");
 		return;
@@ -964,6 +966,26 @@ static void do_test(void)
 		test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template,
 			    XETA_DEC_TEST_VECTORS);
 
+		//FCrypt
+		test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template,
+			    FCRYPT_ENC_TEST_VECTORS);
+		test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template,
+			    FCRYPT_DEC_TEST_VECTORS);
+
+		//CAMELLIA
+		test_cipher("ecb(camellia)", ENCRYPT,
+			    camellia_enc_tv_template,
+			    CAMELLIA_ENC_TEST_VECTORS);
+		test_cipher("ecb(camellia)", DECRYPT,
+			    camellia_dec_tv_template,
+			    CAMELLIA_DEC_TEST_VECTORS);
+		test_cipher("cbc(camellia)", ENCRYPT,
+			    camellia_cbc_enc_tv_template,
+			    CAMELLIA_CBC_ENC_TEST_VECTORS);
+		test_cipher("cbc(camellia)", DECRYPT,
+			    camellia_cbc_dec_tv_template,
+			    CAMELLIA_CBC_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
@@ -980,6 +1002,10 @@ static void do_test(void)
 			  HMAC_SHA1_TEST_VECTORS);
 		test_hash("hmac(sha256)", hmac_sha256_tv_template,
 			  HMAC_SHA256_TEST_VECTORS);
+		test_hash("hmac(sha384)", hmac_sha384_tv_template,
+			  HMAC_SHA384_TEST_VECTORS);
+		test_hash("hmac(sha512)", hmac_sha512_tv_template,
+			  HMAC_SHA512_TEST_VECTORS);
 
 		test_hash("xcbc(aes)", aes_xcbc128_tv_template,
 			  XCBC_AES_TEST_VECTORS);
@@ -1177,6 +1203,28 @@ static void do_test(void)
 			    XETA_DEC_TEST_VECTORS);
 		break;
 
+	case 31:
+		test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template,
+			    FCRYPT_ENC_TEST_VECTORS);
+		test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template,
+			    FCRYPT_DEC_TEST_VECTORS);
+		break;
+
+	case 32:
+		test_cipher("ecb(camellia)", ENCRYPT,
+			    camellia_enc_tv_template,
+			    CAMELLIA_ENC_TEST_VECTORS);
+		test_cipher("ecb(camellia)", DECRYPT,
+			    camellia_dec_tv_template,
+			    CAMELLIA_DEC_TEST_VECTORS);
+		test_cipher("cbc(camellia)", ENCRYPT,
+			    camellia_cbc_enc_tv_template,
+			    CAMELLIA_CBC_ENC_TEST_VECTORS);
+		test_cipher("cbc(camellia)", DECRYPT,
+			    camellia_cbc_dec_tv_template,
+			    CAMELLIA_CBC_DEC_TEST_VECTORS);
+		break;
+
 	case 100:
 		test_hash("hmac(md5)", hmac_md5_tv_template,
 			  HMAC_MD5_TEST_VECTORS);
@@ -1192,6 +1240,16 @@ static void do_test(void)
 			  HMAC_SHA256_TEST_VECTORS);
 		break;
 
+	case 103:
+		test_hash("hmac(sha384)", hmac_sha384_tv_template,
+			  HMAC_SHA384_TEST_VECTORS);
+		break;
+
+	case 104:
+		test_hash("hmac(sha512)", hmac_sha512_tv_template,
+			  HMAC_SHA512_TEST_VECTORS);
+		break;
+
 
 	case 200:
 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
@@ -1260,6 +1318,17 @@ static void do_test(void)
 				  des_speed_template);
 		break;
 
+	case 205:
+		test_cipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
+				camellia_speed_template);
+		test_cipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
+				camellia_speed_template);
+		test_cipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
+				camellia_speed_template);
+		test_cipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
+				camellia_speed_template);
+		break;
+
 	case 300:
 		/* fall through */
 

+ 537 - 1
crypto/tcrypt.h

@@ -12,6 +12,7 @@
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
+ * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
  * 2004-08-09 Cipher speed tests by Reyk Floeter <reyk@vantronix.net>
  * 2003-09-14 Changes by Kartikey Mahendra Bhatt
  *
@@ -27,7 +28,7 @@
 
 struct hash_testvec {
 	/* only used with keyed hash algorithms */
-	char key[128] __attribute__ ((__aligned__(4)));
+	char key[132] __attribute__ ((__aligned__(4)));
 	char plaintext[240];
 	char digest[MAX_DIGEST_SIZE];
 	unsigned char tap[MAX_TAP];
@@ -1001,6 +1002,248 @@ static struct hash_testvec aes_xcbc128_tv_template[] = {
 	}
 };
 
+/*
+ * SHA384 HMAC test vectors from RFC4231
+ */
+
+#define HMAC_SHA384_TEST_VECTORS	4
+
+static struct hash_testvec hmac_sha384_tv_template[] = {
+	{
+		.key	= { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			    0x0b, 0x0b, 0x0b, 0x0b }, // (20 bytes)
+		.ksize	= 20,
+		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }, // ("Hi There")
+		.psize	= 8,
+		.digest	= { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62,
+			    0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
+			    0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
+			    0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
+			    0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f,
+			    0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 },
+	}, {
+		.key	= { 0x4a, 0x65, 0x66, 0x65 }, // ("Jefe")
+		.ksize	= 4,
+		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+			       0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, // ("what do ya want ")
+			       0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+			       0x69, 0x6e, 0x67, 0x3f }, // ("for nothing?")
+		.psize	= 28,
+		.digest	= { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31,
+			    0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
+			    0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
+			    0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
+			    0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7,
+			    0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 },
+		.np	= 4,
+		.tap	= { 7, 7, 7, 7 }
+	}, {
+		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa }, // (131 bytes)
+		.ksize	= 131,
+		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+			       0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, // ("Test Using Large")
+			       0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+			       0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, // ("r Than Block-Siz")
+			       0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+			       0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, // ("e Key - Hash Key")
+			       0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }, // (" First")
+		.psize	= 54,
+		.digest	= { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90,
+			    0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
+			    0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
+			    0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
+			    0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82,
+			    0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 },
+	}, {
+		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa }, // (131 bytes)
+		.ksize	= 131,
+		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+			       0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, // ("This is a test u")
+			       0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+			       0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, // ("sing a larger th")
+			       0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+			       0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, // ("an block-size ke")
+			       0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+			       0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, // ("y and a larger t")
+			       0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+			       0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, // ("han block-size d")
+			       0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+			       0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, // ("ata. The key nee")
+			       0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+			       0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, // ("ds to be hashed ")
+			       0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+			       0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, // ("before being use")
+			       0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+			       0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, // ("d by the HMAC al")
+			       0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e }, // ("gorithm.")
+		.psize	= 152,
+		.digest	= { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d,
+			    0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
+			    0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
+			    0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
+			    0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d,
+			    0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e },
+	},
+};
+
+/*
+ * SHA512 HMAC test vectors from RFC4231
+ */
+
+#define HMAC_SHA512_TEST_VECTORS	4
+
+static struct hash_testvec hmac_sha512_tv_template[] = {
+	{
+		.key	= { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			    0x0b, 0x0b, 0x0b, 0x0b }, // (20 bytes)
+		.ksize	= 20,
+		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 }, // ("Hi There")
+		.psize	= 8,
+		.digest	= { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
+			    0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+			    0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+			    0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
+			    0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
+			    0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
+			    0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70,
+			    0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 },
+	}, {
+		.key	= { 0x4a, 0x65, 0x66, 0x65 }, // ("Jefe")
+		.ksize	= 4,
+		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+			       0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, // ("what do ya want ")
+			       0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+			       0x69, 0x6e, 0x67, 0x3f }, // ("for nothing?")
+		.psize	= 28,
+		.digest	= { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
+			    0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+			    0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+			    0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
+			    0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a,
+			    0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
+			    0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b,
+			    0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 },
+		.np	= 4,
+		.tap	= { 7, 7, 7, 7 }
+	}, {
+		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa }, // (131 bytes)
+		.ksize	= 131,
+		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
+			       0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65, // ("Test Using Large")
+			       0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
+			       0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a, // ("r Than Block-Siz")
+			       0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
+			       0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79, // ("e Key - Hash Key")
+			       0x20, 0x46, 0x69, 0x72, 0x73, 0x74 }, // (" First")
+		.psize	= 54,
+		.digest	= { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb,
+			    0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
+			    0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
+			    0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
+			    0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98,
+			    0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
+			    0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec,
+			    0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 },
+	}, {
+		.key	= { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+			    0xaa, 0xaa, 0xaa }, // (131 bytes)
+		.ksize	= 131,
+		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+			       0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, // ("This is a test u")
+			       0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
+			       0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68, // ("sing a larger th")
+			       0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+			       0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65, // ("an block-size ke")
+			       0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+			       0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, // ("y and a larger t")
+			       0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+			       0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64, // ("han block-size d")
+			       0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
+			       0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65, // ("ata. The key nee")
+			       0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+			       0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20, // ("ds to be hashed ")
+			       0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
+			       0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, // ("before being use")
+			       0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+			       0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c, // ("d by the HMAC al")
+			       0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e }, // ("gorithm.")
+		.psize	= 152,
+		.digest	= { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba,
+			    0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
+			    0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
+			    0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
+			    0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1,
+			    0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
+			    0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60,
+			    0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 },
+	},
+};
+
 /*
  * DES test vectors.
  */
@@ -3316,6 +3559,278 @@ static struct cipher_testvec xeta_dec_tv_template[] = {
 	}
 };
 
+/* 
+ * FCrypt test vectors 
+ */
+#define FCRYPT_ENC_TEST_VECTORS	ARRAY_SIZE(fcrypt_pcbc_enc_tv_template)
+#define FCRYPT_DEC_TEST_VECTORS	ARRAY_SIZE(fcrypt_pcbc_dec_tv_template)
+
+static struct cipher_testvec fcrypt_pcbc_enc_tv_template[] = {
+	{ /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ilen	= 8,
+		.result	= { 0x0E, 0x09, 0x00, 0xC7, 0x3E, 0xF7, 0xED, 0x41 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x11, 0x44, 0x77, 0xAA, 0xDD, 0x00, 0x33, 0x66 },
+		.klen	= 8,
+		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 },
+		.ilen	= 8,
+		.result	= { 0xD8, 0xED, 0x78, 0x74, 0x77, 0xEC, 0x06, 0x80 },
+		.rlen	= 8,
+	}, { /* From Arla */
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.klen	= 8,
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.ilen	= 48,
+		.result	= { 0x00, 0xf0, 0xe,  0x11, 0x75, 0xe6, 0x23, 0x82,
+			    0xee, 0xac, 0x98, 0x62, 0x44, 0x51, 0xe4, 0x84,
+			    0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+			    0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03,
+			    0x23, 0xb5, 0x62, 0xd7, 0x0c, 0xf5, 0x27, 0xd1,
+			    0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef },
+		.rlen	= 48,
+	}, {
+		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 8,
+		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.ilen	= 48,
+		.result	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
+		.rlen	= 48,
+	}, { /* split-page version */
+		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 8,
+		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.input	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.ilen	= 48,
+		.result	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
+		.rlen	= 48,
+		.np	= 2,
+		.tap	= { 20, 28 },
+	}
+};
+
+static struct cipher_testvec fcrypt_pcbc_dec_tv_template[] = {
+	{ /* http://www.openafs.org/pipermail/openafs-devel/2000-December/005320.html */
+		.key	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.klen	= 8,
+		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input	= { 0x0E, 0x09, 0x00, 0xC7, 0x3E, 0xF7, 0xED, 0x41 },
+		.ilen	= 8,
+		.result	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x11, 0x44, 0x77, 0xAA, 0xDD, 0x00, 0x33, 0x66 },
+		.klen	= 8,
+		.iv	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.input	= { 0xD8, 0xED, 0x78, 0x74, 0x77, 0xEC, 0x06, 0x80 },
+		.ilen	= 8,
+		.result	= { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 },
+		.rlen	= 8,
+	}, { /* From Arla */
+		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.klen	= 8,
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.input	= { 0x00, 0xf0, 0xe,  0x11, 0x75, 0xe6, 0x23, 0x82,
+			    0xee, 0xac, 0x98, 0x62, 0x44, 0x51, 0xe4, 0x84,
+			    0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7,
+			    0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03,
+			    0x23, 0xb5, 0x62, 0xd7, 0x0c, 0xf5, 0x27, 0xd1,
+			    0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef },
+		.ilen	= 48,
+		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.rlen	= 48,
+	}, {
+		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 8,
+		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.input	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
+		.ilen	= 48,
+		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.rlen	= 48,
+	}, { /* split-page version */
+		.key	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 8,
+		.iv	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
+		.input	= { 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c,
+			    0x01, 0x88, 0x7f, 0x3e, 0x31, 0x6e, 0x62, 0x9d,
+			    0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58,
+			    0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0,
+			    0x19, 0x89, 0x09, 0x1c, 0x2a, 0x8e, 0x8c, 0x94,
+			    0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f },
+		.ilen	= 48,
+		.result	= "The quick brown fox jumps over the lazy dogs.\0\0",
+		.rlen	= 48,
+		.np	= 2,
+		.tap	= { 20, 28 },
+	}
+};
+
+/*
+ * CAMELLIA test vectors.
+ */
+#define CAMELLIA_ENC_TEST_VECTORS 3
+#define CAMELLIA_DEC_TEST_VECTORS 3
+#define CAMELLIA_CBC_ENC_TEST_VECTORS 2
+#define CAMELLIA_CBC_DEC_TEST_VECTORS 2
+
+static struct cipher_testvec camellia_enc_tv_template[] = {
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 16,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 16,
+		.result	= { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+			    0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+		.klen	= 24,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 16,
+		.result	= { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+			    0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.klen	= 32,
+		.input	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.ilen	= 16,
+		.result	= { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+			    0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+		.rlen	= 16,
+	},
+};
+
+static struct cipher_testvec camellia_dec_tv_template[] = {
+	{
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.klen	= 16,
+		.input	= { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
+			    0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 },
+		.ilen	= 16,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },
+		.klen	= 24,
+		.input	= { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
+			    0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 },
+		.ilen	= 16,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
+			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+		.klen	= 32,
+		.input	= { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
+			    0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 },
+		.ilen	= 16,
+		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+			    0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+		.rlen	= 16,
+	},
+};
+
+static struct cipher_testvec camellia_cbc_enc_tv_template[] = {
+	{
+		.key    = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+			    0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
+		.klen   = 16,
+		.iv	= { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+			    0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+		.input	= { "Single block msg" },
+		.ilen   = 16,
+		.result = { 0xea, 0x32, 0x12, 0x76, 0x3b, 0x50, 0x10, 0xe7,
+			    0x18, 0xf6, 0xfd, 0x5d, 0xf6, 0x8f, 0x13, 0x51 },
+		.rlen   = 16,
+	}, {
+		.key    = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+			    0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
+		.klen   = 16,
+		.iv     = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+			    0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+		.input  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+		.ilen   = 32,
+		.result = { 0xa5, 0xdf, 0x6e, 0x50, 0xda, 0x70, 0x6c, 0x01,
+			    0x4a, 0xab, 0xf3, 0xf2, 0xd6, 0xfc, 0x6c, 0xfd,
+			    0x19, 0xb4, 0x3e, 0x57, 0x1c, 0x02, 0x5e, 0xa0,
+			    0x15, 0x78, 0xe0, 0x5e, 0xf2, 0xcb, 0x87, 0x16 },
+		.rlen   = 32,
+	},
+};
+
+static struct cipher_testvec camellia_cbc_dec_tv_template[] = {
+	{
+		.key    = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+			    0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
+		.klen   = 16,
+		.iv	= { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+			    0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+		.input	= { 0xea, 0x32, 0x12, 0x76, 0x3b, 0x50, 0x10, 0xe7,
+			    0x18, 0xf6, 0xfd, 0x5d, 0xf6, 0x8f, 0x13, 0x51 },
+		.ilen   = 16,
+		.result = { "Single block msg" },
+		.rlen   = 16,
+	}, {
+		.key    = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+			    0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
+		.klen   = 16,
+		.iv     = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+			    0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+		.input = { 0xa5, 0xdf, 0x6e, 0x50, 0xda, 0x70, 0x6c, 0x01,
+			    0x4a, 0xab, 0xf3, 0xf2, 0xd6, 0xfc, 0x6c, 0xfd,
+			    0x19, 0xb4, 0x3e, 0x57, 0x1c, 0x02, 0x5e, 0xa0,
+			    0x15, 0x78, 0xe0, 0x5e, 0xf2, 0xcb, 0x87, 0x16 },
+		.ilen   = 32,
+		.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+		.rlen   = 32,
+	},
+};
+
 /*
  * Compression stuff.
  */
@@ -3769,4 +4284,25 @@ static struct hash_speed generic_hash_speed_template[] = {
 	{  .blen = 0,	.plen = 0, }
 };
 
+static struct cipher_speed camellia_speed_template[] = {
+      { .klen = 16, .blen = 16, },
+      { .klen = 16, .blen = 64, },
+      { .klen = 16, .blen = 256, },
+      { .klen = 16, .blen = 1024, },
+      { .klen = 16, .blen = 8192, },
+      { .klen = 24, .blen = 16, },
+      { .klen = 24, .blen = 64, },
+      { .klen = 24, .blen = 256, },
+      { .klen = 24, .blen = 1024, },
+      { .klen = 24, .blen = 8192, },
+      { .klen = 32, .blen = 16, },
+      { .klen = 32, .blen = 64, },
+      { .klen = 32, .blen = 256, },
+      { .klen = 32, .blen = 1024, },
+      { .klen = 32, .blen = 8192, },
+
+      /* End marker */
+      {  .klen = 0, .blen = 0, }
+};
+
 #endif	/* _CRYPTO_TCRYPT_H */

+ 38 - 22
crypto/xcbc.c

@@ -21,6 +21,7 @@
 
 #include <linux/crypto.h>
 #include <linux/err.h>
+#include <linux/hardirq.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/rtnetlink.h>
@@ -47,7 +48,7 @@ static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
  * +------------------------
  */
 struct crypto_xcbc_ctx {
-	struct crypto_tfm *child;
+	struct crypto_cipher *child;
 	u8 *odds;
 	u8 *prev;
 	u8 *key;
@@ -75,8 +76,7 @@ static int _crypto_xcbc_digest_setkey(struct crypto_hash *parent,
 	if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen)))
 	    return err;
 
-	ctx->child->__crt_alg->cra_cipher.cia_encrypt(ctx->child, key1,
-			ctx->consts);
+	crypto_cipher_encrypt_one(ctx->child, key1, ctx->consts);
 
 	return crypto_cipher_setkey(ctx->child, key1, bs);
 }
@@ -86,7 +86,7 @@ static int crypto_xcbc_digest_setkey(struct crypto_hash *parent,
 {
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
 
-	if (keylen != crypto_tfm_alg_blocksize(ctx->child))
+	if (keylen != crypto_cipher_blocksize(ctx->child))
 		return -EINVAL;
 
 	ctx->keylen = keylen;
@@ -108,13 +108,13 @@ static int crypto_xcbc_digest_init(struct hash_desc *pdesc)
 	return 0;
 }
 
-static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
-				     struct scatterlist *sg,
-				     unsigned int nbytes)
+static int crypto_xcbc_digest_update2(struct hash_desc *pdesc,
+				      struct scatterlist *sg,
+				      unsigned int nbytes)
 {
 	struct crypto_hash *parent = pdesc->tfm;
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
-	struct crypto_tfm *tfm = ctx->child;
+	struct crypto_cipher *tfm = ctx->child;
 	int bs = crypto_hash_blocksize(parent);
 	unsigned int i = 0;
 
@@ -142,7 +142,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 					offset += len;
 
 				crypto_kunmap(p, 0);
-				crypto_yield(tfm->crt_flags);
+				crypto_yield(pdesc->flags);
 				continue;
 			}
 
@@ -152,7 +152,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 			p += bs - ctx->len;
 
 			ctx->xor(ctx->prev, ctx->odds, bs);
-			tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
+			crypto_cipher_encrypt_one(tfm, ctx->prev, ctx->prev);
 
 			/* clearing the length */
 			ctx->len = 0;
@@ -160,7 +160,8 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 			/* encrypting the rest of data */
 			while (len > bs) {
 				ctx->xor(ctx->prev, p, bs);
-				tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
+				crypto_cipher_encrypt_one(tfm, ctx->prev,
+							  ctx->prev);
 				p += bs;
 				len -= bs;
 			}
@@ -171,7 +172,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 				ctx->len = len;
 			}
 			crypto_kunmap(p, 0);
-			crypto_yield(tfm->crt_flags);
+			crypto_yield(pdesc->flags);
 			slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
 			offset = 0;
 			pg++;
@@ -183,11 +184,20 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 	return 0;
 }
 
+static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
+				     struct scatterlist *sg,
+				     unsigned int nbytes)
+{
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+	return crypto_xcbc_digest_update2(pdesc, sg, nbytes);
+}
+
 static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
 {
 	struct crypto_hash *parent = pdesc->tfm;
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
-	struct crypto_tfm *tfm = ctx->child;
+	struct crypto_cipher *tfm = ctx->child;
 	int bs = crypto_hash_blocksize(parent);
 	int err = 0;
 
@@ -197,13 +207,14 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
 		if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
 			return err;
 
-		tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key2, (const u8*)(ctx->consts+bs));
+		crypto_cipher_encrypt_one(tfm, key2,
+					  (u8 *)(ctx->consts + bs));
 
 		ctx->xor(ctx->prev, ctx->odds, bs);
 		ctx->xor(ctx->prev, key2, bs);
 		_crypto_xcbc_digest_setkey(parent, ctx);
 
-		tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
+		crypto_cipher_encrypt_one(tfm, out, ctx->prev);
 	} else {
 		u8 key3[bs];
 		unsigned int rlen;
@@ -218,14 +229,15 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
 		if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
 			return err;
 
-		tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key3, (const u8*)(ctx->consts+bs*2));
+		crypto_cipher_encrypt_one(tfm, key3,
+					  (u8 *)(ctx->consts + bs * 2));
 
 		ctx->xor(ctx->prev, ctx->odds, bs);
 		ctx->xor(ctx->prev, key3, bs);
 
 		_crypto_xcbc_digest_setkey(parent, ctx);
 
-		tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
+		crypto_cipher_encrypt_one(tfm, out, ctx->prev);
 	}
 
 	return 0;
@@ -234,21 +246,25 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
 static int crypto_xcbc_digest(struct hash_desc *pdesc,
 		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
 {
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
 	crypto_xcbc_digest_init(pdesc);
-	crypto_xcbc_digest_update(pdesc, sg, nbytes);
+	crypto_xcbc_digest_update2(pdesc, sg, nbytes);
 	return crypto_xcbc_digest_final(pdesc, out);
 }
 
 static int xcbc_init_tfm(struct crypto_tfm *tfm)
 {
+	struct crypto_cipher *cipher;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
 	int bs = crypto_hash_blocksize(__crypto_hash_cast(tfm));
 
-	tfm = crypto_spawn_tfm(spawn);
-	if (IS_ERR(tfm))
-		return PTR_ERR(tfm);
+	cipher = crypto_spawn_cipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
 
 	switch(bs) {
 	case 16:
@@ -258,7 +274,7 @@ static int xcbc_init_tfm(struct crypto_tfm *tfm)
 		return -EINVAL;
 	}
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	ctx->odds = (u8*)(ctx+1);
 	ctx->prev = ctx->odds + bs;
 	ctx->key = ctx->prev + bs;

+ 1 - 1
drivers/crypto/geode-aes.c

@@ -457,7 +457,7 @@ static struct pci_driver geode_aes_driver = {
 static int __init
 geode_aes_init(void)
 {
-	return pci_module_init(&geode_aes_driver);
+	return pci_register_driver(&geode_aes_driver);
 }
 
 static void __exit

+ 1 - 3
drivers/net/bonding/bond_alb.c

@@ -184,7 +184,7 @@ static int tlb_initialize(struct bonding *bond)
 
 	spin_lock_init(&(bond_info->tx_hashtbl_lock));
 
-	new_hashtbl = kmalloc(size, GFP_KERNEL);
+	new_hashtbl = kzalloc(size, GFP_KERNEL);
 	if (!new_hashtbl) {
 		printk(KERN_ERR DRV_NAME
 		       ": %s: Error: Failed to allocate TLB hash table\n",
@@ -195,8 +195,6 @@ static int tlb_initialize(struct bonding *bond)
 
 	bond_info->tx_hashtbl = new_hashtbl;
 
-	memset(bond_info->tx_hashtbl, 0, size);
-
 	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
 		tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
 	}

+ 1 - 3
drivers/net/bonding/bond_main.c

@@ -1343,14 +1343,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 			"inaccurate.\n", bond_dev->name, slave_dev->name);
 	}
 
-	new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
+	new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
 	if (!new_slave) {
 		res = -ENOMEM;
 		goto err_undo_flags;
 	}
 
-	memset(new_slave, 0, sizeof(struct slave));
-
 	/* save slave's original flags before calling
 	 * netdev_set_master and dev_open
 	 */

+ 1 - 4
drivers/net/slip.c

@@ -1343,15 +1343,12 @@ static int __init slip_init(void)
 	printk(KERN_INFO "SLIP linefill/keepalive option.\n");
 #endif
 
-	slip_devs = kmalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
+	slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
 	if (!slip_devs) {
 		printk(KERN_ERR "SLIP: Can't allocate slip devices array!  Uaargh! (-> No SLIP available)\n");
 		return -ENOMEM;
 	}
 
-	/* Clear the pointer array, we allocate devices when we need them */
-	memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev);
-
 	/* Fill in our line protocol discipline, and register it */
 	if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
 		printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);

+ 1 - 1
drivers/net/tg3.c

@@ -3380,7 +3380,7 @@ next_pkt:
 		}
 next_pkt_nopost:
 		sw_idx++;
-		sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
+		sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
 
 		/* Refresh hw_idx to see if there is new work */
 		if (sw_idx == hw_idx) {

+ 101 - 117
drivers/s390/char/monreader.c

@@ -3,7 +3,7 @@
  *
  * Character device driver for reading z/VM *MONITOR service records.
  *
- * Copyright (C) 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
  *
  * Author: Gerald Schaefer <geraldsc@de.ibm.com>
  */
@@ -22,7 +22,7 @@
 #include <asm/ebcdic.h>
 #include <asm/extmem.h>
 #include <linux/poll.h>
-#include "../net/iucv.h"
+#include <net/iucv/iucv.h>
 
 
 //#define MON_DEBUG			/* Debug messages on/off */
@@ -50,14 +50,13 @@ static char mon_dcss_name[9] = "MONDCSS\0";
 struct mon_msg {
 	u32 pos;
 	u32 mca_offset;
-	iucv_MessagePending local_eib;
+	struct iucv_message msg;
 	char msglim_reached;
 	char replied_msglim;
 };
 
 struct mon_private {
-	u16 pathid;
-	iucv_handle_t iucv_handle;
+	struct iucv_path *path;
 	struct mon_msg *msg_array[MON_MSGLIM];
 	unsigned int   write_index;
 	unsigned int   read_index;
@@ -75,8 +74,6 @@ static unsigned long mon_dcss_end;
 static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue);
 static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue);
 
-static u8 iucv_host[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
 static u8 user_data_connect[16] = {
 	/* Version code, must be 0x01 for shared mode */
 	0x01,
@@ -100,8 +97,7 @@ static u8 user_data_sever[16] = {
  * Create the 8 bytes EBCDIC DCSS segment name from
  * an ASCII name, incl. padding
  */
-static inline void
-dcss_mkname(char *ascii_name, char *ebcdic_name)
+static inline void dcss_mkname(char *ascii_name, char *ebcdic_name)
 {
 	int i;
 
@@ -119,8 +115,7 @@ dcss_mkname(char *ascii_name, char *ebcdic_name)
  * print appropriate error message for segment_load()/segment_type()
  * return code
  */
-static void
-mon_segment_warn(int rc, char* seg_name)
+static void mon_segment_warn(int rc, char* seg_name)
 {
 	switch (rc) {
 	case -ENOENT:
@@ -166,44 +161,37 @@ mon_segment_warn(int rc, char* seg_name)
 	}
 }
 
-static inline unsigned long
-mon_mca_start(struct mon_msg *monmsg)
+static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
 {
-	return monmsg->local_eib.ln1msg1.iprmmsg1_u32;
+	return *(u32 *) &monmsg->msg.rmmsg;
 }
 
-static inline unsigned long
-mon_mca_end(struct mon_msg *monmsg)
+static inline unsigned long mon_mca_end(struct mon_msg *monmsg)
 {
-	return monmsg->local_eib.ln1msg2.ipbfln1f;
+	return *(u32 *) &monmsg->msg.rmmsg[4];
 }
 
-static inline u8
-mon_mca_type(struct mon_msg *monmsg, u8 index)
+static inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index)
 {
 	return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);
 }
 
-static inline u32
-mon_mca_size(struct mon_msg *monmsg)
+static inline u32 mon_mca_size(struct mon_msg *monmsg)
 {
 	return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;
 }
 
-static inline u32
-mon_rec_start(struct mon_msg *monmsg)
+static inline u32 mon_rec_start(struct mon_msg *monmsg)
 {
 	return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4));
 }
 
-static inline u32
-mon_rec_end(struct mon_msg *monmsg)
+static inline u32 mon_rec_end(struct mon_msg *monmsg)
 {
 	return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
 }
 
-static inline int
-mon_check_mca(struct mon_msg *monmsg)
+static inline int mon_check_mca(struct mon_msg *monmsg)
 {
 	if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
 	    (mon_rec_start(monmsg) < mon_dcss_start) ||
@@ -221,20 +209,17 @@ mon_check_mca(struct mon_msg *monmsg)
 	return 0;
 }
 
-static inline int
-mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
+static inline int mon_send_reply(struct mon_msg *monmsg,
+				 struct mon_private *monpriv)
 {
-	u8 prmmsg[8];
 	int rc;
 
 	P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
 		"0x%08X\n\n",
-		monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,
-		monmsg->local_eib.iptrgcls);
-	rc = iucv_reply_prmmsg(monmsg->local_eib.ippathid,
-				monmsg->local_eib.ipmsgid,
-				monmsg->local_eib.iptrgcls,
-				0, prmmsg);
+		monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
+
+	rc = iucv_message_reply(monpriv->path, &monmsg->msg,
+				IUCV_IPRMDATA, NULL, 0);
 	atomic_dec(&monpriv->msglim_count);
 	if (likely(!monmsg->msglim_reached)) {
 		monmsg->pos = 0;
@@ -251,10 +236,19 @@ mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
 	return 0;
 }
 
-static inline struct mon_private *
-mon_alloc_mem(void)
+static inline void mon_free_mem(struct mon_private *monpriv)
+{
+	int i;
+
+	for (i = 0; i < MON_MSGLIM; i++)
+		if (monpriv->msg_array[i])
+			kfree(monpriv->msg_array[i]);
+	kfree(monpriv);
+}
+
+static inline struct mon_private *mon_alloc_mem(void)
 {
-	int i,j;
+	int i;
 	struct mon_private *monpriv;
 
 	monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
@@ -267,16 +261,15 @@ mon_alloc_mem(void)
 						    GFP_KERNEL);
 		if (!monpriv->msg_array[i]) {
 			P_ERROR("open, no memory for msg_array\n");
-			for (j = 0; j < i; j++)
-				kfree(monpriv->msg_array[j]);
+			mon_free_mem(monpriv);
 			return NULL;
 		}
 	}
 	return monpriv;
 }
 
-static inline void
-mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
+static inline void mon_read_debug(struct mon_msg *monmsg,
+				  struct mon_private *monpriv)
 {
 #ifdef MON_DEBUG
 	u8 msg_type[2], mca_type;
@@ -284,7 +277,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
 
 	records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
 
-	memcpy(msg_type, &monmsg->local_eib.iptrgcls, 2);
+	memcpy(msg_type, &monmsg->msg.class, 2);
 	EBCASC(msg_type, 2);
 	mca_type = mon_mca_type(monmsg, 0);
 	EBCASC(&mca_type, 1);
@@ -292,8 +285,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
 	P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
 		monpriv->read_index, monpriv->write_index);
 	P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
-		monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,
-		monmsg->local_eib.iptrgcls);
+		monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
 	P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
 		msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
 		mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
@@ -306,8 +298,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
 #endif
 }
 
-static inline void
-mon_next_mca(struct mon_msg *monmsg)
+static inline void mon_next_mca(struct mon_msg *monmsg)
 {
 	if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
 		return;
@@ -316,8 +307,7 @@ mon_next_mca(struct mon_msg *monmsg)
 	monmsg->pos = 0;
 }
 
-static inline struct mon_msg *
-mon_next_message(struct mon_private *monpriv)
+static inline struct mon_msg *mon_next_message(struct mon_private *monpriv)
 {
 	struct mon_msg *monmsg;
 
@@ -342,39 +332,37 @@ mon_next_message(struct mon_private *monpriv)
 /******************************************************************************
  *                               IUCV handler                                 *
  *****************************************************************************/
-static void
-mon_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data)
+static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
 {
-	struct mon_private *monpriv = (struct mon_private *) pgm_data;
+	struct mon_private *monpriv = path->private;
 
 	P_DEBUG("IUCV connection completed\n");
 	P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
 		"0x%02X, Sample = 0x%02X\n",
-		eib->ipuser[0], eib->ipuser[1], eib->ipuser[2]);
+		ipuser[0], ipuser[1], ipuser[2]);
 	atomic_set(&monpriv->iucv_connected, 1);
 	wake_up(&mon_conn_wait_queue);
 }
 
-static void
-mon_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data)
+static void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
 {
-	struct mon_private *monpriv = (struct mon_private *) pgm_data;
+	struct mon_private *monpriv = path->private;
 
-	P_ERROR("IUCV connection severed with rc = 0x%X\n",
-		(u8) eib->ipuser[0]);
+	P_ERROR("IUCV connection severed with rc = 0x%X\n", ipuser[0]);
+	iucv_path_sever(path, NULL);
 	atomic_set(&monpriv->iucv_severed, 1);
 	wake_up(&mon_conn_wait_queue);
 	wake_up_interruptible(&mon_read_wait_queue);
 }
 
-static void
-mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
+static void mon_iucv_message_pending(struct iucv_path *path,
+				     struct iucv_message *msg)
 {
-	struct mon_private *monpriv = (struct mon_private *) pgm_data;
+	struct mon_private *monpriv = path->private;
 
 	P_DEBUG("IUCV message pending\n");
-	memcpy(&monpriv->msg_array[monpriv->write_index]->local_eib, eib,
-	       sizeof(iucv_MessagePending));
+	memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
+	       msg, sizeof(*msg));
 	if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
 		P_WARNING("IUCV message pending, message limit (%i) reached\n",
 			  MON_MSGLIM);
@@ -385,54 +373,45 @@ mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
 	wake_up_interruptible(&mon_read_wait_queue);
 }
 
-static iucv_interrupt_ops_t mon_iucvops = {
-	.ConnectionComplete = mon_iucv_ConnectionComplete,
-	.ConnectionSevered  = mon_iucv_ConnectionSevered,
-	.MessagePending     = mon_iucv_MessagePending,
+static struct iucv_handler monreader_iucv_handler = {
+	.path_complete	 = mon_iucv_path_complete,
+	.path_severed	 = mon_iucv_path_severed,
+	.message_pending = mon_iucv_message_pending,
 };
 
 /******************************************************************************
  *                               file operations                              *
  *****************************************************************************/
-static int
-mon_open(struct inode *inode, struct file *filp)
+static int mon_open(struct inode *inode, struct file *filp)
 {
-	int rc, i;
 	struct mon_private *monpriv;
+	int rc;
 
 	/*
 	 * only one user allowed
 	 */
+	rc = -EBUSY;
 	if (test_and_set_bit(MON_IN_USE, &mon_in_use))
-		return -EBUSY;
+		goto out;
 
+	rc = -ENOMEM;
 	monpriv = mon_alloc_mem();
 	if (!monpriv)
-		return -ENOMEM;
+		goto out_use;
 
 	/*
-	 * Register with IUCV and connect to *MONITOR service
+	 * Connect to *MONITOR service
 	 */
-	monpriv->iucv_handle = iucv_register_program("my_monreader    ",
-							MON_SERVICE,
-							NULL,
-							&mon_iucvops,
-							monpriv);
-	if (!monpriv->iucv_handle) {
-		P_ERROR("failed to register with iucv driver\n");
-		rc = -EIO;
-		goto out_error;
-	}
-	P_INFO("open, registered with IUCV\n");
-
-	rc = iucv_connect(&monpriv->pathid, MON_MSGLIM, user_data_connect,
-			  MON_SERVICE, iucv_host, IPRMDATA, NULL, NULL,
-			  monpriv->iucv_handle, NULL);
+	monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL);
+	if (!monpriv->path)
+		goto out_priv;
+	rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler,
+			       MON_SERVICE, NULL, user_data_connect, monpriv);
 	if (rc) {
 		P_ERROR("iucv connection to *MONITOR failed with "
 			"IPUSER SEVER code = %i\n", rc);
 		rc = -EIO;
-		goto out_unregister;
+		goto out_path;
 	}
 	/*
 	 * Wait for connection confirmation
@@ -444,24 +423,23 @@ mon_open(struct inode *inode, struct file *filp)
 		atomic_set(&monpriv->iucv_severed, 0);
 		atomic_set(&monpriv->iucv_connected, 0);
 		rc = -EIO;
-		goto out_unregister;
+		goto out_path;
 	}
 	P_INFO("open, established connection to *MONITOR service\n\n");
 	filp->private_data = monpriv;
 	return nonseekable_open(inode, filp);
 
-out_unregister:
-	iucv_unregister_program(monpriv->iucv_handle);
-out_error:
-	for (i = 0; i < MON_MSGLIM; i++)
-		kfree(monpriv->msg_array[i]);
-	kfree(monpriv);
+out_path:
+	kfree(monpriv->path);
+out_priv:
+	mon_free_mem(monpriv);
+out_use:
 	clear_bit(MON_IN_USE, &mon_in_use);
+out:
 	return rc;
 }
 
-static int
-mon_close(struct inode *inode, struct file *filp)
+static int mon_close(struct inode *inode, struct file *filp)
 {
 	int rc, i;
 	struct mon_private *monpriv = filp->private_data;
@@ -469,18 +447,12 @@ mon_close(struct inode *inode, struct file *filp)
 	/*
 	 * Close IUCV connection and unregister
 	 */
-	rc = iucv_sever(monpriv->pathid, user_data_sever);
+	rc = iucv_path_sever(monpriv->path, user_data_sever);
 	if (rc)
 		P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
 	else
 		P_INFO("close, terminated connection to *MONITOR service\n");
 
-	rc = iucv_unregister_program(monpriv->iucv_handle);
-	if (rc)
-		P_ERROR("close, iucv_unregister failed with rc = %i\n", rc);
-	else
-		P_INFO("close, unregistered with IUCV\n");
-
 	atomic_set(&monpriv->iucv_severed, 0);
 	atomic_set(&monpriv->iucv_connected, 0);
 	atomic_set(&monpriv->read_ready, 0);
@@ -495,8 +467,8 @@ mon_close(struct inode *inode, struct file *filp)
 	return 0;
 }
 
-static ssize_t
-mon_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
+static ssize_t mon_read(struct file *filp, char __user *data,
+			size_t count, loff_t *ppos)
 {
 	struct mon_private *monpriv = filp->private_data;
 	struct mon_msg *monmsg;
@@ -563,8 +535,7 @@ out_copy:
 	return count;
 }
 
-static unsigned int
-mon_poll(struct file *filp, struct poll_table_struct *p)
+static unsigned int mon_poll(struct file *filp, struct poll_table_struct *p)
 {
 	struct mon_private *monpriv = filp->private_data;
 
@@ -593,8 +564,7 @@ static struct miscdevice mon_dev = {
 /******************************************************************************
  *                              module init/exit                              *
  *****************************************************************************/
-static int __init
-mon_init(void)
+static int __init mon_init(void)
 {
 	int rc;
 
@@ -603,22 +573,34 @@ mon_init(void)
 		return -ENODEV;
 	}
 
+	/*
+	 * Register with IUCV and connect to *MONITOR service
+	 */
+	rc = iucv_register(&monreader_iucv_handler, 1);
+	if (rc) {
+		P_ERROR("failed to register with iucv driver\n");
+		return rc;
+	}
+	P_INFO("open, registered with IUCV\n");
+
 	rc = segment_type(mon_dcss_name);
 	if (rc < 0) {
 		mon_segment_warn(rc, mon_dcss_name);
-		return rc;
+		goto out_iucv;
 	}
 	if (rc != SEG_TYPE_SC) {
 		P_ERROR("segment %s has unsupported type, should be SC\n",
 			mon_dcss_name);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out_iucv;
 	}
 
 	rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
 			  &mon_dcss_start, &mon_dcss_end);
 	if (rc < 0) {
 		mon_segment_warn(rc, mon_dcss_name);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out_iucv;
 	}
 	dcss_mkname(mon_dcss_name, &user_data_connect[8]);
 
@@ -634,14 +616,16 @@ mon_init(void)
 
 out:
 	segment_unload(mon_dcss_name);
+out_iucv:
+	iucv_unregister(&monreader_iucv_handler, 1);
 	return rc;
 }
 
-static void __exit
-mon_exit(void)
+static void __exit mon_exit(void)
 {
 	segment_unload(mon_dcss_name);
 	WARN_ON(misc_deregister(&mon_dev) != 0);
+	iucv_unregister(&monreader_iucv_handler, 1);
 	return;
 }
 

+ 127 - 152
drivers/s390/char/vmlogrdr.c

@@ -3,7 +3,7 @@
  *	character device driver for reading z/VM system service records
  *
  *
- *	Copyright (C) 2004 IBM Corporation
+ *	Copyright 2004 IBM Corporation
  *	character device driver for reading z/VM system service records,
  *	Version 1.0
  *	Author(s): Xenia Tkatschow <xenia@us.ibm.com>
@@ -21,7 +21,7 @@
 #include <asm/cpcmd.h>
 #include <asm/debug.h>
 #include <asm/ebcdic.h>
-#include "../net/iucv.h"
+#include <net/iucv/iucv.h>
 #include <linux/kmod.h>
 #include <linux/cdev.h>
 #include <linux/device.h>
@@ -60,12 +60,11 @@ struct vmlogrdr_priv_t {
 	char system_service[8];
 	char internal_name[8];
 	char recording_name[8];
-	u16 pathid;
+	struct iucv_path *path;
 	int connection_established;
 	int iucv_path_severed;
-	iucv_MessagePending local_interrupt_buffer;
+	struct iucv_message local_interrupt_buffer;
 	atomic_t receive_ready;
-	iucv_handle_t iucv_handle;
 	int minor_num;
 	char * buffer;
 	char * current_position;
@@ -97,37 +96,19 @@ static struct file_operations vmlogrdr_fops = {
 };
 
 
-static u8 iucvMagic[16] = {
-	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
-	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
-};
+static void vmlogrdr_iucv_path_complete(struct iucv_path *, u8 ipuser[16]);
+static void vmlogrdr_iucv_path_severed(struct iucv_path *, u8 ipuser[16]);
+static void vmlogrdr_iucv_message_pending(struct iucv_path *,
+					  struct iucv_message *);
 
 
-static u8 mask[] = {
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+static struct iucv_handler vmlogrdr_iucv_handler = {
+	.path_complete	 = vmlogrdr_iucv_path_complete,
+	.path_severed	 = vmlogrdr_iucv_path_severed,
+	.message_pending = vmlogrdr_iucv_message_pending,
 };
 
 
-static u8 iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-
-static void
-vmlogrdr_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data);
-static void
-vmlogrdr_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data);
-static void
-vmlogrdr_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data);
-
-
-static iucv_interrupt_ops_t vmlogrdr_iucvops = {
-	.ConnectionComplete = vmlogrdr_iucv_ConnectionComplete,
-	.ConnectionSevered  = vmlogrdr_iucv_ConnectionSevered,
-	.MessagePending     = vmlogrdr_iucv_MessagePending,
-};
-
 static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
 static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
 
@@ -176,28 +157,29 @@ static struct cdev  *vmlogrdr_cdev = NULL;
 static int recording_class_AB;
 
 
-static void
-vmlogrdr_iucv_ConnectionComplete (iucv_ConnectionComplete * eib,
-				   void * pgm_data)
+static void vmlogrdr_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
 {
-	struct vmlogrdr_priv_t * logptr = pgm_data;
+	struct vmlogrdr_priv_t * logptr = path->private;
+
 	spin_lock(&logptr->priv_lock);
 	logptr->connection_established = 1;
 	spin_unlock(&logptr->priv_lock);
 	wake_up(&conn_wait_queue);
-	return;
 }
 
 
-static void
-vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
+static void vmlogrdr_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
 {
-	u8 reason = (u8) eib->ipuser[8];
-	struct vmlogrdr_priv_t * logptr = pgm_data;
+	struct vmlogrdr_priv_t * logptr = path->private;
+	u8 reason = (u8) ipuser[8];
 
 	printk (KERN_ERR "vmlogrdr: connection severed with"
 		" reason %i\n", reason);
 
+	iucv_path_sever(path, NULL);
+	kfree(path);
+	logptr->path = NULL;
+
 	spin_lock(&logptr->priv_lock);
 	logptr->connection_established = 0;
 	logptr->iucv_path_severed = 1;
@@ -209,10 +191,10 @@ vmlogrdr_iucv_ConnectionSevered (iucv_ConnectionSevered * eib, void * pgm_data)
 }
 
 
-static void
-vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data)
+static void vmlogrdr_iucv_message_pending(struct iucv_path *path,
+					  struct iucv_message *msg)
 {
-	struct vmlogrdr_priv_t * logptr = pgm_data;
+	struct vmlogrdr_priv_t * logptr = path->private;
 
 	/*
 	 * This function is the bottom half so it should be quick.
@@ -220,15 +202,15 @@ vmlogrdr_iucv_MessagePending (iucv_MessagePending * eib, void * pgm_data)
 	 * the usage count
 	 */
 	spin_lock(&logptr->priv_lock);
-	memcpy(&(logptr->local_interrupt_buffer), eib, sizeof(*eib));
+	memcpy(&logptr->local_interrupt_buffer, msg, sizeof(*msg));
 	atomic_inc(&logptr->receive_ready);
 	spin_unlock(&logptr->priv_lock);
 	wake_up_interruptible(&read_wait_queue);
 }
 
 
-static int
-vmlogrdr_get_recording_class_AB(void) {
+static int vmlogrdr_get_recording_class_AB(void)
+{
 	char cp_command[]="QUERY COMMAND RECORDING ";
 	char cp_response[80];
 	char *tail;
@@ -258,8 +240,9 @@ vmlogrdr_get_recording_class_AB(void) {
 }
 
 
-static int
-vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
+static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
+			      int action, int purge)
+{
 
 	char cp_command[80];
 	char cp_response[160];
@@ -317,8 +300,7 @@ vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
 }
 
 
-static int
-vmlogrdr_open (struct inode *inode, struct file *filp)
+static int vmlogrdr_open (struct inode *inode, struct file *filp)
 {
 	int dev_num = 0;
 	struct vmlogrdr_priv_t * logptr = NULL;
@@ -328,10 +310,7 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
 	dev_num = iminor(inode);
 	if (dev_num > MAXMINOR)
 		return -ENODEV;
-
 	logptr = &sys_ser[dev_num];
-	if (logptr == NULL)
-		return -ENODEV;
 
 	/*
 	 * only allow for blocking reads to be open
@@ -344,52 +323,38 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
 	if (logptr->dev_in_use)	{
 		spin_unlock_bh(&logptr->priv_lock);
 		return -EBUSY;
-	} else {
-		logptr->dev_in_use = 1;
-		spin_unlock_bh(&logptr->priv_lock);
 	}
-
+	logptr->dev_in_use = 1;
+	logptr->connection_established = 0;
+	logptr->iucv_path_severed = 0;
 	atomic_set(&logptr->receive_ready, 0);
 	logptr->buffer_free = 1;
+	spin_unlock_bh(&logptr->priv_lock);
 
 	/* set the file options */
 	filp->private_data = logptr;
 	filp->f_op = &vmlogrdr_fops;
 
 	/* start recording for this service*/
-	ret=0;
-	if (logptr->autorecording)
+	if (logptr->autorecording) {
 		ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
-	if (ret)
-		printk (KERN_WARNING "vmlogrdr: failed to start "
-			"recording automatically\n");
-
-	/* Register with iucv driver */
-	logptr->iucv_handle = iucv_register_program(iucvMagic,
-			logptr->system_service, mask, &vmlogrdr_iucvops,
-			logptr);
-
-	if (logptr->iucv_handle == NULL) {
-		printk (KERN_ERR "vmlogrdr: failed to register with"
-			"iucv driver\n");
-		goto not_registered;
+		if (ret)
+			printk (KERN_WARNING "vmlogrdr: failed to start "
+				"recording automatically\n");
 	}
 
 	/* create connection to the system service */
-	spin_lock_bh(&logptr->priv_lock);
-	logptr->connection_established = 0;
-	logptr->iucv_path_severed = 0;
-	spin_unlock_bh(&logptr->priv_lock);
-
-	connect_rc = iucv_connect (&(logptr->pathid), 10, iucvMagic,
-					logptr->system_service, iucv_host, 0,
-					NULL, NULL,
-					logptr->iucv_handle, NULL);
+	logptr->path = iucv_path_alloc(10, 0, GFP_KERNEL);
+	if (!logptr->path)
+		goto out_dev;
+	connect_rc = iucv_path_connect(logptr->path, &vmlogrdr_iucv_handler,
+				       logptr->system_service, NULL, NULL,
+				       logptr);
 	if (connect_rc) {
 		printk (KERN_ERR "vmlogrdr: iucv connection to %s "
 			"failed with rc %i \n", logptr->system_service,
 			connect_rc);
-		goto not_connected;
+		goto out_path;
 	}
 
 	/* We've issued the connect and now we must wait for a
@@ -398,35 +363,28 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
 	 */
 	wait_event(conn_wait_queue, (logptr->connection_established)
 		   || (logptr->iucv_path_severed));
-	if (logptr->iucv_path_severed) {
-		goto not_connected;
-	}
-
+	if (logptr->iucv_path_severed)
+		goto out_record;
  	return nonseekable_open(inode, filp);
 
-not_connected:
-	iucv_unregister_program(logptr->iucv_handle);
-	logptr->iucv_handle = NULL;
-not_registered:
+out_record:
 	if (logptr->autorecording)
 		vmlogrdr_recording(logptr,0,logptr->autopurge);
+out_path:
+	kfree(logptr->path);	/* kfree(NULL) is ok. */
+	logptr->path = NULL;
+out_dev:
 	logptr->dev_in_use = 0;
 	return -EIO;
-
-
 }
 
 
-static int
-vmlogrdr_release (struct inode *inode, struct file *filp)
+static int vmlogrdr_release (struct inode *inode, struct file *filp)
 {
 	int ret;
 
 	struct vmlogrdr_priv_t * logptr = filp->private_data;
 
-	iucv_unregister_program(logptr->iucv_handle);
-	logptr->iucv_handle = NULL;
-
 	if (logptr->autorecording) {
 		ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
 		if (ret)
@@ -439,8 +397,8 @@ vmlogrdr_release (struct inode *inode, struct file *filp)
 }
 
 
-static int
-vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
+static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv)
+{
 	int rc, *temp;
 	/* we need to keep track of two data sizes here:
 	 * The number of bytes we need to receive from iucv and
@@ -461,8 +419,7 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
 			 * We need to return the total length of the record
                          * + size of FENCE in the first 4 bytes of the buffer.
 		         */
-			iucv_data_count =
-				priv->local_interrupt_buffer.ln1msg2.ipbfln1f;
+			iucv_data_count = priv->local_interrupt_buffer.length;
 			user_data_count = sizeof(int);
 			temp = (int*)priv->buffer;
 			*temp= iucv_data_count + sizeof(FENCE);
@@ -474,14 +431,10 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
 		 */
 		if (iucv_data_count > NET_BUFFER_SIZE)
 			iucv_data_count = NET_BUFFER_SIZE;
-		rc = iucv_receive(priv->pathid,
-				  priv->local_interrupt_buffer.ipmsgid,
-				  priv->local_interrupt_buffer.iptrgcls,
-				  buffer,
-				  iucv_data_count,
-				  NULL,
-				  NULL,
-				  &priv->residual_length);
+		rc = iucv_message_receive(priv->path,
+					  &priv->local_interrupt_buffer,
+					  0, buffer, iucv_data_count,
+					  &priv->residual_length);
 		spin_unlock_bh(&priv->priv_lock);
 		/* An rc of 5 indicates that the record was bigger then
 		 * the buffer, which is OK for us. A 9 indicates that the
@@ -513,8 +466,8 @@ vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) {
 }
 
 
-static ssize_t
-vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
+static ssize_t vmlogrdr_read(struct file *filp, char __user *data,
+			     size_t count, loff_t * ppos)
 {
 	int rc;
 	struct vmlogrdr_priv_t * priv = filp->private_data;
@@ -546,8 +499,10 @@ vmlogrdr_read(struct file *filp, char __user *data, size_t count, loff_t * ppos)
 	return count;
 }
 
-static ssize_t
-vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
+static ssize_t vmlogrdr_autopurge_store(struct device * dev,
+					struct device_attribute *attr,
+					const char * buf, size_t count)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret = count;
 
@@ -565,8 +520,10 @@ vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, con
 }
 
 
-static ssize_t
-vmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) {
+static ssize_t vmlogrdr_autopurge_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	return sprintf(buf, "%u\n", priv->autopurge);
 }
@@ -576,8 +533,10 @@ static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,
 		   vmlogrdr_autopurge_store);
 
 
-static ssize_t
-vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
+static ssize_t vmlogrdr_purge_store(struct device * dev,
+				    struct device_attribute *attr,
+				    const char * buf, size_t count)
+{
 
 	char cp_command[80];
 	char cp_response[80];
@@ -617,9 +576,10 @@ vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const c
 static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);
 
 
-static ssize_t
-vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf,
-			     size_t count) {
+static ssize_t vmlogrdr_autorecording_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret = count;
 
@@ -637,8 +597,10 @@ vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr,
 }
 
 
-static ssize_t
-vmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) {
+static ssize_t vmlogrdr_autorecording_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	return sprintf(buf, "%u\n", priv->autorecording);
 }
@@ -648,9 +610,10 @@ static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,
 		   vmlogrdr_autorecording_store);
 
 
-static ssize_t
-vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
-
+static ssize_t vmlogrdr_recording_store(struct device * dev,
+					struct device_attribute *attr,
+					const char * buf, size_t count)
+{
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret;
 
@@ -675,8 +638,9 @@ vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, con
 static DEVICE_ATTR(recording, 0200, NULL, vmlogrdr_recording_store);
 
 
-static ssize_t
-vmlogrdr_recording_status_show(struct device_driver *driver, char *buf) {
+static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver,
+					      char *buf)
+{
 
 	char cp_command[] = "QUERY RECORDING ";
 	int len;
@@ -709,52 +673,63 @@ static struct device_driver vmlogrdr_driver = {
 };
 
 
-static int
-vmlogrdr_register_driver(void) {
+static int vmlogrdr_register_driver(void)
+{
 	int ret;
 
+	/* Register with iucv driver */
+	ret = iucv_register(&vmlogrdr_iucv_handler, 1);
+	if (ret) {
+		printk (KERN_ERR "vmlogrdr: failed to register with"
+			"iucv driver\n");
+		goto out;
+	}
+
 	ret = driver_register(&vmlogrdr_driver);
 	if (ret) {
 		printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
-		return ret;
+		goto out_iucv;
 	}
 
 	ret = driver_create_file(&vmlogrdr_driver,
 				 &driver_attr_recording_status);
 	if (ret) {
 		printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
-		goto unregdriver;
+		goto out_driver;
 	}
 
 	vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
 	if (IS_ERR(vmlogrdr_class)) {
 		printk(KERN_ERR "vmlogrdr: failed to create class.\n");
-		ret=PTR_ERR(vmlogrdr_class);
-		vmlogrdr_class=NULL;
-		goto unregattr;
+		ret = PTR_ERR(vmlogrdr_class);
+		vmlogrdr_class = NULL;
+		goto out_attr;
 	}
 	return 0;
 
-unregattr:
+out_attr:
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
-unregdriver:
+out_driver:
 	driver_unregister(&vmlogrdr_driver);
+out_iucv:
+	iucv_unregister(&vmlogrdr_iucv_handler, 1);
+out:
 	return ret;
 }
 
 
-static void
-vmlogrdr_unregister_driver(void) {
+static void vmlogrdr_unregister_driver(void)
+{
 	class_destroy(vmlogrdr_class);
 	vmlogrdr_class = NULL;
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
 	driver_unregister(&vmlogrdr_driver);
-	return;
+	iucv_unregister(&vmlogrdr_iucv_handler, 1);
 }
 
 
-static int
-vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
+static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
+{
 	struct device *dev;
 	int ret;
 
@@ -803,9 +778,10 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
 }
 
 
-static int
-vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
-	class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
+static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
+{
+	class_device_destroy(vmlogrdr_class,
+			     MKDEV(vmlogrdr_major, priv->minor_num));
 	if (priv->device != NULL) {
 		sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
 		device_unregister(priv->device);
@@ -815,8 +791,8 @@ vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
 }
 
 
-static int
-vmlogrdr_register_cdev(dev_t dev) {
+static int vmlogrdr_register_cdev(dev_t dev)
+{
 	int rc = 0;
 	vmlogrdr_cdev = cdev_alloc();
 	if (!vmlogrdr_cdev) {
@@ -836,9 +812,10 @@ vmlogrdr_register_cdev(dev_t dev) {
 }
 
 
-static void
-vmlogrdr_cleanup(void) {
+static void vmlogrdr_cleanup(void)
+{
         int i;
+
 	if (vmlogrdr_cdev) {
 		cdev_del(vmlogrdr_cdev);
 		vmlogrdr_cdev=NULL;
@@ -855,8 +832,7 @@ vmlogrdr_cleanup(void) {
 }
 
 
-static int
-vmlogrdr_init(void)
+static int vmlogrdr_init(void)
 {
 	int rc;
 	int i;
@@ -906,8 +882,7 @@ cleanup:
 }
 
 
-static void
-vmlogrdr_exit(void)
+static void vmlogrdr_exit(void)
 {
 	vmlogrdr_cleanup();
 	printk (KERN_INFO "vmlogrdr: driver unloaded\n");

+ 0 - 7
drivers/s390/net/Kconfig

@@ -22,13 +22,6 @@ config CTC
 	  available.  This option is also available as a module which will be
 	  called ctc.ko.  If you do not know what it is, it's safe to say "Y".
 
-config IUCV
-	tristate "IUCV support (VM only)"
-	help
-	  Select this option if you want to use inter-user communication
-	  under VM or VIF. If unsure, say "Y" to enable a fast communication
-	  link between VM guests.
-
 config NETIUCV
 	tristate "IUCV network device support (VM only)"
 	depends on IUCV && NETDEVICES

+ 0 - 1
drivers/s390/net/Makefile

@@ -4,7 +4,6 @@
 
 ctc-objs := ctcmain.o ctcdbug.o
 
-obj-$(CONFIG_IUCV) += iucv.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
 obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
 obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o

+ 0 - 2540
drivers/s390/net/iucv.c

@@ -1,2540 +0,0 @@
-/*
- * IUCV network driver
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s):
- *    Original source:
- *      Alan Altmark (Alan_Altmark@us.ibm.com)  Sept. 2000
- *      Xenia Tkatschow (xenia@us.ibm.com)
- *    2Gb awareness and general cleanup:
- *      Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * Documentation used:
- *    The original source
- *    CP Programming Service, IBM document # SC24-5760
- *
- * 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; either version 2, or (at your option)
- * any later version.
- *
- * 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.
- *
- */
-
-/* #define DEBUG */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/spinlock.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <asm/atomic.h>
-#include "iucv.h"
-#include <asm/io.h>
-#include <asm/s390_ext.h>
-#include <asm/ebcdic.h>
-#include <asm/smp.h>
-#include <asm/s390_rdev.h>
-
-/* FLAGS:
- * All flags are defined in the field IPFLAGS1 of each function
- * and can be found in CP Programming Services.
- * IPSRCCLS - Indicates you have specified a source class
- * IPFGMCL  - Indicates you have specified a target class
- * IPFGPID  - Indicates you have specified a pathid
- * IPFGMID  - Indicates you have specified a message ID
- * IPANSLST - Indicates that you are using an address list for
- *            reply data
- * IPBUFLST - Indicates that you are using an address list for
- *            message data
- */
-
-#define IPSRCCLS 	0x01
-#define IPFGMCL         0x01
-#define IPFGPID         0x02
-#define IPFGMID         0x04
-#define IPANSLST        0x08
-#define IPBUFLST        0x40
-
-static int
-iucv_bus_match (struct device *dev, struct device_driver *drv)
-{
-	return 0;
-}
-
-struct bus_type iucv_bus = {
-	.name = "iucv",
-	.match = iucv_bus_match,
-};
-
-struct device *iucv_root;
-
-/* General IUCV interrupt structure */
-typedef struct {
-	__u16 ippathid;
-	__u8  res1;
-	__u8  iptype;
-	__u32 res2;
-	__u8  ipvmid[8];
-	__u8  res3[24];
-} iucv_GeneralInterrupt;
-
-static iucv_GeneralInterrupt *iucv_external_int_buffer = NULL;
-
-/* Spin Lock declaration */
-
-static DEFINE_SPINLOCK(iucv_lock);
-
-static int messagesDisabled = 0;
-
-/***************INTERRUPT HANDLING ***************/
-
-typedef struct {
-	struct list_head queue;
-	iucv_GeneralInterrupt data;
-} iucv_irqdata;
-
-static struct list_head  iucv_irq_queue;
-static DEFINE_SPINLOCK(iucv_irq_queue_lock);
-
-/*
- *Internal function prototypes
- */
-static void iucv_tasklet_handler(unsigned long);
-static void iucv_irq_handler(__u16);
-
-static DECLARE_TASKLET(iucv_tasklet,iucv_tasklet_handler,0);
-
-/************ FUNCTION ID'S ****************************/
-
-#define ACCEPT          10
-#define CONNECT         11
-#define DECLARE_BUFFER  12
-#define PURGE           9
-#define QUERY           0
-#define QUIESCE         13
-#define RECEIVE         5
-#define REJECT          8
-#define REPLY           6
-#define RESUME          14
-#define RETRIEVE_BUFFER 2
-#define SEND            4
-#define SETMASK         16
-#define SEVER           15
-
-/**
- * Structure: handler
- * members: list - list management.
- *          structure: id
- *             userid - 8 char array of machine identification
- *             user_data - 16 char array for user identification
- *             mask - 24 char array used to compare the 2 previous
- *          interrupt_table - vector of interrupt functions.
- *          pgm_data -  ulong, application data that is passed
- *                      to the interrupt handlers
-*/
-typedef struct handler_t {
-	struct list_head list;
-	struct {
-		__u8 userid[8];
-		__u8 user_data[16];
-		__u8 mask[24];
-	}                    id;
-	iucv_interrupt_ops_t *interrupt_table;
-	void                 *pgm_data;
-} handler;
-
-/**
- * iucv_handler_table: List of registered handlers.
- */
-static struct list_head iucv_handler_table;
-
-/**
- * iucv_pathid_table: an array of *handler pointing into
- *                    iucv_handler_table for fast indexing by pathid;
- */
-static handler **iucv_pathid_table;
-
-static unsigned long max_connections;
-
-/**
- * iucv_cpuid: contains the logical cpu number of the cpu which
- * has declared the iucv buffer by issuing DECLARE_BUFFER.
- * If no cpu has done the initialization iucv_cpuid contains -1.
- */
-static int iucv_cpuid = -1;
-/**
- * register_flag: is 0 when external interrupt has not been registered
- */
-static int register_flag;
-
-/****************FIVE 40-BYTE PARAMETER STRUCTURES******************/
-/* Data struct 1: iparml_control
- * Used for iucv_accept
- *          iucv_connect
- *          iucv_quiesce
- *          iucv_resume
- *          iucv_sever
- *          iucv_retrieve_buffer
- * Data struct 2: iparml_dpl     (data in parameter list)
- * Used for iucv_send_prmmsg
- *          iucv_send2way_prmmsg
- *          iucv_send2way_prmmsg_array
- *          iucv_reply_prmmsg
- * Data struct 3: iparml_db       (data in a buffer)
- * Used for iucv_receive
- *          iucv_receive_array
- *          iucv_reject
- *          iucv_reply
- *          iucv_reply_array
- *          iucv_send
- *          iucv_send_array
- *          iucv_send2way
- *          iucv_send2way_array
- *          iucv_declare_buffer
- * Data struct 4: iparml_purge
- * Used for iucv_purge
- *          iucv_query
- * Data struct 5: iparml_set_mask
- * Used for iucv_set_mask
- */
-
-typedef struct {
-	__u16 ippathid;
-	__u8  ipflags1;
-	__u8  iprcode;
-	__u16 ipmsglim;
-	__u16 res1;
-	__u8  ipvmid[8];
-	__u8  ipuser[16];
-	__u8  iptarget[8];
-} iparml_control;
-
-typedef struct {
-	__u16 ippathid;
-	__u8  ipflags1;
-	__u8  iprcode;
-	__u32 ipmsgid;
-	__u32 iptrgcls;
-	__u8  iprmmsg[8];
-	__u32 ipsrccls;
-	__u32 ipmsgtag;
-	__u32 ipbfadr2;
-	__u32 ipbfln2f;
-	__u32 res;
-} iparml_dpl;
-
-typedef struct {
-	__u16 ippathid;
-	__u8  ipflags1;
-	__u8  iprcode;
-	__u32 ipmsgid;
-	__u32 iptrgcls;
-	__u32 ipbfadr1;
-	__u32 ipbfln1f;
-	__u32 ipsrccls;
-	__u32 ipmsgtag;
-	__u32 ipbfadr2;
-	__u32 ipbfln2f;
-	__u32 res;
-} iparml_db;
-
-typedef struct {
-	__u16 ippathid;
-	__u8  ipflags1;
-	__u8  iprcode;
-	__u32 ipmsgid;
-	__u8  ipaudit[3];
-	__u8  res1[5];
-	__u32 res2;
-	__u32 ipsrccls;
-	__u32 ipmsgtag;
-	__u32 res3[3];
-} iparml_purge;
-
-typedef struct {
-	__u8  ipmask;
-	__u8  res1[2];
-	__u8  iprcode;
-	__u32 res2[9];
-} iparml_set_mask;
-
-typedef struct {
-	union {
-		iparml_control  p_ctrl;
-		iparml_dpl      p_dpl;
-		iparml_db       p_db;
-		iparml_purge    p_purge;
-		iparml_set_mask p_set_mask;
-	} param;
-	atomic_t in_use;
-	__u32    res;
-}  __attribute__ ((aligned(8))) iucv_param;
-#define PARAM_POOL_SIZE (PAGE_SIZE / sizeof(iucv_param))
-
-static iucv_param * iucv_param_pool;
-
-MODULE_AUTHOR("(C) 2001 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
-MODULE_DESCRIPTION("Linux for S/390 IUCV lowlevel driver");
-MODULE_LICENSE("GPL");
-
-/*
- * Debugging stuff
- *******************************************************************************/
-
-
-#ifdef DEBUG
-static int debuglevel = 0;
-
-module_param(debuglevel, int, 0);
-MODULE_PARM_DESC(debuglevel,
- "Specifies the debug level (0=off ... 3=all)");
-
-static void
-iucv_dumpit(char *title, void *buf, int len)
-{
-	int i;
-	__u8 *p = (__u8 *)buf;
-
-	if (debuglevel < 3)
-		return;
-
-	printk(KERN_DEBUG "%s\n", title);
-	printk("  ");
-	for (i = 0; i < len; i++) {
-		if (!(i % 16) && i != 0)
-			printk ("\n  ");
-		else if (!(i % 4) && i != 0)
-			printk(" ");
-		printk("%02X", *p++);
-	}
-	if (len % 16)
-		printk ("\n");
-	return;
-}
-#define iucv_debug(lvl, fmt, args...) \
-do { \
-	if (debuglevel >= lvl) \
-		printk(KERN_DEBUG "%s: " fmt "\n", __FUNCTION__ , ## args); \
-} while (0)
-
-#else
-
-#define iucv_debug(lvl, fmt, args...)	do { } while (0)
-#define iucv_dumpit(title, buf, len)	do { } while (0)
-
-#endif
-
-/*
- * Internal functions
- *******************************************************************************/
-
-/**
- * print start banner
- */
-static void
-iucv_banner(void)
-{
-	printk(KERN_INFO "IUCV lowlevel driver initialized\n");
-}
-
-/**
- * iucv_init - Initialization
- *
- * Allocates and initializes various data structures.
- */
-static int
-iucv_init(void)
-{
-	int ret;
-
-	if (iucv_external_int_buffer)
-		return 0;
-
-	if (!MACHINE_IS_VM) {
-		printk(KERN_ERR "IUCV: IUCV connection needs VM as base\n");
-		return -EPROTONOSUPPORT;
-	}
-
-	ret = bus_register(&iucv_bus);
-	if (ret) {
-		printk(KERN_ERR "IUCV: failed to register bus.\n");
-		return ret;
-	}
-
-	iucv_root = s390_root_dev_register("iucv");
-	if (IS_ERR(iucv_root)) {
-		printk(KERN_ERR "IUCV: failed to register iucv root.\n");
-		bus_unregister(&iucv_bus);
-		return PTR_ERR(iucv_root);
-	}
-
-	/* Note: GFP_DMA used used to get memory below 2G */
-	iucv_external_int_buffer = kzalloc(sizeof(iucv_GeneralInterrupt),
-					   GFP_KERNEL|GFP_DMA);
-	if (!iucv_external_int_buffer) {
-		printk(KERN_WARNING
-		       "%s: Could not allocate external interrupt buffer\n",
-		       __FUNCTION__);
-		s390_root_dev_unregister(iucv_root);
-		bus_unregister(&iucv_bus);
-		return -ENOMEM;
-	}
-
-	/* Initialize parameter pool */
-	iucv_param_pool = kzalloc(sizeof(iucv_param) * PARAM_POOL_SIZE,
-				  GFP_KERNEL|GFP_DMA);
-	if (!iucv_param_pool) {
-		printk(KERN_WARNING "%s: Could not allocate param pool\n",
-		       __FUNCTION__);
-		kfree(iucv_external_int_buffer);
-		iucv_external_int_buffer = NULL;
-		s390_root_dev_unregister(iucv_root);
-		bus_unregister(&iucv_bus);
-		return -ENOMEM;
-	}
-
-	/* Initialize irq queue */
-	INIT_LIST_HEAD(&iucv_irq_queue);
-
-	/* Initialize handler table */
-	INIT_LIST_HEAD(&iucv_handler_table);
-
-	iucv_banner();
-	return 0;
-}
-
-/**
- * iucv_exit - De-Initialization
- *
- * Frees everything allocated from iucv_init.
- */
-static int iucv_retrieve_buffer (void);
-
-static void
-iucv_exit(void)
-{
-	iucv_retrieve_buffer();
-	kfree(iucv_external_int_buffer);
-	iucv_external_int_buffer = NULL;
-	kfree(iucv_param_pool);
-	iucv_param_pool = NULL;
-	s390_root_dev_unregister(iucv_root);
-	bus_unregister(&iucv_bus);
-	printk(KERN_INFO "IUCV lowlevel driver unloaded\n");
-}
-
-/**
- * grab_param: - Get a parameter buffer from the pre-allocated pool.
- *
- * This function searches for an unused element in the pre-allocated pool
- * of parameter buffers. If one is found, it marks it "in use" and returns
- * a pointer to it. The calling function is responsible for releasing it
- * when it has finished its usage.
- *
- * Returns: A pointer to iucv_param.
- */
-static __inline__ iucv_param *
-grab_param(void)
-{
-	iucv_param *ptr;
-        static int hint = 0;
-
-	ptr = iucv_param_pool + hint;
-	do {
-		ptr++;
-		if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
-			ptr = iucv_param_pool;
-	} while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0);
-	hint = ptr - iucv_param_pool;
-
-	memset(&ptr->param, 0, sizeof(ptr->param));
-	return ptr;
-}
-
-/**
- * release_param - Release a parameter buffer.
- * @p: A pointer to a struct iucv_param, previously obtained by calling
- *     grab_param().
- *
- * This function marks the specified parameter buffer "unused".
- */
-static __inline__ void
-release_param(void *p)
-{
-	atomic_set(&((iucv_param *)p)->in_use, 0);
-}
-
-/**
- * iucv_add_handler: - Add a new handler
- * @new_handler: handle that is being entered into chain.
- *
- * Places new handle on iucv_handler_table, if identical handler is not
- * found.
- *
- * Returns: 0 on success, !0 on failure (handler already in chain).
- */
-static int
-iucv_add_handler (handler *new)
-{
-	ulong flags;
-
-	iucv_debug(1, "entering");
-	iucv_dumpit("handler:", new, sizeof(handler));
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	if (!list_empty(&iucv_handler_table)) {
-		struct list_head *lh;
-
-		/**
-		 * Search list for handler with identical id. If one
-		 * is found, the new handler is _not_ added.
-		 */
-		list_for_each(lh, &iucv_handler_table) {
-			handler *h = list_entry(lh, handler, list);
-			if (!memcmp(&new->id, &h->id, sizeof(h->id))) {
-				iucv_debug(1, "ret 1");
-				spin_unlock_irqrestore (&iucv_lock, flags);
-				return 1;
-			}
-		}
-	}
-	/**
-	 * If we get here, no handler was found.
-	 */
-	INIT_LIST_HEAD(&new->list);
-	list_add(&new->list, &iucv_handler_table);
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	iucv_debug(1, "exiting");
-	return 0;
-}
-
-/**
- * b2f0:
- * @code: identifier of IUCV call to CP.
- * @parm: pointer to 40 byte iparml area passed to CP
- *
- * Calls CP to execute IUCV commands.
- *
- * Returns: return code from CP's IUCV call
- */
-static inline ulong b2f0(__u32 code, void *parm)
-{
-	register unsigned long reg0 asm ("0");
-	register unsigned long reg1 asm ("1");
-	iucv_dumpit("iparml before b2f0 call:", parm, sizeof(iucv_param));
-
-	reg0 = code;
-	reg1 = virt_to_phys(parm);
-	asm volatile(".long 0xb2f01000" : : "d" (reg0), "a" (reg1));
-
-	iucv_dumpit("iparml after b2f0 call:", parm, sizeof(iucv_param));
-
-	return (unsigned long)*((__u8 *)(parm + 3));
-}
-
-/*
- * Name: iucv_add_pathid
- * Purpose: Adds a path id to the system.
- * Input: pathid -  pathid that is going to be entered into system
- *        handle -  address of handler that the pathid will be associated
- *		   with.
- *        pgm_data - token passed in by application.
- * Output: 0: successful addition of pathid
- *	   - EINVAL - pathid entry is being used by another application
- *	   - ENOMEM - storage allocation for a new pathid table failed
-*/
-static int
-__iucv_add_pathid(__u16 pathid, handler *handler)
-{
-
-	iucv_debug(1, "entering");
-
-	iucv_debug(1, "handler is pointing to %p", handler);
-
-	if (pathid > (max_connections - 1))
-		return -EINVAL;
-
-	if (iucv_pathid_table[pathid]) {
-		iucv_debug(1, "pathid entry is %p", iucv_pathid_table[pathid]);
-		printk(KERN_WARNING
-		       "%s: Pathid being used, error.\n", __FUNCTION__);
-		return -EINVAL;
-	}
-	iucv_pathid_table[pathid] = handler;
-
-	iucv_debug(1, "exiting");
-	return 0;
-}				/* end of add_pathid function */
-
-static int
-iucv_add_pathid(__u16 pathid, handler *handler)
-{
-	ulong flags;
-	int rc;
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	rc = __iucv_add_pathid(pathid, handler);
-	spin_unlock_irqrestore (&iucv_lock, flags);
-	return rc;
-}
-
-static void
-iucv_remove_pathid(__u16 pathid)
-{
-	ulong flags;
-
-	if (pathid > (max_connections - 1))
-		return;
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	iucv_pathid_table[pathid] = NULL;
-	spin_unlock_irqrestore (&iucv_lock, flags);
-}
-
-/**
- * iucv_declare_buffer_cpuid
- * Register at VM for subsequent IUCV operations. This is executed
- * on the reserved CPU iucv_cpuid. Called from iucv_declare_buffer().
- */
-static void
-iucv_declare_buffer_cpuid (void *result)
-{
-	iparml_db *parm;
-
-	parm = (iparml_db *)grab_param();
-	parm->ipbfadr1 = virt_to_phys(iucv_external_int_buffer);
-	if ((*((ulong *)result) = b2f0(DECLARE_BUFFER, parm)) == 1)
-		*((ulong *)result) = parm->iprcode;
-	release_param(parm);
-}
-
-/**
- * iucv_retrieve_buffer_cpuid:
- * Unregister IUCV usage at VM. This is always executed on the same
- * cpu that registered the buffer to VM.
- * Called from iucv_retrieve_buffer().
- */
-static void
-iucv_retrieve_buffer_cpuid (void *cpu)
-{
-	iparml_control *parm;
-
-	parm = (iparml_control *)grab_param();
-	b2f0(RETRIEVE_BUFFER, parm);
-	release_param(parm);
-}
-
-/**
- * Name: iucv_declare_buffer
- * Purpose: Specifies the guests real address of an external
- *          interrupt.
- * Input: void
- * Output: iprcode - return code from b2f0 call
- */
-static int
-iucv_declare_buffer (void)
-{
-	unsigned long flags;
-	ulong b2f0_result;
-
-	iucv_debug(1, "entering");
-	b2f0_result = -ENODEV;
-	spin_lock_irqsave (&iucv_lock, flags);
-	if (iucv_cpuid == -1) {
-		/* Reserve any cpu for use by iucv. */
-		iucv_cpuid = smp_get_cpu(CPU_MASK_ALL);
-		spin_unlock_irqrestore (&iucv_lock, flags);
-		smp_call_function_on(iucv_declare_buffer_cpuid,
-			&b2f0_result, 0, 1, iucv_cpuid);
-		if (b2f0_result) {
-			smp_put_cpu(iucv_cpuid);
-			iucv_cpuid = -1;
-		}
-		iucv_debug(1, "Address of EIB = %p", iucv_external_int_buffer);
-	} else {
-		spin_unlock_irqrestore (&iucv_lock, flags);
-		b2f0_result = 0;
-	}
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_retrieve_buffer:
- *
- * Terminates all use of IUCV.
- * Returns: return code from CP
- */
-static int
-iucv_retrieve_buffer (void)
-{
-	iucv_debug(1, "entering");
-	if (iucv_cpuid != -1) {
-		smp_call_function_on(iucv_retrieve_buffer_cpuid,
-				     NULL, 0, 1, iucv_cpuid);
-		/* Release the cpu reserved by iucv_declare_buffer. */
-		smp_put_cpu(iucv_cpuid);
-		iucv_cpuid = -1;
-	}
-	iucv_debug(1, "exiting");
-	return 0;
-}
-
-/**
- * iucv_remove_handler:
- * @users_handler: handler to be removed
- *
- * Remove handler when application unregisters.
- */
-static void
-iucv_remove_handler(handler *handler)
-{
-	unsigned long flags;
-
-	if ((!iucv_pathid_table) || (!handler))
-		return;
-
-	iucv_debug(1, "entering");
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	list_del(&handler->list);
-	if (list_empty(&iucv_handler_table)) {
-		if (register_flag) {
-			unregister_external_interrupt(0x4000, iucv_irq_handler);
-			register_flag = 0;
-		}
-	}
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	iucv_debug(1, "exiting");
-	return;
-}
-
-/**
- * iucv_register_program:
- * @pgmname:  user identification
- * @userid:   machine identification
- * @pgmmask:  Indicates which bits in the pgmname and userid combined will be
- *            used to determine who is given control.
- * @ops:      Address of interrupt handler table.
- * @pgm_data: Application data to be passed to interrupt handlers.
- *
- * Registers an application with IUCV.
- * Returns:
- *           The address of handler, or NULL on failure.
- * NOTE on pgmmask:
- *   If pgmname, userid and pgmmask are provided, pgmmask is entered into the
- *   handler as is.
- *   If pgmmask is NULL, the internal mask is set to all 0xff's
- *   When userid is NULL, the first 8 bytes of the internal mask are forced
- *   to 0x00.
- *   If pgmmask and userid are NULL, the first 8 bytes of the internal mask
- *   are forced to 0x00 and the last 16 bytes to 0xff.
- */
-
-iucv_handle_t
-iucv_register_program (__u8 pgmname[16],
-		       __u8 userid[8],
-		       __u8 pgmmask[24],
-		       iucv_interrupt_ops_t * ops, void *pgm_data)
-{
-	ulong rc = 0;		/* return code from function calls */
-	handler *new_handler;
-
-	iucv_debug(1, "entering");
-
-	if (ops == NULL) {
-		/* interrupt table is not defined */
-		printk(KERN_WARNING "%s: Interrupt table is not defined, "
-		       "exiting\n", __FUNCTION__);
-		return NULL;
-	}
-	if (!pgmname) {
-		printk(KERN_WARNING "%s: pgmname not provided\n", __FUNCTION__);
-		return NULL;
-	}
-
-	/* Allocate handler entry */
-	new_handler = kmalloc(sizeof(handler), GFP_ATOMIC);
-	if (new_handler == NULL) {
-		printk(KERN_WARNING "%s: storage allocation for new handler "
-		       "failed.\n", __FUNCTION__);
-		return NULL;
-	}
-
-	if (!iucv_pathid_table) {
-		if (iucv_init()) {
-			kfree(new_handler);
-			return NULL;
-		}
-
-		max_connections = iucv_query_maxconn();
-		iucv_pathid_table = kcalloc(max_connections, sizeof(handler *),
-					GFP_ATOMIC);
-		if (iucv_pathid_table == NULL) {
-			printk(KERN_WARNING "%s: iucv_pathid_table storage "
-			       "allocation failed\n", __FUNCTION__);
-			kfree(new_handler);
-			return NULL;
-		}
-	}
-	memset(new_handler, 0, sizeof (handler));
-	memcpy(new_handler->id.user_data, pgmname,
-		sizeof (new_handler->id.user_data));
-	if (userid) {
-		memcpy (new_handler->id.userid, userid,
-			sizeof (new_handler->id.userid));
-		ASCEBC (new_handler->id.userid,
-			sizeof (new_handler->id.userid));
-		EBC_TOUPPER (new_handler->id.userid,
-			     sizeof (new_handler->id.userid));
-
-		if (pgmmask) {
-			memcpy (new_handler->id.mask, pgmmask,
-				sizeof (new_handler->id.mask));
-		} else {
-			memset (new_handler->id.mask, 0xFF,
-				sizeof (new_handler->id.mask));
-		}
-	} else {
-		if (pgmmask) {
-			memcpy (new_handler->id.mask, pgmmask,
-				sizeof (new_handler->id.mask));
-		} else {
-			memset (new_handler->id.mask, 0xFF,
-				sizeof (new_handler->id.mask));
-		}
-		memset (new_handler->id.userid, 0x00,
-			sizeof (new_handler->id.userid));
-	}
-	/* fill in the rest of handler */
-	new_handler->pgm_data = pgm_data;
-	new_handler->interrupt_table = ops;
-
-	/*
-	 * Check if someone else is registered with same pgmname, userid
-	 * and mask. If someone is already registered with same pgmname,
-	 * userid and mask, registration will fail and NULL will be returned
-	 * to the application.
-	 * If identical handler not found, then handler is added to list.
-	 */
-	rc = iucv_add_handler(new_handler);
-	if (rc) {
-		printk(KERN_WARNING "%s: Someone already registered with same "
-		       "pgmname, userid, pgmmask\n", __FUNCTION__);
-		kfree (new_handler);
-		return NULL;
-	}
-
-	rc = iucv_declare_buffer();
-	if (rc) {
-		char *err = "Unknown";
-		iucv_remove_handler(new_handler);
-		kfree(new_handler);
-		switch(rc) {
-		case 0x03:
-			err = "Directory error";
-			break;
-		case 0x0a:
-			err = "Invalid length";
-			break;
-		case 0x13:
-			err = "Buffer already exists";
-			break;
-		case 0x3e:
-			err = "Buffer overlap";
-			break;
-		case 0x5c:
-			err = "Paging or storage error";
-			break;
-		}
-		printk(KERN_WARNING "%s: iucv_declare_buffer "
-		       "returned error 0x%02lx (%s)\n", __FUNCTION__, rc, err);
-		return NULL;
-	}
-	if (!register_flag) {
-		/* request the 0x4000 external interrupt */
-		rc = register_external_interrupt (0x4000, iucv_irq_handler);
-		if (rc) {
-			iucv_remove_handler(new_handler);
-			kfree (new_handler);
-			printk(KERN_WARNING "%s: "
-			       "register_external_interrupt returned %ld\n",
-			       __FUNCTION__, rc);
-			return NULL;
-
-		}
-		register_flag = 1;
-	}
-	iucv_debug(1, "exiting");
-	return new_handler;
-}				/* end of register function */
-
-/**
- * iucv_unregister_program:
- * @handle: address of handler
- *
- * Unregister application with IUCV.
- * Returns:
- *   0 on success, -EINVAL, if specified handle is invalid.
- */
-
-int
-iucv_unregister_program (iucv_handle_t handle)
-{
-	handler *h = NULL;
-	struct list_head *lh;
-	int i;
-	ulong flags;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "address of handler is %p", h);
-
-	/* Checking if handle is valid  */
-	spin_lock_irqsave (&iucv_lock, flags);
-	list_for_each(lh, &iucv_handler_table) {
-		if ((handler *)handle == list_entry(lh, handler, list)) {
-			h = (handler *)handle;
-			break;
-		}
-	}
-	if (!h) {
-		spin_unlock_irqrestore (&iucv_lock, flags);
-		if (handle)
-			printk(KERN_WARNING
-			       "%s: Handler not found in iucv_handler_table.\n",
-			       __FUNCTION__);
-		else
-			printk(KERN_WARNING
-			       "%s: NULL handle passed by application.\n",
-			       __FUNCTION__);
-		return -EINVAL;
-	}
-
-	/**
-	 * First, walk thru iucv_pathid_table and sever any pathid which is
-	 * still pointing to the handler to be removed.
-	 */
-	for (i = 0; i < max_connections; i++)
-		if (iucv_pathid_table[i] == h) {
-			spin_unlock_irqrestore (&iucv_lock, flags);
-			iucv_sever(i, h->id.user_data);
-			spin_lock_irqsave(&iucv_lock, flags);
-		}
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	iucv_remove_handler(h);
-	kfree(h);
-
-	iucv_debug(1, "exiting");
-	return 0;
-}
-
-/**
- * iucv_accept:
- * @pathid:             Path identification number
- * @msglim_reqstd:      The number of outstanding messages requested.
- * @user_data:          Data specified by the iucv_connect function.
- * @flags1:             Contains options for this path.
- *     - IPPRTY (0x20)   Specifies if you want to send priority message.
- *     - IPRMDATA (0x80) Specifies whether your program can handle a message
- *                       in the parameter list.
- *     - IPQUSCE (0x40)  Specifies whether you want to quiesce the path being
- *		         established.
- * @handle:             Address of handler.
- * @pgm_data:           Application data passed to interrupt handlers.
- * @flags1_out:         Pointer to an int. If not NULL, on return the options for
- *                      the path are stored at the given location:
- *     - IPPRTY (0x20)  Indicates you may send a priority message.
- * @msglim:             Pointer to an __u16. If not NULL, on return the maximum
- *                      number of outstanding messages is stored at the given
- *                      location.
- *
- * This function is issued after the user receives a Connection Pending external
- * interrupt and now wishes to complete the IUCV communication path.
- * Returns:
- *   return code from CP
- */
-int
-iucv_accept(__u16 pathid, __u16 msglim_reqstd,
-	     __u8 user_data[16], int flags1,
-	     iucv_handle_t handle, void *pgm_data,
-	     int *flags1_out, __u16 * msglim)
-{
-	ulong b2f0_result = 0;
-	ulong flags;
-	struct list_head *lh;
-	handler *h = NULL;
-	iparml_control *parm;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	/* Checking if handle is valid  */
-	spin_lock_irqsave (&iucv_lock, flags);
-	list_for_each(lh, &iucv_handler_table) {
-		if ((handler *)handle == list_entry(lh, handler, list)) {
-			h = (handler *)handle;
-			break;
-		}
-	}
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	if (!h) {
-		if (handle)
-			printk(KERN_WARNING
-			       "%s: Handler not found in iucv_handler_table.\n",
-			       __FUNCTION__);
-		else
-			printk(KERN_WARNING
-			       "%s: NULL handle passed by application.\n",
-			       __FUNCTION__);
-		return -EINVAL;
-	}
-
-	parm = (iparml_control *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->ipmsglim = msglim_reqstd;
-	if (user_data)
-		memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-
-	parm->ipflags1 = (__u8)flags1;
-	b2f0_result = b2f0(ACCEPT, parm);
-
-	if (!b2f0_result) {
-		if (msglim)
-			*msglim = parm->ipmsglim;
-		if (pgm_data)
-			h->pgm_data = pgm_data;
-		if (flags1_out)
-			*flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
-	}
-	release_param(parm);
-
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_connect:
- * @pathid:        Path identification number
- * @msglim_reqstd: Number of outstanding messages requested
- * @user_data:     16-byte user data
- * @userid:        8-byte of user identification
- * @system_name:   8-byte identifying the system name
- * @flags1:        Specifies options for this path:
- *     - IPPRTY (0x20)   Specifies if you want to send priority message.
- *     - IPRMDATA (0x80) Specifies whether your program can handle a message
- *                       in  the parameter list.
- *     - IPQUSCE (0x40)  Specifies whether you want to quiesce the path being
- *                       established.
- *     - IPLOCAL (0x01)  Allows an application to force the partner to be on the
- *                       local system. If local is specified then target class
- *                       cannot be specified.
- * @flags1_out:    Pointer to an int. If not NULL, on return the options for
- *                 the path are stored at the given location:
- *     - IPPRTY (0x20)   Indicates you may send a priority message.
- * @msglim:        Pointer to an __u16. If not NULL, on return the maximum
- *                 number of outstanding messages is stored at the given
- *                 location.
- * @handle:        Address of handler.
- * @pgm_data:      Application data to be passed to interrupt handlers.
- *
- * This function establishes an IUCV path. Although the connect may complete
- * successfully, you are not able to use the path until you receive an IUCV
- * Connection Complete external interrupt.
- * Returns: return code from CP, or one of the following
- *     - ENOMEM
- *     - return code from iucv_declare_buffer
- *     - EINVAL - invalid handle passed by application
- *     - EINVAL - pathid address is NULL
- *     - ENOMEM - pathid table storage allocation failed
- *     - return code from internal function add_pathid
- */
-int
-iucv_connect (__u16 *pathid, __u16 msglim_reqstd,
-	      __u8 user_data[16], __u8 userid[8],
-	      __u8 system_name[8], int flags1,
-	      int *flags1_out, __u16 * msglim,
-	      iucv_handle_t handle, void *pgm_data)
-{
-	iparml_control *parm;
-	iparml_control local_parm;
-	struct list_head *lh;
-	ulong b2f0_result = 0;
-	ulong flags;
-	int add_pathid_result = 0;
-	handler *h = NULL;
-	__u8 no_memory[16] = "NO MEMORY";
-
-	iucv_debug(1, "entering");
-
-	/* Checking if handle is valid  */
-	spin_lock_irqsave (&iucv_lock, flags);
-	list_for_each(lh, &iucv_handler_table) {
-		if ((handler *)handle == list_entry(lh, handler, list)) {
-			h = (handler *)handle;
-			break;
-		}
-	}
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	if (!h) {
-		if (handle)
-			printk(KERN_WARNING
-			       "%s: Handler not found in iucv_handler_table.\n",
-			       __FUNCTION__);
-		else
-			printk(KERN_WARNING
-			       "%s: NULL handle passed by application.\n",
-			       __FUNCTION__);
-		return -EINVAL;
-	}
-
-	if (pathid == NULL) {
-		printk(KERN_WARNING "%s: NULL pathid pointer\n",
-		       __FUNCTION__);
-		return -EINVAL;
-	}
-
-	parm = (iparml_control *)grab_param();
-
-	parm->ipmsglim = msglim_reqstd;
-
-	if (user_data)
-		memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-
-	if (userid) {
-		memcpy(parm->ipvmid, userid, sizeof(parm->ipvmid));
-		ASCEBC(parm->ipvmid, sizeof(parm->ipvmid));
-		EBC_TOUPPER(parm->ipvmid, sizeof(parm->ipvmid));
-	}
-
-	if (system_name) {
-		memcpy(parm->iptarget, system_name, sizeof(parm->iptarget));
-		ASCEBC(parm->iptarget, sizeof(parm->iptarget));
-		EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget));
-	}
-
-	/* In order to establish an IUCV connection, the procedure is:
-         *
-         * b2f0(CONNECT)
-         * take the ippathid from the b2f0 call
-         * register the handler to the ippathid
-         *
-         * Unfortunately, the ConnectionEstablished message gets sent after the
-         * b2f0(CONNECT) call but before the register is handled.
-         *
-         * In order for this race condition to be eliminated, the IUCV Control
-         * Interrupts must be disabled for the above procedure.
-         *
-         * David Kennedy <dkennedy@linuxcare.com>
-         */
-
-	/* Enable everything but IUCV Control messages */
-	iucv_setmask(~(AllInterrupts));
-	messagesDisabled = 1;
-
-	spin_lock_irqsave (&iucv_lock, flags);
-	parm->ipflags1 = (__u8)flags1;
-	b2f0_result = b2f0(CONNECT, parm);
-	memcpy(&local_parm, parm, sizeof(local_parm));
-	release_param(parm);
-	parm = &local_parm;
-	if (!b2f0_result)
-		add_pathid_result = __iucv_add_pathid(parm->ippathid, h);
-	spin_unlock_irqrestore (&iucv_lock, flags);
-
-	if (b2f0_result) {
-		iucv_setmask(~0);
-		messagesDisabled = 0;
-		return b2f0_result;
-	}
-
-	*pathid = parm->ippathid;
-
-	/* Enable everything again */
-	iucv_setmask(IUCVControlInterruptsFlag);
-
-	if (msglim)
-		*msglim = parm->ipmsglim;
-	if (flags1_out)
-		*flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0;
-
-	if (add_pathid_result) {
-		iucv_sever(*pathid, no_memory);
-		printk(KERN_WARNING "%s: add_pathid failed with rc ="
-			" %d\n", __FUNCTION__, add_pathid_result);
-		return(add_pathid_result);
-	}
-
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_purge:
- * @pathid: Path identification number
- * @msgid:  Message ID of message to purge.
- * @srccls: Message class of the message to purge.
- * @audit:  Pointer to an __u32. If not NULL, on return, information about
- *          asynchronous errors that may have affected the normal completion
- *          of this message ist stored at the given location.
- *
- * Cancels a message you have sent.
- * Returns: return code from CP
- */
-int
-iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
-{
-	iparml_purge *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	parm = (iparml_purge *)grab_param();
-
-	parm->ipmsgid = msgid;
-	parm->ippathid = pathid;
-	parm->ipsrccls = srccls;
-	parm->ipflags1 |= (IPSRCCLS | IPFGMID | IPFGPID);
-	b2f0_result = b2f0(PURGE, parm);
-
-	if (!b2f0_result && audit) {
-		memcpy(audit, parm->ipaudit, sizeof(parm->ipaudit));
-		/* parm->ipaudit has only 3 bytes */
-		*audit >>= 8;
-	}
-
-	release_param(parm);
-
-	iucv_debug(1, "b2f0_result = %ld", b2f0_result);
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_query_generic:
- * @want_maxconn: Flag, describing which value is to be returned.
- *
- * Helper function for iucv_query_maxconn() and iucv_query_bufsize().
- *
- * Returns: The buffersize, if want_maxconn is 0; the maximum number of
- *           connections, if want_maxconn is 1 or an error-code < 0 on failure.
- */
-static int
-iucv_query_generic(int want_maxconn)
-{
-	register unsigned long reg0 asm ("0");
-	register unsigned long reg1 asm ("1");
-	iparml_purge *parm = (iparml_purge *)grab_param();
-	int bufsize, maxconn;
-	int ccode;
-
-	/**
-	 * Call b2f0 and store R0 (max buffer size),
-	 * R1 (max connections) and CC.
-	 */
-	reg0 = QUERY;
-	reg1 = virt_to_phys(parm);
-	asm volatile(
-		"	.long	0xb2f01000\n"
-		"	ipm	%0\n"
-		"	srl	%0,28\n"
-		: "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
-	bufsize = reg0;
-	maxconn = reg1;
-	release_param(parm);
-
-	if (ccode)
-		return -EPERM;
-	if (want_maxconn)
-		return maxconn;
-	return bufsize;
-}
-
-/**
- * iucv_query_maxconn:
- *
- * Determines the maximum number of connections thay may be established.
- *
- * Returns: Maximum number of connections that can be.
- */
-ulong
-iucv_query_maxconn(void)
-{
-	return iucv_query_generic(1);
-}
-
-/**
- * iucv_query_bufsize:
- *
- * Determines the size of the external interrupt buffer.
- *
- * Returns: Size of external interrupt buffer.
- */
-ulong
-iucv_query_bufsize (void)
-{
-	return iucv_query_generic(0);
-}
-
-/**
- * iucv_quiesce:
- * @pathid:    Path identification number
- * @user_data: 16-byte user data
- *
- * Temporarily suspends incoming messages on an IUCV path.
- * You can later reactivate the path by invoking the iucv_resume function.
- * Returns: return code from CP
- */
-int
-iucv_quiesce (__u16 pathid, __u8 user_data[16])
-{
-	iparml_control *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	parm = (iparml_control *)grab_param();
-
-	memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-	parm->ippathid = pathid;
-
-	b2f0_result = b2f0(QUIESCE, parm);
-	release_param(parm);
-
-	iucv_debug(1, "b2f0_result = %ld", b2f0_result);
-	iucv_debug(1, "exiting");
-
-	return b2f0_result;
-}
-
-/**
- * iucv_receive:
- * @pathid: Path identification number.
- * @buffer: Address of buffer to receive. Must be below 2G.
- * @buflen: Length of buffer to receive.
- * @msgid:  Specifies the message ID.
- * @trgcls: Specifies target class.
- * @flags1_out: Receives options for path on return.
- *    - IPNORPY (0x10)  Specifies whether a reply is required
- *    - IPPRTY (0x20)   Specifies if you want to send priority message
- *    - IPRMDATA (0x80) Specifies the data is contained in the parameter list
- * @residual_buffer: Receives the address of buffer updated by the number
- *                   of bytes you have received on return.
- * @residual_length: On return, receives one of the following values:
- *    - 0                          If the receive buffer is the same length as
- *                                 the message.
- *    - Remaining bytes in buffer  If the receive buffer is longer than the
- *                                 message.
- *    - Remaining bytes in message If the receive buffer is shorter than the
- *                                 message.
- *
- * This function receives messages that are being sent to you over established
- * paths.
- * Returns: return code from CP IUCV call; If the receive buffer is shorter
- *   than the message, always 5
- *   -EINVAL - buffer address is pointing to NULL
- */
-int
-iucv_receive (__u16 pathid, __u32 msgid, __u32 trgcls,
-	      void *buffer, ulong buflen,
-	      int *flags1_out, ulong * residual_buffer, ulong * residual_length)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-	int moved = 0;	/* number of bytes moved from parmlist to buffer */
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr1 = (__u32) (addr_t) buffer;
-	parm->ipbfln1f = (__u32) ((ulong) buflen);
-	parm->ipmsgid = msgid;
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (IPFGPID | IPFGMID | IPFGMCL);
-
-	b2f0_result = b2f0(RECEIVE, parm);
-
-	if (!b2f0_result || b2f0_result == 5) {
-		if (flags1_out) {
-			iucv_debug(2, "*flags1_out = %d", *flags1_out);
-			*flags1_out = (parm->ipflags1 & (~0x07));
-			iucv_debug(2, "*flags1_out = %d", *flags1_out);
-		}
-
-		if (!(parm->ipflags1 & IPRMDATA)) {	/*msg not in parmlist */
-			if (residual_length)
-				*residual_length = parm->ipbfln1f;
-
-			if (residual_buffer)
-				*residual_buffer = parm->ipbfadr1;
-		} else {
-			moved = min_t (unsigned long, buflen, 8);
-
-			memcpy ((char *) buffer,
-				(char *) &parm->ipbfadr1, moved);
-
-			if (buflen < 8)
-				b2f0_result = 5;
-
-			if (residual_length)
-				*residual_length = abs (buflen - 8);
-
-			if (residual_buffer)
-				*residual_buffer = (ulong) (buffer + moved);
-		}
-	}
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_receive_array
- * Purpose: This function receives messages that are being sent to you
- *          over established paths.
- * Input: pathid - path identification number
- *        buffer - address of array of buffers
- *        buflen - total length of buffers
- *        msgid - specifies the message ID.
- *        trgcls - specifies target class
- * Output:
- *        flags1_out: Options for path.
- *          IPNORPY - 0x10 specifies whether a reply is required
- *          IPPRTY - 0x20 specifies if you want to send priority message
- *         IPRMDATA - 0x80 specifies the data is contained in the parameter list
- *       residual_buffer - address points to the current list entry IUCV
- *                         is working on.
- *       residual_length -
- *              Contains one of the following values, if the receive buffer is:
- *               The same length as the message, this field is zero.
- *               Longer than the message, this field contains the number of
- *                bytes remaining in the buffer.
- *               Shorter than the message, this field contains the residual
- *                count (that is, the number of bytes remaining in the
- *                message that does not fit into the buffer. In this case
- *		  b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
- */
-int
-iucv_receive_array (__u16 pathid,
-		    __u32 msgid, __u32 trgcls,
-		    iucv_array_t * buffer, ulong buflen,
-		    int *flags1_out,
-		    ulong * residual_buffer, ulong * residual_length)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-	int i = 0, moved = 0, need_to_move = 8, dyn_len;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ipbfln1f = (__u32) buflen;
-	parm->ipmsgid = msgid;
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (IPBUFLST | IPFGPID | IPFGMID | IPFGMCL);
-
-	b2f0_result = b2f0(RECEIVE, parm);
-
-	if (!b2f0_result || b2f0_result == 5) {
-
-		if (flags1_out) {
-			iucv_debug(2, "*flags1_out = %d", *flags1_out);
-			*flags1_out = (parm->ipflags1 & (~0x07));
-			iucv_debug(2, "*flags1_out = %d", *flags1_out);
-		}
-
-		if (!(parm->ipflags1 & IPRMDATA)) {	/*msg not in parmlist */
-
-			if (residual_length)
-				*residual_length = parm->ipbfln1f;
-
-			if (residual_buffer)
-				*residual_buffer = parm->ipbfadr1;
-
-		} else {
-			/* copy msg from parmlist to users array. */
-
-			while ((moved < 8) && (moved < buflen)) {
-				dyn_len =
-				    min_t (unsigned int,
-					 (buffer + i)->length, need_to_move);
-
-				memcpy ((char *)((ulong)((buffer + i)->address)),
-					((char *) &parm->ipbfadr1) + moved,
-					dyn_len);
-
-				moved += dyn_len;
-				need_to_move -= dyn_len;
-
-				(buffer + i)->address =
-				    	(__u32)
-				((ulong)(__u8 *) ((ulong)(buffer + i)->address)
-						+ dyn_len);
-
-				(buffer + i)->length -= dyn_len;
-				i++;
-			}
-
-			if (need_to_move)	/* buflen < 8 bytes */
-				b2f0_result = 5;
-
-			if (residual_length)
-				*residual_length = abs (buflen - 8);
-
-			if (residual_buffer) {
-				if (!moved)
-					*residual_buffer = (ulong) buffer;
-				else
-					*residual_buffer =
-					    (ulong) (buffer + (i - 1));
-			}
-
-		}
-	}
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-/**
- * iucv_reject:
- * @pathid: Path identification number.
- * @msgid:  Message ID of the message to reject.
- * @trgcls: Target class of the message to reject.
- * Returns: return code from CP
- *
- * Refuses a specified message. Between the time you are notified of a
- * message and the time that you complete the message, the message may
- * be rejected.
- */
-int
-iucv_reject (__u16 pathid, __u32 msgid, __u32 trgcls)
-{
-	iparml_db *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->ipmsgid = msgid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (IPFGMCL | IPFGMID | IPFGPID);
-
-	b2f0_result = b2f0(REJECT, parm);
-	release_param(parm);
-
-	iucv_debug(1, "b2f0_result = %ld", b2f0_result);
-	iucv_debug(1, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_reply
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- * Input: pathid - path identification number
- *        msgid - specifies the message ID.
- *        trgcls - specifies target class
- *        flags1 - option for path
- *                 IPPRTY- 0x20 - specifies if you want to send priority message
- *        buffer - address of reply buffer
- *        buflen - length of reply buffer
- * Output: ipbfadr2 - Address of buffer updated by the number
- *                    of bytes you have moved.
- *         ipbfln2f - Contains one of the following values:
- *              If the answer buffer is the same length as the reply, this field
- *               contains zero.
- *              If the answer buffer is longer than the reply, this field contains
- *               the number of bytes remaining in the buffer.
- *              If the answer buffer is shorter than the reply, this field contains
- *               a residual count (that is, the number of bytes remianing in the
- *               reply that does not fit into the buffer. In this
- *                case b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
- */
-int
-iucv_reply (__u16 pathid,
-	    __u32 msgid, __u32 trgcls,
-	    int flags1,
-	    void *buffer, ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr2 = (__u32) ((ulong) buffer);
-	parm->ipbfln2f = (__u32) buflen;	/* length of message */
-	parm->ippathid = pathid;
-	parm->ipmsgid = msgid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (__u8) flags1;	/* priority message */
-
-	b2f0_result = b2f0(REPLY, parm);
-
-	if ((!b2f0_result) || (b2f0_result == 5)) {
-		if (ipbfadr2)
-			*ipbfadr2 = parm->ipbfadr2;
-		if (ipbfln2f)
-			*ipbfln2f = parm->ipbfln2f;
-	}
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_reply_array
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- *          The array identifies a list of addresses and lengths of
- *          discontiguous buffers that contains the reply data.
- * Input: pathid - path identification number
- *        msgid - specifies the message ID.
- *        trgcls - specifies target class
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        buffer - address of array of reply buffers
- *        buflen - total length of reply buffers
- * Output: ipbfadr2 - Address of buffer which IUCV is currently working on.
- *         ipbfln2f - Contains one of the following values:
- *              If the answer buffer is the same length as the reply, this field
- *               contains zero.
- *              If the answer buffer is longer than the reply, this field contains
- *               the number of bytes remaining in the buffer.
- *              If the answer buffer is shorter than the reply, this field contains
- *               a residual count (that is, the number of bytes remianing in the
- *               reply that does not fit into the buffer. In this
- *               case b2f0_result = 5.
- * Return: b2f0_result - return code from CP
- *             (-EINVAL) - buffer address is NULL
-*/
-int
-iucv_reply_array (__u16 pathid,
-		  __u32 msgid, __u32 trgcls,
-		  int flags1,
-		  iucv_array_t * buffer,
-		  ulong buflen, ulong * ipbfadr2, ulong * ipbfln2f)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr2 = (__u32) ((ulong) buffer);
-	parm->ipbfln2f = buflen;	/* length of message */
-	parm->ippathid = pathid;
-	parm->ipmsgid = msgid;
-	parm->iptrgcls = trgcls;
-	parm->ipflags1 = (IPANSLST | flags1);
-
-	b2f0_result = b2f0(REPLY, parm);
-
-	if ((!b2f0_result) || (b2f0_result == 5)) {
-
-		if (ipbfadr2)
-			*ipbfadr2 = parm->ipbfadr2;
-		if (ipbfln2f)
-			*ipbfln2f = parm->ipbfln2f;
-	}
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_reply_prmmsg
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- *          Prmmsg signifies the data is moved into the
- *          parameter list.
- * Input: pathid - path identification number
- *        msgid - specifies the message ID.
- *        trgcls - specifies target class
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        prmmsg - 8-bytes of data to be placed into the parameter
- *                 list.
- * Output: NA
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_reply_prmmsg (__u16 pathid,
-		   __u32 msgid, __u32 trgcls, int flags1, __u8 prmmsg[8])
-{
-	iparml_dpl *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	parm = (iparml_dpl *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->ipmsgid = msgid;
-	parm->iptrgcls = trgcls;
-	memcpy(parm->iprmmsg, prmmsg, sizeof (parm->iprmmsg));
-	parm->ipflags1 = (IPRMDATA | flags1);
-
-	b2f0_result = b2f0(REPLY, parm);
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/**
- * iucv_resume:
- * @pathid:    Path identification number
- * @user_data: 16-byte of user data
- *
- * This function restores communication over a quiesced path.
- * Returns: return code from CP
- */
-int
-iucv_resume (__u16 pathid, __u8 user_data[16])
-{
-	iparml_control *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	iucv_debug(1, "pathid = %d", pathid);
-
-	parm = (iparml_control *)grab_param();
-
-	memcpy (parm->ipuser, user_data, sizeof (*user_data));
-	parm->ippathid = pathid;
-
-	b2f0_result = b2f0(RESUME, parm);
-	release_param(parm);
-
-	iucv_debug(1, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send
- * Purpose: sends messages
- * Input: pathid - ushort, pathid
- *        msgid  - ulong *, id of message returned to caller
- *        trgcls - ulong, target message class
- *        srccls - ulong, source message class
- *        msgtag - ulong, message tag
- *	  flags1  - Contains options for this path.
- *		IPPRTY - Ox20 - specifies if you want to send a priority message.
- *        buffer - pointer to buffer
- *        buflen - ulong, length of buffer
- * Output: b2f0_result - return code from b2f0 call
- *         msgid - returns message id
- */
-int
-iucv_send (__u16 pathid, __u32 * msgid,
-	   __u32 trgcls, __u32 srccls,
-	   __u32 msgtag, int flags1, void *buffer, ulong buflen)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipbfln1f = (__u32) buflen;	/* length of message */
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = (IPNORPY | flags1);	/* one way priority message */
-
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send_array
- * Purpose: This function transmits data to another application.
- *          The contents of buffer is the address of the array of
- *          addresses and lengths of discontiguous buffers that hold
- *          the message text. This is a one-way message and the
- *          receiver will not reply to the message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag to be associated witht the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        buffer - address of array of send buffers
- *        buflen - total length of send buffers
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
- */
-int
-iucv_send_array (__u16 pathid,
-		 __u32 * msgid,
-		 __u32 trgcls,
-		 __u32 srccls,
-		 __u32 msgtag, int flags1, iucv_array_t * buffer, ulong buflen)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ipbfln1f = (__u32) buflen;	/* length of message */
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = (IPNORPY | IPBUFLST | flags1);
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send_prmmsg
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a one-way message and the
- *          receiver will not reply to the message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag to be associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        prmmsg - 8-bytes of data to be placed into parameter list
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_send_prmmsg (__u16 pathid,
-		  __u32 * msgid,
-		  __u32 trgcls,
-		  __u32 srccls, __u32 msgtag, int flags1, __u8 prmmsg[8])
-{
-	iparml_dpl *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	parm = (iparml_dpl *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = (IPRMDATA | IPNORPY | flags1);
-	memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
-
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way
- * Purpose: This function transmits data to another application.
- *          Data to be transmitted is in a buffer. The receiver
- *          of the send is expected to reply to the message and
- *          a buffer is provided into which IUCV moves the reply
- *          to this message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        buffer - address of send buffer
- *        buflen - length of send buffer
- *        ansbuf - address of buffer to reply with
- *        anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer or ansbuf address is NULL
- */
-int
-iucv_send2way (__u16 pathid,
-	       __u32 * msgid,
-	       __u32 trgcls,
-	       __u32 srccls,
-	       __u32 msgtag,
-	       int flags1,
-	       void *buffer, ulong buflen, void *ansbuf, ulong anslen)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer || !ansbuf)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ipbfln1f = (__u32) buflen;	/* length of message */
-	parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
-	parm->ipbfln2f = (__u32) anslen;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = flags1;	/* priority message */
-
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_array
- * Purpose: This function transmits data to another application.
- *          The contents of buffer is the address of the array of
- *          addresses and lengths of discontiguous buffers that hold
- *          the message text. The receiver of the send is expected to
- *          reply to the message and a buffer is provided into which
- *          IUCV moves the reply to this message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - spcifies a tag to be associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        buffer - address of array of send buffers
- *        buflen - total length of send buffers
- *        ansbuf - address of buffer to reply with
- *        anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
- */
-int
-iucv_send2way_array (__u16 pathid,
-		     __u32 * msgid,
-		     __u32 trgcls,
-		     __u32 srccls,
-		     __u32 msgtag,
-		     int flags1,
-		     iucv_array_t * buffer,
-		     ulong buflen, iucv_array_t * ansbuf, ulong anslen)
-{
-	iparml_db *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!buffer || !ansbuf)
-		return -EINVAL;
-
-	parm = (iparml_db *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipbfadr1 = (__u32) ((ulong) buffer);
-	parm->ipbfln1f = (__u32) buflen;	/* length of message */
-	parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
-	parm->ipbfln2f = (__u32) anslen;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipflags1 = (IPBUFLST | IPANSLST | flags1);
-	b2f0_result = b2f0(SEND, parm);
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_prmmsg
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a two-way message and the
- *          receiver of the message is expected to reply. A buffer
- *          is provided into which IUCV moves the reply to this
- *          message.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag to be associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        prmmsg - 8-bytes of data to be placed in parameter list
- *        ansbuf - address of buffer to reply with
- *        anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - buffer address is NULL
-*/
-int
-iucv_send2way_prmmsg (__u16 pathid,
-		      __u32 * msgid,
-		      __u32 trgcls,
-		      __u32 srccls,
-		      __u32 msgtag,
-		      ulong flags1, __u8 prmmsg[8], void *ansbuf, ulong anslen)
-{
-	iparml_dpl *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!ansbuf)
-		return -EINVAL;
-
-	parm = (iparml_dpl *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
-	parm->ipbfln2f = (__u32) anslen;
-	parm->ipflags1 = (IPRMDATA | flags1);	/* message in prmlist */
-	memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
-
-	b2f0_result = b2f0(SEND, parm);
-
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-
-	return b2f0_result;
-}
-
-/*
- * Name: iucv_send2way_prmmsg_array
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a two-way message and the
- *          receiver of the message is expected to reply. A buffer
- *          is provided into which IUCV moves the reply to this
- *          message. The contents of ansbuf is the address of the
- *          array of addresses and lengths of discontiguous buffers
- *          that contain the reply.
- * Input: pathid - path identification number
- *        trgcls - specifies target class
- *        srccls - specifies the source message class
- *        msgtag - specifies a tag to be associated with the message
- *        flags1 - option for path
- *                 IPPRTY- specifies if you want to send priority message
- *        prmmsg - 8-bytes of data to be placed into the parameter list
- *        ansbuf - address of buffer to reply with
- *        anslen - length of buffer to reply with
- * Output: msgid - specifies the message ID.
- * Return: b2f0_result - return code from CP
- *         (-EINVAL) - ansbuf address is NULL
- */
-int
-iucv_send2way_prmmsg_array (__u16 pathid,
-			    __u32 * msgid,
-			    __u32 trgcls,
-			    __u32 srccls,
-			    __u32 msgtag,
-			    int flags1,
-			    __u8 prmmsg[8],
-			    iucv_array_t * ansbuf, ulong anslen)
-{
-	iparml_dpl *parm;
-	ulong b2f0_result;
-
-	iucv_debug(2, "entering");
-
-	if (!ansbuf)
-		return -EINVAL;
-
-	parm = (iparml_dpl *)grab_param();
-
-	parm->ippathid = pathid;
-	parm->iptrgcls = trgcls;
-	parm->ipsrccls = srccls;
-	parm->ipmsgtag = msgtag;
-	parm->ipbfadr2 = (__u32) ((ulong) ansbuf);
-	parm->ipbfln2f = (__u32) anslen;
-	parm->ipflags1 = (IPRMDATA | IPANSLST | flags1);
-	memcpy(parm->iprmmsg, prmmsg, sizeof(parm->iprmmsg));
-	b2f0_result = b2f0(SEND, parm);
-	if ((!b2f0_result) && (msgid))
-		*msgid = parm->ipmsgid;
-	release_param(parm);
-
-	iucv_debug(2, "exiting");
-	return b2f0_result;
-}
-
-void
-iucv_setmask_cpuid (void *result)
-{
-        iparml_set_mask *parm;
-
-        iucv_debug(1, "entering");
-        parm = (iparml_set_mask *)grab_param();
-        parm->ipmask = *((__u8*)result);
-        *((ulong *)result) = b2f0(SETMASK, parm);
-        release_param(parm);
-
-        iucv_debug(1, "b2f0_result = %ld", *((ulong *)result));
-        iucv_debug(1, "exiting");
-}
-
-/*
- * Name: iucv_setmask
- * Purpose: This function enables or disables the following IUCV
- *          external interruptions: Nonpriority and priority message
- *          interrupts, nonpriority and priority reply interrupts.
- * Input: SetMaskFlag - options for interrupts
- *           0x80 - Nonpriority_MessagePendingInterruptsFlag
- *           0x40 - Priority_MessagePendingInterruptsFlag
- *           0x20 - Nonpriority_MessageCompletionInterruptsFlag
- *           0x10 - Priority_MessageCompletionInterruptsFlag
- *           0x08 - IUCVControlInterruptsFlag
- * Output: NA
- * Return: b2f0_result - return code from CP
-*/
-int
-iucv_setmask (int SetMaskFlag)
-{
-	union {
-		ulong result;
-		__u8  param;
-	} u;
-	int cpu;
-
-	u.param = SetMaskFlag;
-	cpu = get_cpu();
-	smp_call_function_on(iucv_setmask_cpuid, &u, 0, 1, iucv_cpuid);
-	put_cpu();
-
-	return u.result;
-}
-
-/**
- * iucv_sever:
- * @pathid:    Path identification number
- * @user_data: 16-byte of user data
- *
- * This function terminates an iucv path.
- * Returns: return code from CP
- */
-int
-iucv_sever(__u16 pathid, __u8 user_data[16])
-{
-	iparml_control *parm;
-	ulong b2f0_result = 0;
-
-	iucv_debug(1, "entering");
-	parm = (iparml_control *)grab_param();
-
-	memcpy(parm->ipuser, user_data, sizeof(parm->ipuser));
-	parm->ippathid = pathid;
-
-	b2f0_result = b2f0(SEVER, parm);
-
-	if (!b2f0_result)
-		iucv_remove_pathid(pathid);
-	release_param(parm);
-
-	iucv_debug(1, "exiting");
-	return b2f0_result;
-}
-
-/*
- * Interrupt Handlers
- *******************************************************************************/
-
-/**
- * iucv_irq_handler:
- * @regs: Current registers
- * @code: irq code
- *
- * Handles external interrupts coming in from CP.
- * Places the interrupt buffer on a queue and schedules iucv_tasklet_handler().
- */
-static void
-iucv_irq_handler(__u16 code)
-{
-	iucv_irqdata *irqdata;
-
-	irqdata = kmalloc(sizeof(iucv_irqdata), GFP_ATOMIC);
-	if (!irqdata) {
-		printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__);
-		return;
-	}
-
-	memcpy(&irqdata->data, iucv_external_int_buffer,
-	       sizeof(iucv_GeneralInterrupt));
-
-	spin_lock(&iucv_irq_queue_lock);
-	list_add_tail(&irqdata->queue, &iucv_irq_queue);
-	spin_unlock(&iucv_irq_queue_lock);
-
-	tasklet_schedule(&iucv_tasklet);
-}
-
-/**
- * iucv_do_int:
- * @int_buf: Pointer to copy of external interrupt buffer
- *
- * The workhorse for handling interrupts queued by iucv_irq_handler().
- * This function is called from the bottom half iucv_tasklet_handler().
- */
-static void
-iucv_do_int(iucv_GeneralInterrupt * int_buf)
-{
-	handler *h = NULL;
-	struct list_head *lh;
-	ulong flags;
-	iucv_interrupt_ops_t *interrupt = NULL;	/* interrupt addresses */
-	__u8 temp_buff1[24], temp_buff2[24];	/* masked handler id. */
-	int rc = 0, j = 0;
-	__u8 no_listener[16] = "NO LISTENER";
-
-	iucv_debug(2, "entering, pathid %d, type %02X",
-		 int_buf->ippathid, int_buf->iptype);
-	iucv_dumpit("External Interrupt Buffer:",
-		    int_buf, sizeof(iucv_GeneralInterrupt));
-
-	ASCEBC (no_listener, 16);
-
-	if (int_buf->iptype != 01) {
-		if ((int_buf->ippathid) > (max_connections - 1)) {
-			printk(KERN_WARNING "%s: Got interrupt with pathid %d"
-			       " > max_connections (%ld)\n", __FUNCTION__,
-			       int_buf->ippathid, max_connections - 1);
-		} else {
-			h = iucv_pathid_table[int_buf->ippathid];
-			interrupt = h->interrupt_table;
-			iucv_dumpit("Handler:", h, sizeof(handler));
-		}
-	}
-
-	/* end of if statement */
-	switch (int_buf->iptype) {
-		case 0x01:		/* connection pending */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			spin_lock_irqsave(&iucv_lock, flags);
-			list_for_each(lh, &iucv_handler_table) {
-				h = list_entry(lh, handler, list);
-				memcpy(temp_buff1, &(int_buf->ipvmid), 24);
-				memcpy(temp_buff2, &(h->id.userid), 24);
-				for (j = 0; j < 24; j++) {
-					temp_buff1[j] &= (h->id.mask)[j];
-					temp_buff2[j] &= (h->id.mask)[j];
-				}
-
-				iucv_dumpit("temp_buff1:",
-					    temp_buff1, sizeof(temp_buff1));
-				iucv_dumpit("temp_buff2",
-					    temp_buff2, sizeof(temp_buff2));
-
-				if (!memcmp (temp_buff1, temp_buff2, 24)) {
-
-					iucv_debug(2,
-						   "found a matching handler");
-					break;
-				} else
-					h = NULL;
-			}
-			spin_unlock_irqrestore (&iucv_lock, flags);
-			if (h) {
-				/* ADD PATH TO PATHID TABLE */
-				rc = iucv_add_pathid(int_buf->ippathid, h);
-				if (rc) {
-					iucv_sever (int_buf->ippathid,
-						    no_listener);
-					iucv_debug(1,
-						   "add_pathid failed, rc = %d",
-						   rc);
-				} else {
-					interrupt = h->interrupt_table;
-					if (interrupt->ConnectionPending) {
-						EBCASC (int_buf->ipvmid, 8);
-						interrupt->ConnectionPending(
-							(iucv_ConnectionPending *)int_buf,
-							h->pgm_data);
-					} else
-						iucv_sever(int_buf->ippathid,
-							   no_listener);
-				}
-			} else
-				iucv_sever(int_buf->ippathid, no_listener);
-			break;
-
-		case 0x02:		/*connection complete */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			if (h) {
-				if (interrupt->ConnectionComplete)
-				{
-					interrupt->ConnectionComplete(
-						(iucv_ConnectionComplete *)int_buf,
-						h->pgm_data);
-				}
-				else
-					iucv_debug(1,
-						   "ConnectionComplete not called");
-			} else
-				iucv_sever(int_buf->ippathid, no_listener);
-			break;
-
-		case 0x03:		/* connection severed */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			if (h) {
-				if (interrupt->ConnectionSevered)
-					interrupt->ConnectionSevered(
-						(iucv_ConnectionSevered *)int_buf,
-						h->pgm_data);
-
-				else
-					iucv_sever (int_buf->ippathid, no_listener);
-			} else
-				iucv_sever(int_buf->ippathid, no_listener);
-			break;
-
-		case 0x04:		/* connection quiesced */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			if (h) {
-				if (interrupt->ConnectionQuiesced)
-					interrupt->ConnectionQuiesced(
-						(iucv_ConnectionQuiesced *)int_buf,
-						h->pgm_data);
-				else
-					iucv_debug(1,
-						   "ConnectionQuiesced not called");
-			}
-			break;
-
-		case 0x05:		/* connection resumed */
-			if (messagesDisabled) {
-			    iucv_setmask(~0);
-			    messagesDisabled = 0;
-			}
-			if (h) {
-				if (interrupt->ConnectionResumed)
-					interrupt->ConnectionResumed(
-						(iucv_ConnectionResumed *)int_buf,
-						h->pgm_data);
-				else
-					iucv_debug(1,
-						   "ConnectionResumed not called");
-			}
-			break;
-
-		case 0x06:		/* priority message complete */
-		case 0x07:		/* nonpriority message complete */
-			if (h) {
-				if (interrupt->MessageComplete)
-					interrupt->MessageComplete(
-						(iucv_MessageComplete *)int_buf,
-						h->pgm_data);
-				else
-					iucv_debug(2,
-						   "MessageComplete not called");
-			}
-			break;
-
-		case 0x08:		/* priority message pending  */
-		case 0x09:		/* nonpriority message pending  */
-			if (h) {
-				if (interrupt->MessagePending)
-					interrupt->MessagePending(
-						(iucv_MessagePending *) int_buf,
-						h->pgm_data);
-				else
-					iucv_debug(2,
-						   "MessagePending not called");
-			}
-			break;
-		default:		/* unknown iucv type */
-			printk(KERN_WARNING "%s: unknown iucv interrupt\n",
-			       __FUNCTION__);
-			break;
-	}			/* end switch */
-
-	iucv_debug(2, "exiting pathid %d, type %02X",
-		 int_buf->ippathid, int_buf->iptype);
-
-	return;
-}
-
-/**
- * iucv_tasklet_handler:
- *
- * This function loops over the queue of irq buffers and runs iucv_do_int()
- * on every queue element.
- */
-static void
-iucv_tasklet_handler(unsigned long ignored)
-{
-	struct list_head head;
-	struct list_head *next;
-	ulong  flags;
-
-	spin_lock_irqsave(&iucv_irq_queue_lock, flags);
-	list_add(&head, &iucv_irq_queue);
-	list_del_init(&iucv_irq_queue);
-	spin_unlock_irqrestore (&iucv_irq_queue_lock, flags);
-
-	next = head.next;
-	while (next != &head) {
-		iucv_irqdata *p = list_entry(next, iucv_irqdata, queue);
-
-		next = next->next;
-		iucv_do_int(&p->data);
-		kfree(p);
-	}
-
-	return;
-}
-
-subsys_initcall(iucv_init);
-module_exit(iucv_exit);
-
-/**
- * Export all public stuff
- */
-EXPORT_SYMBOL (iucv_bus);
-EXPORT_SYMBOL (iucv_root);
-EXPORT_SYMBOL (iucv_accept);
-EXPORT_SYMBOL (iucv_connect);
-#if 0
-EXPORT_SYMBOL (iucv_purge);
-EXPORT_SYMBOL (iucv_query_maxconn);
-EXPORT_SYMBOL (iucv_query_bufsize);
-EXPORT_SYMBOL (iucv_quiesce);
-#endif
-EXPORT_SYMBOL (iucv_receive);
-#if 0
-EXPORT_SYMBOL (iucv_receive_array);
-#endif
-EXPORT_SYMBOL (iucv_reject);
-#if 0
-EXPORT_SYMBOL (iucv_reply);
-EXPORT_SYMBOL (iucv_reply_array);
-EXPORT_SYMBOL (iucv_resume);
-#endif
-EXPORT_SYMBOL (iucv_reply_prmmsg);
-EXPORT_SYMBOL (iucv_send);
-EXPORT_SYMBOL (iucv_send2way);
-EXPORT_SYMBOL (iucv_send2way_array);
-EXPORT_SYMBOL (iucv_send2way_prmmsg);
-EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
-#if 0
-EXPORT_SYMBOL (iucv_send_array);
-EXPORT_SYMBOL (iucv_send_prmmsg);
-EXPORT_SYMBOL (iucv_setmask);
-#endif
-EXPORT_SYMBOL (iucv_sever);
-EXPORT_SYMBOL (iucv_register_program);
-EXPORT_SYMBOL (iucv_unregister_program);

+ 0 - 849
drivers/s390/net/iucv.h

@@ -1,849 +0,0 @@
-/*
- *  drivers/s390/net/iucv.h
- *    IUCV base support.
- *
- *  S390 version
- *    Copyright (C) 2000 IBM Corporation
- *    Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
- *		Xenia Tkatschow (xenia@us.ibm.com)
- *
- *
- * Functionality:
- * To explore any of the IUCV functions, one must first register
- * their program using iucv_register_program(). Once your program has
- * successfully completed a register, it can exploit the other functions.
- * For furthur reference on all IUCV functionality, refer to the
- * CP Programming Services book, also available on the web
- * thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
- *
- *      Definition of Return Codes
- *      -All positive return codes including zero are reflected back
- *       from CP except for iucv_register_program. The definition of each
- *       return code can be found in CP Programming Services book.
- *       Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
- *      - Return Code of:
- *             (-EINVAL) Invalid value
- *             (-ENOMEM) storage allocation failed
- *	pgmask defined in iucv_register_program will be set depending on input
- *	paramters.
- *
- */
-
-#include <linux/types.h>
-#include <asm/debug.h>
-
-/**
- * Debug Facility stuff
- */
-#define IUCV_DBF_SETUP_NAME "iucv_setup"
-#define IUCV_DBF_SETUP_LEN 32
-#define IUCV_DBF_SETUP_PAGES 2
-#define IUCV_DBF_SETUP_NR_AREAS 1
-#define IUCV_DBF_SETUP_LEVEL 3
-
-#define IUCV_DBF_DATA_NAME "iucv_data"
-#define IUCV_DBF_DATA_LEN 128
-#define IUCV_DBF_DATA_PAGES 2
-#define IUCV_DBF_DATA_NR_AREAS 1
-#define IUCV_DBF_DATA_LEVEL 2
-
-#define IUCV_DBF_TRACE_NAME "iucv_trace"
-#define IUCV_DBF_TRACE_LEN 16
-#define IUCV_DBF_TRACE_PAGES 4
-#define IUCV_DBF_TRACE_NR_AREAS 1
-#define IUCV_DBF_TRACE_LEVEL 3
-
-#define IUCV_DBF_TEXT(name,level,text) \
-	do { \
-		debug_text_event(iucv_dbf_##name,level,text); \
-	} while (0)
-
-#define IUCV_DBF_HEX(name,level,addr,len) \
-	do { \
-		debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
-	} while (0)
-
-DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
-
-#define IUCV_DBF_TEXT_(name,level,text...)				\
-	do {								\
-		char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf);	\
-		sprintf(iucv_dbf_txt_buf, text);		  	\
-		debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \
-		put_cpu_var(iucv_dbf_txt_buf);				\
-	} while (0)
-
-#define IUCV_DBF_SPRINTF(name,level,text...) \
-	do { \
-		debug_sprintf_event(iucv_dbf_trace, level, ##text ); \
-		debug_sprintf_event(iucv_dbf_trace, level, text ); \
-	} while (0)
-
-/**
- * some more debug stuff
- */
-#define IUCV_HEXDUMP16(importance,header,ptr) \
-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-		   *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
-		   *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
-		   *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
-		   *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
-		   *(((char*)ptr)+12),*(((char*)ptr)+13), \
-		   *(((char*)ptr)+14),*(((char*)ptr)+15)); \
-PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-		   "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-		   *(((char*)ptr)+16),*(((char*)ptr)+17), \
-		   *(((char*)ptr)+18),*(((char*)ptr)+19), \
-		   *(((char*)ptr)+20),*(((char*)ptr)+21), \
-		   *(((char*)ptr)+22),*(((char*)ptr)+23), \
-		   *(((char*)ptr)+24),*(((char*)ptr)+25), \
-		   *(((char*)ptr)+26),*(((char*)ptr)+27), \
-		   *(((char*)ptr)+28),*(((char*)ptr)+29), \
-		   *(((char*)ptr)+30),*(((char*)ptr)+31));
-
-static inline void
-iucv_hex_dump(unsigned char *buf, size_t len)
-{
-	size_t i;
-
-	for (i = 0; i < len; i++) {
-		if (i && !(i % 16))
-			printk("\n");
-		printk("%02x ", *(buf + i));
-	}
-	printk("\n");
-}
-/**
- * end of debug stuff
- */
-
-#define uchar  unsigned char
-#define ushort unsigned short
-#define ulong  unsigned long
-#define iucv_handle_t void *
-
-/* flags1:
- * All flags are defined in the field IPFLAGS1 of each function
- * and can be found in CP Programming Services.
- * IPLOCAL  - Indicates the connect can only be satisfied on the
- *            local system
- * IPPRTY   - Indicates a priority message
- * IPQUSCE  - Indicates you do not want to receive messages on a
- *            path until an iucv_resume is issued
- * IPRMDATA - Indicates that the message is in the parameter list
- */
-#define IPLOCAL   	0x01
-#define IPPRTY         	0x20
-#define IPQUSCE        	0x40
-#define IPRMDATA       	0x80
-
-/* flags1_out:
- * All flags are defined in the output field of IPFLAGS1 for each function
- * and can be found in CP Programming Services.
- * IPNORPY - Specifies this is a one-way message and no reply is expected.
- * IPPRTY   - Indicates a priority message is permitted. Defined in flags1.
- */
-#define IPNORPY         0x10
-
-#define Nonpriority_MessagePendingInterruptsFlag         0x80
-#define Priority_MessagePendingInterruptsFlag            0x40
-#define Nonpriority_MessageCompletionInterruptsFlag      0x20
-#define Priority_MessageCompletionInterruptsFlag         0x10
-#define IUCVControlInterruptsFlag                        0x08
-#define AllInterrupts                                    0xf8
-/*
- * Mapping of external interrupt buffers should be used with the corresponding
- * interrupt types.
- * Names: iucv_ConnectionPending    ->  connection pending
- *        iucv_ConnectionComplete   ->  connection complete
- *        iucv_ConnectionSevered    ->  connection severed
- *        iucv_ConnectionQuiesced   ->  connection quiesced
- *        iucv_ConnectionResumed    ->  connection resumed
- *        iucv_MessagePending       ->  message pending
- *        iucv_MessageComplete      ->  message complete
- */
-typedef struct {
-	u16 ippathid;
-	uchar ipflags1;
-	uchar iptype;
-	u16 ipmsglim;
-	u16 res1;
-	uchar ipvmid[8];
-	uchar ipuser[16];
-	u32 res3;
-	uchar ippollfg;
-	uchar res4[3];
-} iucv_ConnectionPending;
-
-typedef struct {
-	u16 ippathid;
-	uchar ipflags1;
-	uchar iptype;
-	u16 ipmsglim;
-	u16 res1;
-	uchar res2[8];
-	uchar ipuser[16];
-	u32 res3;
-	uchar ippollfg;
-	uchar res4[3];
-} iucv_ConnectionComplete;
-
-typedef struct {
-	u16 ippathid;
-	uchar res1;
-	uchar iptype;
-	u32 res2;
-	uchar res3[8];
-	uchar ipuser[16];
-	u32 res4;
-	uchar ippollfg;
-	uchar res5[3];
-} iucv_ConnectionSevered;
-
-typedef struct {
-	u16 ippathid;
-	uchar res1;
-	uchar iptype;
-	u32 res2;
-	uchar res3[8];
-	uchar ipuser[16];
-	u32 res4;
-	uchar ippollfg;
-	uchar res5[3];
-} iucv_ConnectionQuiesced;
-
-typedef struct {
-	u16 ippathid;
-	uchar res1;
-	uchar iptype;
-	u32 res2;
-	uchar res3[8];
-	uchar ipuser[16];
-	u32 res4;
-	uchar ippollfg;
-	uchar res5[3];
-} iucv_ConnectionResumed;
-
-typedef struct {
-	u16 ippathid;
-	uchar ipflags1;
-	uchar iptype;
-	u32 ipmsgid;
-	u32 iptrgcls;
-	union u2 {
-		u32 iprmmsg1_u32;
-		uchar iprmmsg1[4];
-	} ln1msg1;
-	union u1 {
-		u32 ipbfln1f;
-		uchar iprmmsg2[4];
-	} ln1msg2;
-	u32 res1[3];
-	u32 ipbfln2f;
-	uchar ippollfg;
-	uchar res2[3];
-} iucv_MessagePending;
-
-typedef struct {
-	u16 ippathid;
-	uchar ipflags1;
-	uchar iptype;
-	u32 ipmsgid;
-	u32 ipaudit;
-	uchar iprmmsg[8];
-	u32 ipsrccls;
-	u32 ipmsgtag;
-	u32 res;
-	u32 ipbfln2f;
-	uchar ippollfg;
-	uchar res2[3];
-} iucv_MessageComplete;
-
-/*
- * iucv_interrupt_ops_t: Is a vector of functions that handle
- * IUCV interrupts.
- * Parameter list:
- *         eib - is a pointer to a 40-byte area described
- *               with one of the structures above.
- *         pgm_data - this data is strictly for the
- *                    interrupt handler that is passed by
- *                    the application. This may be an address
- *                    or token.
-*/
-typedef struct {
-	void (*ConnectionPending) (iucv_ConnectionPending * eib,
-				   void *pgm_data);
-	void (*ConnectionComplete) (iucv_ConnectionComplete * eib,
-				    void *pgm_data);
-	void (*ConnectionSevered) (iucv_ConnectionSevered * eib,
-				   void *pgm_data);
-	void (*ConnectionQuiesced) (iucv_ConnectionQuiesced * eib,
-				    void *pgm_data);
-	void (*ConnectionResumed) (iucv_ConnectionResumed * eib,
-				   void *pgm_data);
-	void (*MessagePending) (iucv_MessagePending * eib, void *pgm_data);
-	void (*MessageComplete) (iucv_MessageComplete * eib, void *pgm_data);
-} iucv_interrupt_ops_t;
-
-/*
- *iucv_array_t : Defines buffer array.
- * Inside the array may be 31- bit addresses and 31-bit lengths.
-*/
-typedef struct {
-	u32 address;
-	u32 length;
-} iucv_array_t __attribute__ ((aligned (8)));
-
-extern struct bus_type iucv_bus;
-extern struct device *iucv_root;
-
-/*   -prototypes-    */
-/*
- * Name: iucv_register_program
- * Purpose: Registers an application with IUCV
- * Input: prmname - user identification
- *        userid  - machine identification
- *        pgmmask - indicates which bits in the prmname and userid combined will be
- *  		    used to determine who is given control
- *        ops     - address of vector of interrupt handlers
- *        pgm_data- application data passed to interrupt handlers
- * Output: NA
- * Return: address of handler
- *         (0) - Error occurred, registration not completed.
- * NOTE: Exact cause of failure will be recorded in syslog.
-*/
-iucv_handle_t iucv_register_program (uchar pgmname[16],
-				     uchar userid[8],
-				     uchar pgmmask[24],
-				     iucv_interrupt_ops_t * ops,
-				     void *pgm_data);
-
-/*
- * Name: iucv_unregister_program
- * Purpose: Unregister application with IUCV
- * Input: address of handler
- * Output: NA
- * Return: (0) - Normal return
- *         (-EINVAL) - Internal error, wild pointer
-*/
-int iucv_unregister_program (iucv_handle_t handle);
-
-/*
- * Name: iucv_accept
- * Purpose: This function is issued after the user receives a Connection Pending external
- *          interrupt and now wishes to complete the IUCV communication path.
- * Input:  pathid - u16 , Path identification number
- *         msglim_reqstd - u16, The number of outstanding messages requested.
- *         user_data - uchar[16], Data specified by the iucv_connect function.
- *	   flags1 - int, Contains options for this path.
- *           -IPPRTY   - 0x20- Specifies if you want to send priority message.
- *           -IPRMDATA - 0x80, Specifies whether your program can handle a message
- *            	in  the parameter list.
- *           -IPQUSCE  - 0x40, Specifies whether you want to quiesce the path being
- *		established.
- *         handle - iucv_handle_t, Address of handler.
- *         pgm_data - void *, Application data passed to interrupt handlers.
- *         flags1_out - int * Contains information about the path
- *           - IPPRTY - 0x20, Indicates you may send priority messages.
- *         msglim - *u16, Number of outstanding messages.
- * Output: return code from CP IUCV call.
-*/
-
-int iucv_accept (u16 pathid,
-		 u16 msglim_reqstd,
-		 uchar user_data[16],
-		 int flags1,
-		 iucv_handle_t handle,
-		 void *pgm_data, int *flags1_out, u16 * msglim);
-
-/*
- * Name: iucv_connect
- * Purpose: This function establishes an IUCV path. Although the connect may complete
- *	    successfully, you are not able to use the path until you receive an IUCV
- *          Connection Complete external interrupt.
- * Input: pathid - u16 *, Path identification number
- *        msglim_reqstd - u16, Number of outstanding messages requested
- *        user_data - uchar[16], 16-byte user data
- *	  userid - uchar[8], User identification
- *        system_name - uchar[8], 8-byte identifying the system name
- *	  flags1 - int, Contains options for this path.
- *          -IPPRTY -   0x20, Specifies if you want to send priority message.
- *          -IPRMDATA - 0x80, Specifies whether your program can handle a message
- *            	 in  the parameter list.
- *          -IPQUSCE -  0x40, Specifies whether you want to quiesce the path being
- *		established.
- *          -IPLOCAL -  0X01, Allows an application to force the partner to be on
- *		the local system. If local is specified then target class cannot be
- *		specified.
- *        flags1_out - int * Contains information about the path
- *           - IPPRTY - 0x20, Indicates you may send priority messages.
- *        msglim - * u16, Number of outstanding messages
- *        handle - iucv_handle_t, Address of handler
- *        pgm_data - void *, Application data passed to interrupt handlers
- * Output: return code from CP IUCV call
- *         rc - return code from iucv_declare_buffer
- *         -EINVAL - Invalid handle passed by application
- *         -EINVAL - Pathid address is NULL
- *         add_pathid_result - Return code from internal function add_pathid
-*/
-int
-    iucv_connect (u16 * pathid,
-		  u16 msglim_reqstd,
-		  uchar user_data[16],
-		  uchar userid[8],
-		  uchar system_name[8],
-		  int flags1,
-		  int *flags1_out,
-		  u16 * msglim, iucv_handle_t handle, void *pgm_data);
-
-/*
- * Name: iucv_purge
- * Purpose: This function cancels a message that you have sent.
- * Input: pathid - Path identification number.
- *        msgid - Specifies the message ID of the message to be purged.
- *        srccls - Specifies the source message class.
- * Output: audit - Contains information about asynchronous error
- *                 that may have affected the normal completion
- *                 of this message.
- * Return: Return code from CP IUCV call.
-*/
-int iucv_purge (u16 pathid, u32 msgid, u32 srccls, __u32 *audit);
-/*
- * Name: iucv_query_maxconn
- * Purpose: This function determines the maximum number of communication paths you
- *	    may establish.
- * Return:  maxconn - ulong, Maximum number of connection the virtual machine may
- *          establish.
-*/
-ulong iucv_query_maxconn (void);
-
-/*
- * Name: iucv_query_bufsize
- * Purpose: This function determines how large an external interrupt
- *          buffer IUCV requires to store information.
- * Return:  bufsize - ulong, Size of external interrupt buffer.
- */
-ulong iucv_query_bufsize (void);
-
-/*
- * Name: iucv_quiesce
- * Purpose: This function temporarily suspends incoming messages on an
- *          IUCV path. You can later reactivate the path by invoking
- *          the iucv_resume function.
- * Input: pathid - Path identification number
- *        user_data  - 16-bytes of user data
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_quiesce (u16 pathid, uchar user_data[16]);
-
-/*
- * Name: iucv_receive
- * Purpose: This function receives messages that are being sent to you
- *          over established paths. Data will be returned in buffer for length of
- *          buflen.
- * Input:
- *       pathid - Path identification number.
- *       buffer - Address of buffer to receive.
- *       buflen - Length of buffer to receive.
- *       msgid - Specifies the message ID.
- *       trgcls - Specifies target class.
- * Output:
- *	 flags1_out: int *, Contains information about this path.
- *         IPNORPY - 0x10 Specifies this is a one-way message and no reply is
- *	   expected.
- *         IPPRTY  - 0x20 Specifies if you want to send priority message.
- *         IPRMDATA - 0x80 specifies the data is contained in the parameter list
- *       residual_buffer - address of buffer updated by the number
- *                         of bytes you have received.
- *       residual_length -
- *              Contains one of the following values, if the receive buffer is:
- *               The same length as the message, this field is zero.
- *               Longer than the message, this field contains the number of
- *                bytes remaining in the buffer.
- *               Shorter than the message, this field contains the residual
- *                count (that is, the number of bytes remaining in the
- *                message that does not fit into the buffer. In this
- *                case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - buffer address is pointing to NULL
-*/
-int iucv_receive (u16 pathid,
-		  u32 msgid,
-		  u32 trgcls,
-		  void *buffer,
-		  ulong buflen,
-		  int *flags1_out,
-		  ulong * residual_buffer, ulong * residual_length);
-
- /*
-  * Name: iucv_receive_array
-  * Purpose: This function receives messages that are being sent to you
-  *          over established paths. Data will be returned in first buffer for
-  *          length of first buffer.
-  * Input: pathid - Path identification number.
-  *        msgid - specifies the message ID.
-  *        trgcls - Specifies target class.
-  *        buffer - Address of array of buffers.
-  *        buflen - Total length of buffers.
-  * Output:
-  *        flags1_out: int *, Contains information about this path.
-  *          IPNORPY - 0x10 Specifies this is a one-way message and no reply is
-  *          expected.
-  *          IPPRTY  - 0x20 Specifies if you want to send priority message.
-  *          IPRMDATA - 0x80 specifies the data is contained in the parameter list
-  *       residual_buffer - address points to the current list entry IUCV
-  *                         is working on.
-  *       residual_length -
-  *              Contains one of the following values, if the receive buffer is:
-  *               The same length as the message, this field is zero.
-  *               Longer than the message, this field contains the number of
-  *                bytes remaining in the buffer.
-  *               Shorter than the message, this field contains the residual
-  *                count (that is, the number of bytes remaining in the
-  *                message that does not fit into the buffer. In this
-  *                case b2f0_result = 5.
-  * Return: Return code from CP IUCV call.
-  *         (-EINVAL) - Buffer address is NULL.
-  */
-int iucv_receive_array (u16 pathid,
-			u32 msgid,
-			u32 trgcls,
-			iucv_array_t * buffer,
-			ulong buflen,
-			int *flags1_out,
-			ulong * residual_buffer, ulong * residual_length);
-
-/*
- * Name: iucv_reject
- * Purpose: The reject function refuses a specified message. Between the
- *          time you are notified of a message and the time that you
- *          complete the message, the message may be rejected.
- * Input: pathid - Path identification number.
- *        msgid - Specifies the message ID.
- *        trgcls - Specifies target class.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_reject (u16 pathid, u32 msgid, u32 trgcls);
-
-/*
- * Name: iucv_reply
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- * Input: pathid - Path identification number.
- *        msgid - Specifies the message ID.
- *        trgcls - Specifies target class.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20, Specifies if you want to send priority message.
- *        buffer - Address of reply buffer.
- *        buflen - Length of reply buffer.
- * Output: residual_buffer - Address of buffer updated by the number
- *                    of bytes you have moved.
- *         residual_length - Contains one of the following values:
- *		If the answer buffer is the same length as the reply, this field
- *		 contains zero.
- *		If the answer buffer is longer than the reply, this field contains
- *		 the number of bytes remaining in the buffer.
- *		If the answer buffer is shorter than the reply, this field contains
- *		 a residual count (that is, the number of bytes remianing in the
- *		 reply that does not fit into the buffer. In this
- *               case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_reply (u16 pathid,
-		u32 msgid,
-		u32 trgcls,
-		int flags1,
-		void *buffer, ulong buflen, ulong * residual_buffer,
-		ulong * residual_length);
-
-/*
- * Name: iucv_reply_array
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- *          The array identifies a list of addresses and lengths of
- *          discontiguous buffers that contains the reply data.
- * Input: pathid - Path identification number
- *        msgid - Specifies the message ID.
- *        trgcls - Specifies target class.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20, Specifies if you want to send priority message.
- *        buffer - Address of array of reply buffers.
- *        buflen - Total length of reply buffers.
- * Output: residual_buffer - Address of buffer which IUCV is currently working on.
- *         residual_length - Contains one of the following values:
- *              If the answer buffer is the same length as the reply, this field
- *               contains zero.
- *              If the answer buffer is longer than the reply, this field contains
- *               the number of bytes remaining in the buffer.
- *              If the answer buffer is shorter than the reply, this field contains
- *               a residual count (that is, the number of bytes remianing in the
- *               reply that does not fit into the buffer. In this
- *               case b2f0_result = 5.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_reply_array (u16 pathid,
-		      u32 msgid,
-		      u32 trgcls,
-		      int flags1,
-		      iucv_array_t * buffer,
-		      ulong buflen, ulong * residual_address,
-		      ulong * residual_length);
-
-/*
- * Name: iucv_reply_prmmsg
- * Purpose: This function responds to the two-way messages that you
- *          receive. You must identify completely the message to
- *          which you wish to reply. ie, pathid, msgid, and trgcls.
- *          Prmmsg signifies the data is moved into the
- *          parameter list.
- * Input: pathid - Path identification number.
- *        msgid - Specifies the message ID.
- *        trgcls - Specifies target class.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into the parameter.
- *                 list.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_reply_prmmsg (u16 pathid,
-		       u32 msgid, u32 trgcls, int flags1, uchar prmmsg[8]);
-
-/*
- * Name: iucv_resume
- * Purpose: This function restores communications over a quiesced path
- * Input: pathid - Path identification number.
- *        user_data  - 16-bytes of user data.
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_resume (u16 pathid, uchar user_data[16]);
-
-/*
- * Name: iucv_send
- * Purpose: This function transmits data to another application.
- *          Data to be transmitted is in a buffer and this is a
- *          one-way message and the receiver will not reply to the
- *          message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Address of send buffer.
- *        buflen - Length of send buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send (u16 pathid,
-	       u32 * msgid,
-	       u32 trgcls,
-	       u32 srccls, u32 msgtag, int flags1, void *buffer, ulong buflen);
-
-/*
- * Name: iucv_send_array
- * Purpose: This function transmits data to another application.
- *          The contents of buffer is the address of the array of
- *          addresses and lengths of discontiguous buffers that hold
- *          the message text. This is a one-way message and the
- *          receiver will not reply to the message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated witht the message.
- *        flags1 - Option for path.
- *          IPPRTY- specifies if you want to send priority message.
- *        buffer - Address of array of send buffers.
- *        buflen - Total length of send buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send_array (u16 pathid,
-		     u32 * msgid,
-		     u32 trgcls,
-		     u32 srccls,
-		     u32 msgtag,
-		     int flags1, iucv_array_t * buffer, ulong buflen);
-
-/*
- * Name: iucv_send_prmmsg
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a one-way message and the
- *          receiver will not reply to the message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into parameter list.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
-*/
-int iucv_send_prmmsg (u16 pathid,
-		      u32 * msgid,
-		      u32 trgcls,
-		      u32 srccls, u32 msgtag, int flags1, uchar prmmsg[8]);
-
-/*
- * Name: iucv_send2way
- * Purpose: This function transmits data to another application.
- *          Data to be transmitted is in a buffer. The receiver
- *          of the send is expected to reply to the message and
- *          a buffer is provided into which IUCV moves the reply
- *          to this message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Address of send buffer.
- *        buflen - Length of send buffer.
- *        ansbuf - Address of buffer into which IUCV moves the reply of
- *                 this message.
- *        anslen - Address of length of buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer or ansbuf address is NULL.
-*/
-int iucv_send2way (u16 pathid,
-		   u32 * msgid,
-		   u32 trgcls,
-		   u32 srccls,
-		   u32 msgtag,
-		   int flags1,
-		   void *buffer, ulong buflen, void *ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_array
- * Purpose: This function transmits data to another application.
- *          The contents of buffer is the address of the array of
- *          addresses and lengths of discontiguous buffers that hold
- *          the message text. The receiver of the send is expected to
- *          reply to the message and a buffer is provided into which
- *          IUCV moves the reply to this message.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Sddress of array of send buffers.
- *        buflen - Total length of send buffers.
- *        ansbuf - Address of array of buffer into which IUCV moves the reply
- *                 of this message.
- *        anslen - Address of length reply buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send2way_array (u16 pathid,
-			 u32 * msgid,
-			 u32 trgcls,
-			 u32 srccls,
-			 u32 msgtag,
-			 int flags1,
-			 iucv_array_t * buffer,
-			 ulong buflen, iucv_array_t * ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_prmmsg
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a two-way message and the
- *          receiver of the message is expected to reply. A buffer
- *          is provided into which IUCV moves the reply to this
- *          message.
- * Input: pathid - Rath identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed in parameter list.
- *        ansbuf - Address of buffer into which IUCV moves the reply of
- *                 this message.
- *        anslen - Address of length of buffer.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Buffer address is NULL.
-*/
-int iucv_send2way_prmmsg (u16 pathid,
-			  u32 * msgid,
-			  u32 trgcls,
-			  u32 srccls,
-			  u32 msgtag,
-			  ulong flags1,
-			  uchar prmmsg[8], void *ansbuf, ulong anslen);
-
-/*
- * Name: iucv_send2way_prmmsg_array
- * Purpose: This function transmits data to another application.
- *          Prmmsg specifies that the 8-bytes of data are to be moved
- *          into the parameter list. This is a two-way message and the
- *          receiver of the message is expected to reply. A buffer
- *          is provided into which IUCV moves the reply to this
- *          message. The contents of ansbuf is the address of the
- *          array of addresses and lengths of discontiguous buffers
- *          that contain the reply.
- * Input: pathid - Path identification number.
- *        trgcls - Specifies target class.
- *        srccls - Specifies the source message class.
- *        msgtag - Specifies a tag to be associated with the message.
- *        flags1 - Option for path.
- *          IPPRTY- 0x20 specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into the parameter list.
- *        ansbuf - Address of array of buffer into which IUCV moves the reply
- *                 of this message.
- *        anslen - Address of length of reply buffers.
- * Output: msgid - Specifies the message ID.
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Ansbuf address is NULL.
-*/
-int iucv_send2way_prmmsg_array (u16 pathid,
-				u32 * msgid,
-				u32 trgcls,
-				u32 srccls,
-				u32 msgtag,
-				int flags1,
-				uchar prmmsg[8],
-				iucv_array_t * ansbuf, ulong anslen);
-
-/*
- * Name: iucv_setmask
- * Purpose: This function enables or disables the following IUCV
- *          external interruptions: Nonpriority and priority message
- *          interrupts, nonpriority and priority reply interrupts.
- * Input: SetMaskFlag - options for interrupts
- *           0x80 - Nonpriority_MessagePendingInterruptsFlag
- *           0x40 - Priority_MessagePendingInterruptsFlag
- *           0x20 - Nonpriority_MessageCompletionInterruptsFlag
- *           0x10 - Priority_MessageCompletionInterruptsFlag
- *           0x08 - IUCVControlInterruptsFlag
- * Output: NA
- * Return: Return code from CP IUCV call.
-*/
-int iucv_setmask (int SetMaskFlag);
-
-/*
- * Name: iucv_sever
- * Purpose: This function terminates an IUCV path.
- * Input: pathid - Path identification number.
- *        user_data - 16-bytes of user data.
- * Output: NA
- * Return: Return code from CP IUCV call.
- *         (-EINVAL) - Interal error, wild pointer.
-*/
-int iucv_sever (u16 pathid, uchar user_data[16]);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 343 - 337
drivers/s390/net/netiucv.c


+ 74 - 73
drivers/s390/net/smsgiucv.c

@@ -1,7 +1,7 @@
 /*
  * IUCV special message driver
  *
- * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,10 +23,10 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/device.h>
+#include <net/iucv/iucv.h>
 #include <asm/cpcmd.h>
 #include <asm/ebcdic.h>
-
-#include "iucv.h"
+#include "smsgiucv.h"
 
 struct smsg_callback {
 	struct list_head list;
@@ -39,38 +39,46 @@ MODULE_AUTHOR
    ("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)");
 MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver");
 
-static iucv_handle_t smsg_handle;
-static unsigned short smsg_pathid;
+static struct iucv_path *smsg_path;
+
 static DEFINE_SPINLOCK(smsg_list_lock);
 static struct list_head smsg_list = LIST_HEAD_INIT(smsg_list);
 
-static void
-smsg_connection_complete(iucv_ConnectionComplete *eib, void *pgm_data)
+static int smsg_path_pending(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+static void smsg_message_pending(struct iucv_path *, struct iucv_message *);
+
+static struct iucv_handler smsg_handler = {
+	.path_pending	 = smsg_path_pending,
+	.message_pending = smsg_message_pending,
+};
+
+static int smsg_path_pending(struct iucv_path *path, u8 ipvmid[8],
+			     u8 ipuser[16])
 {
+	if (strncmp(ipvmid, "*MSG    ", sizeof(ipvmid)) != 0)
+		return -EINVAL;
+	/* Path pending from *MSG. */
+	return iucv_path_accept(path, &smsg_handler, "SMSGIUCV        ", NULL);
 }
 
-
-static void
-smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
+static void smsg_message_pending(struct iucv_path *path,
+				 struct iucv_message *msg)
 {
 	struct smsg_callback *cb;
-	unsigned char *msg;
+	unsigned char *buffer;
 	unsigned char sender[9];
-	unsigned short len;
 	int rc, i;
 
-	len = eib->ln1msg2.ipbfln1f;
-	msg = kmalloc(len + 1, GFP_ATOMIC|GFP_DMA);
-	if (!msg) {
-		iucv_reject(eib->ippathid, eib->ipmsgid, eib->iptrgcls);
+	buffer = kmalloc(msg->length + 1, GFP_ATOMIC | GFP_DMA);
+	if (!buffer) {
+		iucv_message_reject(path, msg);
 		return;
 	}
-	rc = iucv_receive(eib->ippathid, eib->ipmsgid, eib->iptrgcls,
-			  msg, len, NULL, NULL, NULL);
+	rc = iucv_message_receive(path, msg, 0, buffer, msg->length, NULL);
 	if (rc == 0) {
-		msg[len] = 0;
-		EBCASC(msg, len);
-		memcpy(sender, msg, 8);
+		buffer[msg->length] = 0;
+		EBCASC(buffer, msg->length);
+		memcpy(sender, buffer, 8);
 		sender[8] = 0;
 		/* Remove trailing whitespace from the sender name. */
 		for (i = 7; i >= 0; i--) {
@@ -80,27 +88,17 @@ smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
 		}
 		spin_lock(&smsg_list_lock);
 		list_for_each_entry(cb, &smsg_list, list)
-			if (strncmp(msg + 8, cb->prefix, cb->len) == 0) {
-				cb->callback(sender, msg + 8);
+			if (strncmp(buffer + 8, cb->prefix, cb->len) == 0) {
+				cb->callback(sender, buffer + 8);
 				break;
 			}
 		spin_unlock(&smsg_list_lock);
 	}
-	kfree(msg);
+	kfree(buffer);
 }
 
-static iucv_interrupt_ops_t smsg_ops = {
-	.ConnectionComplete = smsg_connection_complete,
-	.MessagePending     = smsg_message_pending,
-};
-
-static struct device_driver smsg_driver = {
-	.name = "SMSGIUCV",
-	.bus  = &iucv_bus,
-};
-
-int
-smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
+int smsg_register_callback(char *prefix,
+			   void (*callback)(char *from, char *str))
 {
 	struct smsg_callback *cb;
 
@@ -110,18 +108,18 @@ smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
 	cb->prefix = prefix;
 	cb->len = strlen(prefix);
 	cb->callback = callback;
-	spin_lock(&smsg_list_lock);
+	spin_lock_bh(&smsg_list_lock);
 	list_add_tail(&cb->list, &smsg_list);
-	spin_unlock(&smsg_list_lock);
+	spin_unlock_bh(&smsg_list_lock);
 	return 0;
 }
 
-void
-smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
+void smsg_unregister_callback(char *prefix,
+			      void (*callback)(char *from, char *str))
 {
 	struct smsg_callback *cb, *tmp;
 
-	spin_lock(&smsg_list_lock);
+	spin_lock_bh(&smsg_list_lock);
 	cb = NULL;
 	list_for_each_entry(tmp, &smsg_list, list)
 		if (tmp->callback == callback &&
@@ -130,55 +128,58 @@ smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
 			list_del(&cb->list);
 			break;
 		}
-	spin_unlock(&smsg_list_lock);
+	spin_unlock_bh(&smsg_list_lock);
 	kfree(cb);
 }
 
-static void __exit
-smsg_exit(void)
+static struct device_driver smsg_driver = {
+	.name = "SMSGIUCV",
+	.bus  = &iucv_bus,
+};
+
+static void __exit smsg_exit(void)
 {
-	if (smsg_handle > 0) {
-		cpcmd("SET SMSG OFF", NULL, 0, NULL);
-		iucv_sever(smsg_pathid, NULL);
-		iucv_unregister_program(smsg_handle);
-		driver_unregister(&smsg_driver);
-	}
-	return;
+	cpcmd("SET SMSG IUCV", NULL, 0, NULL);
+	iucv_unregister(&smsg_handler, 1);
+	driver_unregister(&smsg_driver);
 }
 
-static int __init
-smsg_init(void)
+static int __init smsg_init(void)
 {
-	static unsigned char pgmmask[24] = {
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-	};
 	int rc;
 
 	rc = driver_register(&smsg_driver);
-	if (rc != 0) {
-		printk(KERN_ERR "SMSGIUCV: failed to register driver.\n");
-		return rc;
-	}
-	smsg_handle = iucv_register_program("SMSGIUCV        ", "*MSG    ",
-					    pgmmask, &smsg_ops, NULL);
-	if (!smsg_handle) {
+	if (rc != 0)
+		goto out;
+	rc = iucv_register(&smsg_handler, 1);
+	if (rc) {
 		printk(KERN_ERR "SMSGIUCV: failed to register to iucv");
-		driver_unregister(&smsg_driver);
-		return -EIO;	/* better errno ? */
+		rc = -EIO;	/* better errno ? */
+		goto out_driver;
+	}
+	smsg_path = iucv_path_alloc(255, 0, GFP_KERNEL);
+	if (!smsg_path) {
+		rc = -ENOMEM;
+		goto out_register;
 	}
-	rc = iucv_connect (&smsg_pathid, 255, NULL, "*MSG    ", NULL, 0,
-			   NULL, NULL, smsg_handle, NULL);
+	rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG    ",
+			       NULL, NULL, NULL);
 	if (rc) {
 		printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
-		iucv_unregister_program(smsg_handle);
-		driver_unregister(&smsg_driver);
-		smsg_handle = NULL;
-		return -EIO;
+		rc = -EIO;	/* better errno ? */
+		goto out_free;
 	}
 	cpcmd("SET SMSG IUCV", NULL, 0, NULL);
 	return 0;
+
+out_free:
+	iucv_path_free(smsg_path);
+out_register:
+	iucv_unregister(&smsg_handler, 1);
+out_driver:
+	driver_unregister(&smsg_driver);
+out:
+	return rc;
 }
 
 module_init(smsg_init);

+ 1 - 3
fs/ecryptfs/crypto.c

@@ -828,9 +828,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
 		mutex_unlock(&crypt_stat->cs_tfm_mutex);
 		goto out;
 	}
-	crypto_blkcipher_set_flags(crypt_stat->tfm,
-				   (ECRYPTFS_DEFAULT_CHAINING_MODE
-				    | CRYPTO_TFM_REQ_WEAK_KEY));
+	crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
 	mutex_unlock(&crypt_stat->cs_tfm_mutex);
 	rc = 0;
 out:

+ 0 - 1
fs/ecryptfs/ecryptfs_kernel.h

@@ -176,7 +176,6 @@ ecryptfs_get_key_payload_data(struct key *key)
 #define ECRYPTFS_FILE_SIZE_BYTES 8
 #define ECRYPTFS_DEFAULT_CIPHER "aes"
 #define ECRYPTFS_DEFAULT_KEY_BYTES 16
-#define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC
 #define ECRYPTFS_DEFAULT_HASH "md5"
 #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
 #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED

+ 21 - 3
include/crypto/algapi.h

@@ -18,8 +18,8 @@ struct module;
 struct seq_file;
 
 struct crypto_type {
-	unsigned int (*ctxsize)(struct crypto_alg *alg);
-	int (*init)(struct crypto_tfm *tfm);
+	unsigned int (*ctxsize)(struct crypto_alg *alg, u32 type, u32 mask);
+	int (*init)(struct crypto_tfm *tfm, u32 type, u32 mask);
 	void (*exit)(struct crypto_tfm *tfm);
 	void (*show)(struct seq_file *m, struct crypto_alg *alg);
 };
@@ -93,7 +93,8 @@ struct crypto_template *crypto_lookup_template(const char *name);
 int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
 		      struct crypto_instance *inst);
 void crypto_drop_spawn(struct crypto_spawn *spawn);
-struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn);
+struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
+				    u32 mask);
 
 struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
 				       u32 type, u32 mask);
@@ -132,11 +133,28 @@ static inline void *crypto_blkcipher_ctx_aligned(struct crypto_blkcipher *tfm)
 	return crypto_tfm_ctx_aligned(&tfm->base);
 }
 
+static inline struct crypto_cipher *crypto_spawn_cipher(
+	struct crypto_spawn *spawn)
+{
+	u32 type = CRYPTO_ALG_TYPE_CIPHER;
+	u32 mask = CRYPTO_ALG_TYPE_MASK;
+
+	return __crypto_cipher_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
 static inline struct cipher_alg *crypto_cipher_alg(struct crypto_cipher *tfm)
 {
 	return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher;
 }
 
+static inline struct crypto_hash *crypto_spawn_hash(struct crypto_spawn *spawn)
+{
+	u32 type = CRYPTO_ALG_TYPE_HASH;
+	u32 mask = CRYPTO_ALG_TYPE_HASH_MASK;
+
+	return __crypto_hash_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
 static inline void *crypto_hash_ctx_aligned(struct crypto_hash *tfm)
 {
 	return crypto_tfm_ctx_aligned(&tfm->base);

+ 0 - 2
include/linux/atmarp.h

@@ -6,9 +6,7 @@
 #ifndef _LINUX_ATMARP_H
 #define _LINUX_ATMARP_H
 
-#ifdef __KERNEL__
 #include <linux/types.h>
-#endif
 #include <linux/atmapi.h>
 #include <linux/atmioc.h>
 

+ 14 - 134
include/linux/crypto.h

@@ -51,15 +51,9 @@
 /*
  * Transform masks and values (for crt_flags).
  */
-#define CRYPTO_TFM_MODE_MASK		0x000000ff
 #define CRYPTO_TFM_REQ_MASK		0x000fff00
 #define CRYPTO_TFM_RES_MASK		0xfff00000
 
-#define CRYPTO_TFM_MODE_ECB		0x00000001
-#define CRYPTO_TFM_MODE_CBC		0x00000002
-#define CRYPTO_TFM_MODE_CFB		0x00000004
-#define CRYPTO_TFM_MODE_CTR		0x00000008
-
 #define CRYPTO_TFM_REQ_WEAK_KEY		0x00000100
 #define CRYPTO_TFM_REQ_MAY_SLEEP	0x00000200
 #define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
@@ -71,12 +65,8 @@
 /*
  * Miscellaneous stuff.
  */
-#define CRYPTO_UNSPEC			0
 #define CRYPTO_MAX_ALG_NAME		64
 
-#define CRYPTO_DIR_ENCRYPT		1
-#define CRYPTO_DIR_DECRYPT		0
-
 /*
  * The macro CRYPTO_MINALIGN_ATTR (along with the void * type in the actual
  * declaration) is used to ensure that the crypto_tfm context structure is
@@ -148,19 +138,6 @@ struct cipher_alg {
 	                  unsigned int keylen);
 	void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 	void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
-
-	unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes) __deprecated;
-	unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes) __deprecated;
-	unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes) __deprecated;
-	unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc,
-					u8 *dst, const u8 *src,
-					unsigned int nbytes) __deprecated;
 };
 
 struct digest_alg {
@@ -243,11 +220,6 @@ int crypto_unregister_alg(struct crypto_alg *alg);
 #ifdef CONFIG_CRYPTO
 int crypto_has_alg(const char *name, u32 type, u32 mask);
 #else
-static inline int crypto_alg_available(const char *name, u32 flags)
-{
-	return 0;
-}
-
 static inline int crypto_has_alg(const char *name, u32 type, u32 mask)
 {
 	return 0;
@@ -339,13 +311,18 @@ struct crypto_tfm {
 	void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
 };
 
-#define crypto_cipher crypto_tfm
-#define crypto_comp crypto_tfm
-
 struct crypto_blkcipher {
 	struct crypto_tfm base;
 };
 
+struct crypto_cipher {
+	struct crypto_tfm base;
+};
+
+struct crypto_comp {
+	struct crypto_tfm base;
+};
+
 struct crypto_hash {
 	struct crypto_tfm base;
 };
@@ -395,40 +372,11 @@ static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
 	return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
 }
 
-static unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
-	__deprecated;
-static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->__crt_alg->cra_cipher.cia_min_keysize;
-}
-
-static unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
-	__deprecated;
-static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->__crt_alg->cra_cipher.cia_max_keysize;
-}
-
-static unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) __deprecated;
-static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_ivsize;
-}
-
 static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
 {
 	return tfm->__crt_alg->cra_blocksize;
 }
 
-static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
-	return tfm->__crt_alg->cra_digest.dia_digestsize;
-}
-
 static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm)
 {
 	return tfm->__crt_alg->cra_alignmask;
@@ -633,7 +581,7 @@ static inline struct crypto_cipher *crypto_alloc_cipher(const char *alg_name,
 
 static inline struct crypto_tfm *crypto_cipher_tfm(struct crypto_cipher *tfm)
 {
-	return tfm;
+	return &tfm->base;
 }
 
 static inline void crypto_free_cipher(struct crypto_cipher *tfm)
@@ -809,76 +757,6 @@ static inline int crypto_hash_setkey(struct crypto_hash *hash,
 	return crypto_hash_crt(hash)->setkey(hash, key, keylen);
 }
 
-static int crypto_cipher_encrypt(struct crypto_tfm *tfm,
-				 struct scatterlist *dst,
-				 struct scatterlist *src,
-				 unsigned int nbytes) __deprecated;
-static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
-                                        struct scatterlist *dst,
-                                        struct scatterlist *src,
-                                        unsigned int nbytes)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
-}                                        
-
-static int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
-				    struct scatterlist *dst,
-				    struct scatterlist *src,
-				    unsigned int nbytes, u8 *iv) __deprecated;
-static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
-                                           struct scatterlist *dst,
-                                           struct scatterlist *src,
-                                           unsigned int nbytes, u8 *iv)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
-}                                        
-
-static int crypto_cipher_decrypt(struct crypto_tfm *tfm,
-				 struct scatterlist *dst,
-				 struct scatterlist *src,
-				 unsigned int nbytes) __deprecated;
-static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
-                                        struct scatterlist *dst,
-                                        struct scatterlist *src,
-                                        unsigned int nbytes)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
-}
-
-static int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
-				    struct scatterlist *dst,
-				    struct scatterlist *src,
-				    unsigned int nbytes, u8 *iv) __deprecated;
-static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
-                                           struct scatterlist *dst,
-                                           struct scatterlist *src,
-                                           unsigned int nbytes, u8 *iv)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
-}
-
-static void crypto_cipher_set_iv(struct crypto_tfm *tfm,
-				 const u8 *src, unsigned int len) __deprecated;
-static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
-                                        const u8 *src, unsigned int len)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	memcpy(tfm->crt_cipher.cit_iv, src, len);
-}
-
-static void crypto_cipher_get_iv(struct crypto_tfm *tfm,
-				 u8 *dst, unsigned int len) __deprecated;
-static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
-                                        u8 *dst, unsigned int len)
-{
-	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
-	memcpy(dst, tfm->crt_cipher.cit_iv, len);
-}
-
 static inline struct crypto_comp *__crypto_comp_cast(struct crypto_tfm *tfm)
 {
 	return (struct crypto_comp *)tfm;
@@ -903,7 +781,7 @@ static inline struct crypto_comp *crypto_alloc_comp(const char *alg_name,
 
 static inline struct crypto_tfm *crypto_comp_tfm(struct crypto_comp *tfm)
 {
-	return tfm;
+	return &tfm->base;
 }
 
 static inline void crypto_free_comp(struct crypto_comp *tfm)
@@ -934,14 +812,16 @@ static inline int crypto_comp_compress(struct crypto_comp *tfm,
                                        const u8 *src, unsigned int slen,
                                        u8 *dst, unsigned int *dlen)
 {
-	return crypto_comp_crt(tfm)->cot_compress(tfm, src, slen, dst, dlen);
+	return crypto_comp_crt(tfm)->cot_compress(crypto_comp_tfm(tfm),
+						  src, slen, dst, dlen);
 }
 
 static inline int crypto_comp_decompress(struct crypto_comp *tfm,
                                          const u8 *src, unsigned int slen,
                                          u8 *dst, unsigned int *dlen)
 {
-	return crypto_comp_crt(tfm)->cot_decompress(tfm, src, slen, dst, dlen);
+	return crypto_comp_crt(tfm)->cot_decompress(crypto_comp_tfm(tfm),
+						    src, slen, dst, dlen);
 }
 
 #endif	/* _LINUX_CRYPTO_H */

+ 10 - 0
include/linux/if_packet.h

@@ -41,6 +41,7 @@ struct sockaddr_ll
 #define PACKET_RX_RING			5
 #define PACKET_STATISTICS		6
 #define PACKET_COPY_THRESH		7
+#define PACKET_AUXDATA			8
 
 struct tpacket_stats
 {
@@ -48,6 +49,15 @@ struct tpacket_stats
 	unsigned int	tp_drops;
 };
 
+struct tpacket_auxdata
+{
+	__u32		tp_status;
+	__u32		tp_len;
+	__u32		tp_snaplen;
+	__u16		tp_mac;
+	__u16		tp_net;
+};
+
 struct tpacket_hdr
 {
 	unsigned long	tp_status;

+ 1 - 1
include/linux/net.h

@@ -24,7 +24,7 @@
 struct poll_table_struct;
 struct inode;
 
-#define NPROTO		32		/* should be enough for now..	*/
+#define NPROTO		33		/* should be enough for now..	*/
 
 #define SYS_SOCKET	1		/* sys_socket(2)		*/
 #define SYS_BIND	2		/* sys_bind(2)			*/

+ 1 - 1
include/linux/netdevice.h

@@ -589,7 +589,7 @@ extern int		dev_open(struct net_device *dev);
 extern int		dev_close(struct net_device *dev);
 extern int		dev_queue_xmit(struct sk_buff *skb);
 extern int		register_netdevice(struct net_device *dev);
-extern int		unregister_netdevice(struct net_device *dev);
+extern void		unregister_netdevice(struct net_device *dev);
 extern void		free_netdev(struct net_device *dev);
 extern void		synchronize_net(void);
 extern int 		register_netdevice_notifier(struct notifier_block *nb);

+ 1 - 0
include/linux/netfilter/Kbuild

@@ -33,6 +33,7 @@ header-y += xt_tcpmss.h
 header-y += xt_tcpudp.h
 header-y += xt_SECMARK.h
 header-y += xt_CONNSECMARK.h
+header-y += xt_TCPMSS.h
 
 unifdef-y += nf_conntrack_common.h
 unifdef-y += nf_conntrack_ftp.h

+ 21 - 0
include/linux/netfilter/nf_conntrack_sane.h

@@ -0,0 +1,21 @@
+#ifndef _NF_CONNTRACK_SANE_H
+#define _NF_CONNTRACK_SANE_H
+/* SANE tracking. */
+
+#ifdef __KERNEL__
+
+#define SANE_PORT	6566
+
+enum sane_state {
+	SANE_STATE_NORMAL,
+	SANE_STATE_START_REQUESTED,
+};
+
+/* This structure exists only once per master */
+struct nf_ct_sane_master {
+	enum sane_state state;
+};
+
+#endif /* __KERNEL__ */
+
+#endif /* _NF_CONNTRACK_SANE_H */

+ 3 - 1
include/linux/netfilter/nf_conntrack_tcp.h

@@ -27,6 +27,9 @@ enum tcp_conntrack {
 /* This sender sent FIN first */
 #define IP_CT_TCP_FLAG_CLOSE_INIT		0x04
 
+/* Be liberal in window checking */
+#define IP_CT_TCP_FLAG_BE_LIBERAL		0x08
+
 #ifdef __KERNEL__
 
 struct ip_ct_tcp_state {
@@ -34,7 +37,6 @@ struct ip_ct_tcp_state {
 	u_int32_t	td_maxend;	/* max of ack + max(win, 1) */
 	u_int32_t	td_maxwin;	/* max(win) */
 	u_int8_t	td_scale;	/* window scale factor */
-	u_int8_t	loose;		/* used when connection picked up from the middle */
 	u_int8_t	flags;		/* per direction options */
 };
 

+ 10 - 0
include/linux/netfilter/xt_TCPMSS.h

@@ -0,0 +1,10 @@
+#ifndef _XT_TCPMSS_H
+#define _XT_TCPMSS_H
+
+struct xt_tcpmss_info {
+	u_int16_t mss;
+};
+
+#define XT_TCPMSS_CLAMP_PMTU 0xffff
+
+#endif /* _XT_TCPMSS_H */

+ 1 - 0
include/linux/netfilter_ipv4/ip_nat.h

@@ -16,6 +16,7 @@ enum ip_nat_manip_type
 
 #define IP_NAT_RANGE_MAP_IPS 1
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
+#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */
 
 /* NAT sequence number modifications */
 struct ip_nat_seq {

+ 3 - 19
include/linux/netfilter_ipv4/ip_tables.h

@@ -272,25 +272,9 @@ ipt_get_target(struct ipt_entry *e)
 #include <linux/init.h>
 extern void ipt_init(void) __init;
 
-#define ipt_register_target(tgt) 	\
-({	(tgt)->family = AF_INET;	\
- 	xt_register_target(tgt); })
-#define ipt_unregister_target(tgt) xt_unregister_target(tgt)
-
-#define ipt_register_match(mtch) 	\
-({	(mtch)->family = AF_INET;	\
-	xt_register_match(mtch); })
-#define ipt_unregister_match(mtch) xt_unregister_match(mtch)
-
-//#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl)
-//#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl)
-
-extern int ipt_register_table(struct ipt_table *table,
+extern int ipt_register_table(struct xt_table *table,
 			      const struct ipt_replace *repl);
-extern void ipt_unregister_table(struct ipt_table *table);
-
-/* net/sched/ipt.c: Gimme access to your targets!  Gets target->me. */
-extern struct ipt_target *ipt_find_target(const char *name, u8 revision);
+extern void ipt_unregister_table(struct xt_table *table);
 
 /* Standard entry. */
 struct ipt_standard
@@ -315,7 +299,7 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb,
 				 unsigned int hook,
 				 const struct net_device *in,
 				 const struct net_device *out,
-				 struct ipt_table *table);
+				 struct xt_table *table);
 
 #define IPT_ALIGN(s) XT_ALIGN(s)
 

+ 3 - 4
include/linux/netfilter_ipv4/ipt_TCPMSS.h

@@ -1,10 +1,9 @@
 #ifndef _IPT_TCPMSS_H
 #define _IPT_TCPMSS_H
 
-struct ipt_tcpmss_info {
-	u_int16_t mss;
-};
+#include <linux/netfilter/xt_TCPMSS.h>
 
-#define IPT_TCPMSS_CLAMP_PMTU 0xffff
+#define ipt_tcpmss_info		xt_tcpmss_info
+#define IPT_TCPMSS_CLAMP_PMTU	XT_TCPMSS_CLAMP_PMTU
 
 #endif /*_IPT_TCPMSS_H*/

+ 22 - 13
include/linux/netfilter_ipv6/ip6_tables.h

@@ -104,6 +104,25 @@ struct ip6t_entry
 	unsigned char elems[0];
 };
 
+/* Standard entry */
+struct ip6t_standard
+{
+	struct ip6t_entry entry;
+	struct ip6t_standard_target target;
+};
+
+struct ip6t_error_target
+{
+	struct ip6t_entry_target target;
+	char errorname[IP6T_FUNCTION_MAXNAMELEN];
+};
+
+struct ip6t_error
+{
+	struct ip6t_entry entry;
+	struct ip6t_error_target target;
+};
+
 /*
  * New IP firewall options for [gs]etsockopt at the RAW IP level.
  * Unlike BSD Linux inherits IP options so you don't have to use
@@ -286,24 +305,14 @@ ip6t_get_target(struct ip6t_entry *e)
 #include <linux/init.h>
 extern void ip6t_init(void) __init;
 
-#define ip6t_register_target(tgt) 		\
-({	(tgt)->family = AF_INET6;		\
- 	xt_register_target(tgt); })
-#define ip6t_unregister_target(tgt) xt_unregister_target(tgt)
-
-#define ip6t_register_match(match)		\
-({	(match)->family = AF_INET6;		\
-	xt_register_match(match); })
-#define ip6t_unregister_match(match) xt_unregister_match(match)
-
-extern int ip6t_register_table(struct ip6t_table *table,
+extern int ip6t_register_table(struct xt_table *table,
 			       const struct ip6t_replace *repl);
-extern void ip6t_unregister_table(struct ip6t_table *table);
+extern void ip6t_unregister_table(struct xt_table *table);
 extern unsigned int ip6t_do_table(struct sk_buff **pskb,
 				  unsigned int hook,
 				  const struct net_device *in,
 				  const struct net_device *out,
-				  struct ip6t_table *table);
+				  struct xt_table *table);
 
 /* Check for an extension */
 extern int ip6t_ext_hdr(u8 nexthdr);

+ 15 - 0
include/linux/netfilter_ipv6/ip6t_mh.h

@@ -0,0 +1,15 @@
+#ifndef _IP6T_MH_H
+#define _IP6T_MH_H
+
+/* MH matching stuff */
+struct ip6t_mh
+{
+	u_int8_t types[2];	/* MH type range */
+	u_int8_t invflags;	/* Inverse flags */
+};
+
+/* Values for "invflags" field in struct ip6t_mh. */
+#define IP6T_MH_INV_TYPE	0x01	/* Invert the sense of type. */
+#define IP6T_MH_INV_MASK	0x01	/* All possible flags. */
+
+#endif /*_IP6T_MH_H*/

+ 3 - 1
include/linux/pfkeyv2.h

@@ -251,7 +251,8 @@ struct sadb_x_sec_ctx {
 #define SADB_X_SPDEXPIRE	21
 #define SADB_X_SPDDELETE2	22
 #define SADB_X_NAT_T_NEW_MAPPING	23
-#define SADB_MAX		23
+#define SADB_X_MIGRATE		24
+#define SADB_MAX		24
 
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS	1
@@ -297,6 +298,7 @@ struct sadb_x_sec_ctx {
 #define SADB_X_EALG_BLOWFISHCBC		7
 #define SADB_EALG_NULL			11
 #define SADB_X_EALG_AESCBC		12
+#define SADB_X_EALG_CAMELLIACBC		22
 #define SADB_EALG_MAX                   253 /* last EALG */
 /* private allocations should use 249-255 (RFC2407) */
 #define SADB_X_EALG_SERPENTCBC  252     /* draft-ietf-ipsec-ciph-aes-cbc-00 */

+ 3 - 1
include/linux/socket.h

@@ -187,7 +187,8 @@ struct ucred {
 #define AF_LLC		26	/* Linux LLC			*/
 #define AF_TIPC		30	/* TIPC sockets			*/
 #define AF_BLUETOOTH	31	/* Bluetooth sockets 		*/
-#define AF_MAX		32	/* For now.. */
+#define AF_IUCV		32	/* IUCV sockets			*/
+#define AF_MAX		33	/* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC	AF_UNSPEC
@@ -220,6 +221,7 @@ struct ucred {
 #define PF_LLC		AF_LLC
 #define PF_TIPC		AF_TIPC
 #define PF_BLUETOOTH	AF_BLUETOOTH
+#define PF_IUCV		AF_IUCV
 #define PF_MAX		AF_MAX
 
 /* Maximum queue length specifiable by listen.  */

+ 2 - 1
include/linux/sysctl.h

@@ -699,7 +699,8 @@ enum {
 	NET_X25_CALL_REQUEST_TIMEOUT=2,
 	NET_X25_RESET_REQUEST_TIMEOUT=3,
 	NET_X25_CLEAR_REQUEST_TIMEOUT=4,
-	NET_X25_ACK_HOLD_BACK_TIMEOUT=5
+	NET_X25_ACK_HOLD_BACK_TIMEOUT=5,
+	NET_X25_FORWARD=6
 };
 
 /* /proc/sys/net/token-ring */

+ 1 - 1
include/linux/tcp.h

@@ -316,7 +316,7 @@ struct tcp_sock {
 	struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
 	struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
 
-	struct tcp_sack_block recv_sack_cache[4];
+	struct tcp_sack_block_wire recv_sack_cache[4];
 
 	/* from STCP, retrans queue hinting */
 	struct sk_buff* lost_skb_hint;

+ 0 - 8
include/linux/wanrouter.h

@@ -516,9 +516,6 @@ struct wan_device {
 /* Public functions available for device drivers */
 extern int register_wan_device(struct wan_device *wandev);
 extern int unregister_wan_device(char *name);
-__be16 wanrouter_type_trans(struct sk_buff *skb, struct net_device *dev);
-int wanrouter_encapsulate(struct sk_buff *skb, struct net_device *dev,
-			  unsigned short type);
 
 /* Proc interface functions. These must not be called by the drivers! */
 extern int wanrouter_proc_init(void);
@@ -527,11 +524,6 @@ extern int wanrouter_proc_add(struct wan_device *wandev);
 extern int wanrouter_proc_delete(struct wan_device *wandev);
 extern int wanrouter_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
 
-extern void lock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
-extern void unlock_adapter_irq(spinlock_t *lock, unsigned long *smp_flags);
-
-
-
 /* Public Data */
 /* list of registered devices */
 extern struct wan_device *wanrouter_router_devlist;

+ 19 - 0
include/linux/xfrm.h

@@ -178,6 +178,9 @@ enum {
 	XFRM_MSG_REPORT,
 #define XFRM_MSG_REPORT XFRM_MSG_REPORT
 
+	XFRM_MSG_MIGRATE,
+#define XFRM_MSG_MIGRATE XFRM_MSG_MIGRATE
+
 	__XFRM_MSG_MAX
 };
 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -256,6 +259,7 @@ enum xfrm_attr_type_t {
 	XFRMA_COADDR,		/* xfrm_address_t */
 	XFRMA_LASTUSED,
 	XFRMA_POLICY_TYPE,	/* struct xfrm_userpolicy_type */
+	XFRMA_MIGRATE,
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -351,6 +355,19 @@ struct xfrm_user_report {
 	struct xfrm_selector		sel;
 };
 
+struct xfrm_user_migrate {
+	xfrm_address_t			old_daddr;
+	xfrm_address_t			old_saddr;
+	xfrm_address_t			new_daddr;
+	xfrm_address_t			new_saddr;
+	__u8				proto;
+	__u8				mode;
+	__u16				reserved;
+	__u32				reqid;
+	__u16				old_family;
+	__u16				new_family;
+};
+
 #ifndef __KERNEL__
 /* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
@@ -375,6 +392,8 @@ enum xfrm_nlgroups {
 #define XFRMNLGRP_AEVENTS	XFRMNLGRP_AEVENTS
 	XFRMNLGRP_REPORT,
 #define XFRMNLGRP_REPORT	XFRMNLGRP_REPORT
+	XFRMNLGRP_MIGRATE,
+#define XFRMNLGRP_MIGRATE	XFRMNLGRP_MIGRATE
 	__XFRMNLGRP_MAX
 };
 #define XFRMNLGRP_MAX	(__XFRMNLGRP_MAX - 1)

+ 5 - 5
include/net/inet_hashtables.h

@@ -34,12 +34,13 @@
 #include <asm/byteorder.h>
 
 /* This is for all connections with a full identity, no wildcards.
- * New scheme, half the table is for TIME_WAIT, the other half is
- * for the rest.  I'll experiment with dynamic table growth later.
+ * One chain is dedicated to TIME_WAIT sockets.
+ * I'll experiment with dynamic table growth later.
  */
 struct inet_ehash_bucket {
 	rwlock_t	  lock;
 	struct hlist_head chain;
+	struct hlist_head twchain;
 };
 
 /* There are a few simple rules, which allow for local port reuse by
@@ -97,8 +98,7 @@ struct inet_hashinfo {
 	 *
 	 *          TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE
 	 *
-	 * First half of the table is for sockets not in TIME_WAIT, second half
-	 * is for TIME_WAIT sockets only.
+	 * TIME_WAIT sockets use a separate chain (twchain).
 	 */
 	struct inet_ehash_bucket	*ehash;
 
@@ -369,7 +369,7 @@ static inline struct sock *
 	}
 
 	/* Must check for a TIME_WAIT'er before going to listener hash. */
-	sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
+	sk_for_each(sk, node, &head->twchain) {
 		if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
 			goto hit;
 	}

+ 106 - 0
include/net/iucv/af_iucv.h

@@ -0,0 +1,106 @@
+/*
+ * Copyright 2006 IBM Corporation
+ * IUCV protocol stack for Linux on zSeries
+ * Version 1.0
+ * Author(s): Jennifer Hunt <jenhunt@us.ibm.com>
+ *
+ */
+
+#ifndef __AFIUCV_H
+#define __AFIUCV_H
+
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/socket.h>
+
+#ifndef AF_IUCV
+#define AF_IUCV		32
+#define PF_IUCV		AF_IUCV
+#endif
+
+/* Connection and socket states */
+enum {
+	IUCV_CONNECTED = 1,
+	IUCV_OPEN,
+	IUCV_BOUND,
+	IUCV_LISTEN,
+	IUCV_SEVERED,
+	IUCV_DISCONN,
+	IUCV_CLOSED
+};
+
+#define IUCV_QUEUELEN_DEFAULT	65535
+#define IUCV_CONN_TIMEOUT	(HZ * 40)
+#define IUCV_DISCONN_TIMEOUT	(HZ * 2)
+#define IUCV_CONN_IDLE_TIMEOUT	(HZ * 60)
+#define IUCV_BUFSIZE_DEFAULT	32768
+
+/* IUCV socket address */
+struct sockaddr_iucv {
+	sa_family_t	siucv_family;
+	unsigned short	siucv_port;		/* Reserved */
+	unsigned int	siucv_addr;		/* Reserved */
+	char		siucv_nodeid[8];	/* Reserved */
+	char		siucv_user_id[8];	/* Guest User Id */
+	char		siucv_name[8];		/* Application Name */
+};
+
+
+/* Common socket structures and functions */
+
+#define iucv_sk(__sk) ((struct iucv_sock *) __sk)
+
+struct iucv_sock {
+	struct sock		sk;
+	char			src_user_id[8];
+	char			src_name[8];
+	char			dst_user_id[8];
+	char			dst_name[8];
+	struct list_head	accept_q;
+	struct sock		*parent;
+	struct iucv_path	*path;
+	struct sk_buff_head	send_skb_q;
+	unsigned int		send_tag;
+};
+
+struct iucv_sock_list {
+	struct hlist_head head;
+	rwlock_t	  lock;
+	atomic_t	  autobind_name;
+};
+
+static void iucv_sock_destruct(struct sock *sk);
+static void iucv_sock_cleanup_listen(struct sock *parent);
+static void iucv_sock_kill(struct sock *sk);
+static void iucv_sock_close(struct sock *sk);
+static int  iucv_sock_create(struct socket *sock, int proto);
+static int  iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
+			int addr_len);
+static int  iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
+			      int alen, int flags);
+static int  iucv_sock_listen(struct socket *sock, int backlog);
+static int  iucv_sock_accept(struct socket *sock, struct socket *newsock,
+			     int flags);
+static int  iucv_sock_getname(struct socket *sock, struct sockaddr *addr,
+			      int *len, int peer);
+static int  iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
+			      struct msghdr *msg, size_t len);
+static int  iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+			      struct msghdr *msg, size_t len, int flags);
+unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
+			    poll_table *wait);
+static int iucv_sock_release(struct socket *sock);
+static int iucv_sock_shutdown(struct socket *sock, int how);
+
+void iucv_sock_link(struct iucv_sock_list *l, struct sock *s);
+void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s);
+int  iucv_sock_wait_state(struct sock *sk, int state, int state2,
+			  unsigned long timeo);
+int  iucv_sock_wait_cnt(struct sock *sk, unsigned long timeo);
+void iucv_accept_enqueue(struct sock *parent, struct sock *sk);
+void iucv_accept_unlink(struct sock *sk);
+struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock);
+
+#endif /* __IUCV_H */

+ 415 - 0
include/net/iucv/iucv.h

@@ -0,0 +1,415 @@
+/*
+ *  drivers/s390/net/iucv.h
+ *    IUCV base support.
+ *
+ *  S390 version
+ *    Copyright 2000, 2006 IBM Corporation
+ *    Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
+ *		Xenia Tkatschow (xenia@us.ibm.com)
+ *    Rewritten for af_iucv:
+ *	Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *
+ *
+ * Functionality:
+ * To explore any of the IUCV functions, one must first register their
+ * program using iucv_register(). Once your program has successfully
+ * completed a register, it can exploit the other functions.
+ * For furthur reference on all IUCV functionality, refer to the
+ * CP Programming Services book, also available on the web thru
+ * www.ibm.com/s390/vm/pubs, manual # SC24-5760
+ *
+ * Definition of Return Codes
+ * - All positive return codes including zero are reflected back
+ *   from CP. The definition of each return code can be found in
+ *   CP Programming Services book.
+ * - Return Code of:
+ *   -EINVAL: Invalid value
+ *   -ENOMEM: storage allocation failed
+ */
+
+#include <linux/types.h>
+#include <asm/debug.h>
+
+/*
+ * IUCV option flags usable by device drivers:
+ *
+ * IUCV_IPRMDATA  Indicates that your program can handle a message in the
+ *		  parameter list / a message is sent in the parameter list.
+ *		  Used for iucv_path_accept, iucv_path_connect,
+ *		  iucv_message_reply, iucv_message_send, iucv_message_send2way.
+ * IUCV_IPQUSCE	  Indicates that you do not want to receive messages on this
+ *		  path until an iucv_path_resume is issued.
+ *		  Used for iucv_path_accept, iucv_path_connect.
+ * IUCV_IPBUFLST  Indicates that an address list is used for the message data.
+ *		  Used for iucv_message_receive, iucv_message_send,
+ *		  iucv_message_send2way.
+ * IUCV_IPPRTY	  Specifies that you want to send priority messages.
+ *		  Used for iucv_path_accept, iucv_path_connect,
+ *		  iucv_message_reply, iucv_message_send, iucv_message_send2way.
+ * IUCV_IPSYNC	  Indicates a synchronous send request.
+ *		  Used for iucv_message_send, iucv_message_send2way.
+ * IUCV_IPANSLST  Indicates that an address list is used for the reply data.
+ *		  Used for iucv_message_reply, iucv_message_send2way.
+ * IUCV_IPLOCAL	  Specifies that the communication partner has to be on the
+ *		  local system. If local is specified no target class can be
+ *		  specified.
+ *		  Used for iucv_path_connect.
+ *
+ * All flags are defined in the input field IPFLAGS1 of each function
+ * and can be found in CP Programming Services.
+ */
+#define IUCV_IPRMDATA	0x80
+#define IUCV_IPQUSCE	0x40
+#define IUCV_IPBUFLST	0x40
+#define IUCV_IPPRTY	0x20
+#define IUCV_IPANSLST	0x08
+#define IUCV_IPSYNC	0x04
+#define IUCV_IPLOCAL	0x01
+
+/*
+ * iucv_array : Defines buffer array.
+ * Inside the array may be 31- bit addresses and 31-bit lengths.
+ * Use a pointer to an iucv_array as the buffer, reply or answer
+ * parameter on iucv_message_send, iucv_message_send2way, iucv_message_receive
+ * and iucv_message_reply if IUCV_IPBUFLST or IUCV_IPANSLST are used.
+ */
+struct iucv_array {
+	u32 address;
+	u32 length;
+} __attribute__ ((aligned (8)));
+
+extern struct bus_type iucv_bus;
+extern struct device *iucv_root;
+
+/*
+ * struct iucv_path
+ * pathid: 16 bit path identification
+ * msglim: 16 bit message limit
+ * flags: properties of the path: IPRMDATA, IPQUSCE, IPPRTY
+ * handler:  address of iucv handler structure
+ * private: private information of the handler associated with the path
+ * list: list_head for the iucv_handler path list.
+ */
+struct iucv_path {
+	u16 pathid;
+	u16 msglim;
+	u8  flags;
+	void *private;
+	struct iucv_handler *handler;
+	struct list_head list;
+};
+
+/*
+ * struct iucv_message
+ * id: 32 bit message id
+ * audit: 32 bit error information of purged or replied messages
+ * class: 32 bit target class of a message (source class for replies)
+ * tag: 32 bit tag to be associated with the message
+ * length: 32 bit length of the message / reply
+ * reply_size: 32 bit maximum allowed length of the reply
+ * rmmsg: 8 byte inline message
+ * flags: message properties (IUCV_IPPRTY)
+ */
+struct iucv_message {
+	u32 id;
+	u32 audit;
+	u32 class;
+	u32 tag;
+	u32 length;
+	u32 reply_size;
+	u8  rmmsg[8];
+	u8  flags;
+};
+
+/*
+ * struct iucv_handler
+ *
+ * A vector of functions that handle IUCV interrupts. Each functions gets
+ * a parameter area as defined by the CP Programming Services and private
+ * pointer that is provided by the user of the interface.
+ */
+struct iucv_handler {
+	 /*
+	  * The path_pending function is called after an iucv interrupt
+	  * type 0x01 has been received. The base code allocates a path
+	  * structure and "asks" the handler if this path belongs to the
+	  * handler. To accept the path the path_pending function needs
+	  * to call iucv_path_accept and return 0. If the callback returns
+	  * a value != 0 the iucv base code will continue with the next
+	  * handler. The order in which the path_pending functions are
+	  * called is the order of the registration of the iucv handlers
+	  * to the base code.
+	  */
+	int  (*path_pending)(struct iucv_path *, u8 ipvmid[8], u8 ipuser[16]);
+	/*
+	 * The path_complete function is called after an iucv interrupt
+	 * type 0x02 has been received for a path that has been established
+	 * for this handler with iucv_path_connect and got accepted by the
+	 * peer with iucv_path_accept.
+	 */
+	void (*path_complete)(struct iucv_path *, u8 ipuser[16]);
+	 /*
+	  * The path_severed function is called after an iucv interrupt
+	  * type 0x03 has been received. The communication peer shutdown
+	  * his end of the communication path. The path still exists and
+	  * remaining messages can be received until a iucv_path_sever
+	  * shuts down the other end of the path as well.
+	  */
+	void (*path_severed)(struct iucv_path *, u8 ipuser[16]);
+	/*
+	 * The path_quiesced function is called after an icuv interrupt
+	 * type 0x04 has been received. The communication peer has quiesced
+	 * the path. Delivery of messages is stopped until iucv_path_resume
+	 * has been called.
+	 */
+	void (*path_quiesced)(struct iucv_path *, u8 ipuser[16]);
+	/*
+	 * The path_resumed function is called after an icuv interrupt
+	 * type 0x05 has been received. The communication peer has resumed
+	 * the path.
+	 */
+	void (*path_resumed)(struct iucv_path *, u8 ipuser[16]);
+	/*
+	 * The message_pending function is called after an icuv interrupt
+	 * type 0x06 or type 0x07 has been received. A new message is
+	 * availabe and can be received with iucv_message_receive.
+	 */
+	void (*message_pending)(struct iucv_path *, struct iucv_message *);
+	/*
+	 * The message_complete function is called after an icuv interrupt
+	 * type 0x08 or type 0x09 has been received. A message send with
+	 * iucv_message_send2way has been replied to. The reply can be
+	 * received with iucv_message_receive.
+	 */
+	void (*message_complete)(struct iucv_path *, struct iucv_message *);
+
+	struct list_head list;
+	struct list_head paths;
+};
+
+/**
+ * iucv_register:
+ * @handler: address of iucv handler structure
+ * @smp: != 0 indicates that the handler can deal with out of order messages
+ *
+ * Registers a driver with IUCV.
+ *
+ * Returns 0 on success, -ENOMEM if the memory allocation for the pathid
+ * table failed, or -EIO if IUCV_DECLARE_BUFFER failed on all cpus.
+ */
+int iucv_register(struct iucv_handler *handler, int smp);
+
+/**
+ * iucv_unregister
+ * @handler:  address of iucv handler structure
+ * @smp: != 0 indicates that the handler can deal with out of order messages
+ *
+ * Unregister driver from IUCV.
+ */
+void iucv_unregister(struct iucv_handler *handle, int smp);
+
+/**
+ * iucv_path_alloc
+ * @msglim: initial message limit
+ * @flags: initial flags
+ * @gfp: kmalloc allocation flag
+ *
+ * Allocate a new path structure for use with iucv_connect.
+ *
+ * Returns NULL if the memory allocation failed or a pointer to the
+ * path structure.
+ */
+static inline struct iucv_path *iucv_path_alloc(u16 msglim, u8 flags, gfp_t gfp)
+{
+	struct iucv_path *path;
+
+	path = kzalloc(sizeof(struct iucv_path), gfp);
+	if (path) {
+		path->msglim = msglim;
+		path->flags = flags;
+	}
+	return path;
+}
+
+/**
+ * iucv_path_free
+ * @path: address of iucv path structure
+ *
+ * Frees a path structure.
+ */
+static inline void iucv_path_free(struct iucv_path *path)
+{
+	kfree(path);
+}
+
+/**
+ * iucv_path_accept
+ * @path: address of iucv path structure
+ * @handler: address of iucv handler structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ * @private: private data passed to interrupt handlers for this path
+ *
+ * This function is issued after the user received a connection pending
+ * external interrupt and now wishes to complete the IUCV communication path.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
+		     u8 userdata[16], void *private);
+
+/**
+ * iucv_path_connect
+ * @path: address of iucv path structure
+ * @handler: address of iucv handler structure
+ * @userid: 8-byte user identification
+ * @system: 8-byte target system identification
+ * @userdata: 16 bytes of data reflected to the communication partner
+ * @private: private data passed to interrupt handlers for this path
+ *
+ * This function establishes an IUCV path. Although the connect may complete
+ * successfully, you are not able to use the path until you receive an IUCV
+ * Connection Complete external interrupt.
+ *
+ * Returns the result of the CP IUCV call.
+ */
+int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
+		      u8 userid[8], u8 system[8], u8 userdata[16],
+		      void *private);
+
+/**
+ * iucv_path_quiesce:
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function temporarily suspends incoming messages on an IUCV path.
+ * You can later reactivate the path by invoking the iucv_resume function.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_path_resume:
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function resumes incoming messages on an IUCV path that has
+ * been stopped with iucv_path_quiesce.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_resume(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_path_sever
+ * @path: address of iucv path structure
+ * @userdata: 16 bytes of data reflected to the communication partner
+ *
+ * This function terminates an IUCV path.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_path_sever(struct iucv_path *path, u8 userdata[16]);
+
+/**
+ * iucv_message_purge
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @srccls: source class of message
+ *
+ * Cancels a message you have sent.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
+		       u32 srccls);
+
+/**
+ * iucv_message_receive
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: flags that affect how the message is received (IUCV_IPBUFLST)
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of data buffer
+ * @residual:
+ *
+ * This function receives messages that are being sent to you over
+ * established paths. This function will deal with RMDATA messages
+ * embedded in struct iucv_message as well.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
+			 u8 flags, void *buffer, size_t size, size_t *residual);
+
+/**
+ * iucv_message_reject
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ *
+ * The reject function refuses a specified message. Between the time you
+ * are notified of a message and the time that you complete the message,
+ * the message may be rejected.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg);
+
+/**
+ * iucv_message_reply
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the reply is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @reply: address of data buffer or address of struct iucv_array
+ * @size: length of reply data buffer
+ *
+ * This function responds to the two-way messages that you receive. You
+ * must identify completely the message to which you wish to reply. ie,
+ * pathid, msgid, and trgcls. Prmmsg signifies the data is moved into
+ * the parameter list.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
+		       u8 flags, void *reply, size_t size);
+
+/**
+ * iucv_message_send
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent (IUCV_IPRMDATA, IUCV_IPPRTY, IUCV_IPBUFLST)
+ * @srccls: source class of message
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of send buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer and this is a one-way message and the
+ * receiver will not reply to the message.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
+		      u8 flags, u32 srccls, void *buffer, size_t size);
+
+/**
+ * iucv_message_send2way
+ * @path: address of iucv path structure
+ * @msg: address of iucv msg structure
+ * @flags: how the message is sent and the reply is received
+ *	   (IUCV_IPRMDATA, IUCV_IPBUFLST, IUCV_IPPRTY, IUCV_ANSLST)
+ * @srccls: source class of message
+ * @buffer: address of data buffer or address of struct iucv_array
+ * @size: length of send buffer
+ * @ansbuf: address of answer buffer or address of struct iucv_array
+ * @asize: size of reply buffer
+ *
+ * This function transmits data to another application. Data to be
+ * transmitted is in a buffer. The receiver of the send is expected to
+ * reply to the message and a buffer is provided into which IUCV moves
+ * the reply to this message.
+ *
+ * Returns the result from the CP IUCV call.
+ */
+int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
+			  u8 flags, u32 srccls, void *buffer, size_t size,
+			  void *answer, size_t asize, size_t *residual);

+ 2 - 0
include/net/netfilter/nf_conntrack.h

@@ -45,6 +45,7 @@ union nf_conntrack_expect_proto {
 #include <linux/netfilter/nf_conntrack_ftp.h>
 #include <linux/netfilter/nf_conntrack_pptp.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
+#include <linux/netfilter/nf_conntrack_sane.h>
 
 /* per conntrack: application helper private data */
 union nf_conntrack_help {
@@ -52,6 +53,7 @@ union nf_conntrack_help {
 	struct nf_ct_ftp_master ct_ftp_info;
 	struct nf_ct_pptp_master ct_pptp_info;
 	struct nf_ct_h323_master ct_h323_info;
+	struct nf_ct_sane_master ct_sane_info;
 };
 
 #include <linux/types.h>

+ 1 - 0
include/net/netfilter/nf_nat.h

@@ -16,6 +16,7 @@ enum nf_nat_manip_type
 
 #define IP_NAT_RANGE_MAP_IPS 1
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
+#define IP_NAT_RANGE_PROTO_RANDOM 4
 
 /* NAT sequence number modifications */
 struct nf_nat_seq {

+ 3 - 2
include/net/route.h

@@ -146,7 +146,8 @@ static inline char rt_tos2priority(u8 tos)
 
 static inline int ip_route_connect(struct rtable **rp, __be32 dst,
 				   __be32 src, u32 tos, int oif, u8 protocol,
-				   __be16 sport, __be16 dport, struct sock *sk)
+				   __be16 sport, __be16 dport, struct sock *sk,
+				   int flags)
 {
 	struct flowi fl = { .oif = oif,
 			    .nl_u = { .ip4_u = { .daddr = dst,
@@ -168,7 +169,7 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
 		*rp = NULL;
 	}
 	security_sk_classify_flow(sk, &fl);
-	return ip_route_output_flow(rp, &fl, sk, 0);
+	return ip_route_output_flow(rp, &fl, sk, flags);
 }
 
 static inline int ip_route_newports(struct rtable **rp, u8 protocol,

+ 2 - 3
include/net/tcp.h

@@ -802,9 +802,8 @@ static inline void tcp_update_wl(struct tcp_sock *tp, u32 ack, u32 seq)
 /*
  * Calculate(/check) TCP checksum
  */
-static inline __sum16 tcp_v4_check(struct tcphdr *th, int len,
-			       __be32 saddr, __be32 daddr,
-			       __wsum base)
+static inline __sum16 tcp_v4_check(int len, __be32 saddr,
+				   __be32 daddr, __wsum base)
 {
 	return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
 }

+ 18 - 0
include/net/x25.h

@@ -161,6 +161,14 @@ struct x25_sock {
 	unsigned long 		vc_facil_mask;	/* inc_call facilities mask */
 };
 
+struct x25_forward {
+	struct list_head	node;
+	unsigned int		lci;
+	struct net_device	*dev1;
+	struct net_device	*dev2;
+	atomic_t		refcnt;
+};
+
 static inline struct x25_sock *x25_sk(const struct sock *sk)
 {
 	return (struct x25_sock *)sk;
@@ -172,6 +180,7 @@ extern int  sysctl_x25_call_request_timeout;
 extern int  sysctl_x25_reset_request_timeout;
 extern int  sysctl_x25_clear_request_timeout;
 extern int  sysctl_x25_ack_holdback_timeout;
+extern int  sysctl_x25_forward;
 
 extern int  x25_addr_ntoa(unsigned char *, struct x25_address *,
 			  struct x25_address *);
@@ -198,6 +207,13 @@ extern int x25_negotiate_facilities(struct sk_buff *, struct sock *,
 				struct x25_dte_facilities *);
 extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
 
+/* x25_forward.c */
+extern void x25_clear_forward_by_lci(unsigned int lci);
+extern void x25_clear_forward_by_dev(struct net_device *);
+extern int x25_forward_data(int, struct x25_neigh *, struct sk_buff *);
+extern int x25_forward_call(struct x25_address *, struct x25_neigh *,
+				struct sk_buff *, int);
+
 /* x25_in.c */
 extern int  x25_process_rx_frame(struct sock *, struct sk_buff *);
 extern int  x25_backlog_rcv(struct sock *, struct sk_buff *);
@@ -282,6 +298,8 @@ extern struct hlist_head x25_list;
 extern rwlock_t x25_list_lock;
 extern struct list_head x25_route_list;
 extern rwlock_t x25_route_list_lock;
+extern struct list_head x25_forward_list;
+extern rwlock_t x25_forward_list_lock;
 
 extern int x25_proc_init(void);
 extern void x25_proc_exit(void);

+ 47 - 0
include/net/xfrm.h

@@ -252,10 +252,13 @@ struct xfrm_state_afinfo {
 						xfrm_address_t *daddr, xfrm_address_t *saddr);
 	int			(*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
 	int			(*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
+	int			(*output)(struct sk_buff *skb);
 };
 
 extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
 extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
+extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
+extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
 extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
@@ -359,6 +362,19 @@ struct xfrm_policy
 	struct xfrm_tmpl       	xfrm_vec[XFRM_MAX_DEPTH];
 };
 
+struct xfrm_migrate {
+	xfrm_address_t		old_daddr;
+	xfrm_address_t		old_saddr;
+	xfrm_address_t		new_daddr;
+	xfrm_address_t		new_saddr;
+	u8			proto;
+	u8			mode;
+	u16			reserved;
+	u32			reqid;
+	u16			old_family;
+	u16			new_family;
+};
+
 #define XFRM_KM_TIMEOUT                30
 /* which seqno */
 #define XFRM_REPLAY_SEQ		1
@@ -385,6 +401,7 @@ struct xfrm_mgr
 	int			(*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
 	int			(*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
 	int			(*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
+	int			(*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -985,6 +1002,16 @@ extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
 			  struct flowi *fl, int family, int strict);
 extern void xfrm_init_pmtu(struct dst_entry *dst);
 
+#ifdef CONFIG_XFRM_MIGRATE
+extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+		      struct xfrm_migrate *m, int num_bundles);
+extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m);
+extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
+					      struct xfrm_migrate *m);
+extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+			struct xfrm_migrate *m, int num_bundles);
+#endif
+
 extern wait_queue_head_t km_waitq;
 extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
 extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
@@ -1050,5 +1077,25 @@ static inline void xfrm_aevent_doreplay(struct xfrm_state *x)
 		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
 }
 
+#ifdef CONFIG_XFRM_MIGRATE
+static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
+{
+	return (struct xfrm_algo *)kmemdup(orig, sizeof(*orig) + orig->alg_key_len, GFP_KERNEL);
+}
+
+static inline void xfrm_states_put(struct xfrm_state **states, int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		xfrm_state_put(*(states + i));
+}
+
+static inline void xfrm_states_delete(struct xfrm_state **states, int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		xfrm_state_delete(*(states + i));
+}
+#endif
 
 #endif	/* _NET_XFRM_H */

+ 1 - 0
net/Kconfig

@@ -37,6 +37,7 @@ config NETDEBUG
 source "net/packet/Kconfig"
 source "net/unix/Kconfig"
 source "net/xfrm/Kconfig"
+source "net/iucv/Kconfig"
 
 config INET
 	bool "TCP/IP networking"

+ 1 - 0
net/Makefile

@@ -47,6 +47,7 @@ obj-$(CONFIG_IP_SCTP)		+= sctp/
 obj-$(CONFIG_IEEE80211)		+= ieee80211/
 obj-$(CONFIG_TIPC)		+= tipc/
 obj-$(CONFIG_NETLABEL)		+= netlabel/
+obj-$(CONFIG_IUCV)		+= iucv/
 
 ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_SYSCTL)		+= sysctl_net.o

+ 2 - 1
net/atm/common.c

@@ -816,7 +816,8 @@ static void __exit atm_exit(void)
 	proto_unregister(&vcc_proto);
 }
 
-module_init(atm_init);
+subsys_initcall(atm_init);
+
 module_exit(atm_exit);
 
 MODULE_LICENSE("GPL");

+ 7 - 22
net/bridge/br_netfilter.c

@@ -949,44 +949,29 @@ static ctl_table brnf_net_table[] = {
 };
 #endif
 
-int br_netfilter_init(void)
+int __init br_netfilter_init(void)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) {
-		int ret;
-
-		if ((ret = nf_register_hook(&br_nf_ops[i])) >= 0)
-			continue;
-
-		while (i--)
-			nf_unregister_hook(&br_nf_ops[i]);
+	int ret;
 
+	ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+	if (ret < 0)
 		return ret;
-	}
-
 #ifdef CONFIG_SYSCTL
 	brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0);
 	if (brnf_sysctl_header == NULL) {
 		printk(KERN_WARNING
 		       "br_netfilter: can't register to sysctl.\n");
-		for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++)
-			nf_unregister_hook(&br_nf_ops[i]);
-		return -EFAULT;
+		nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+		return -ENOMEM;
 	}
 #endif
-
 	printk(KERN_NOTICE "Bridge firewalling registered\n");
-
 	return 0;
 }
 
 void br_netfilter_fini(void)
 {
-	int i;
-
-	for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--)
-		nf_unregister_hook(&br_nf_ops[i]);
+	nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
 #ifdef CONFIG_SYSCTL
 	unregister_sysctl_table(brnf_sysctl_header);
 #endif

+ 9 - 5
net/bridge/br_netlink.c

@@ -45,7 +45,7 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	hdr = nlmsg_data(nlh);
 	hdr->ifi_family = AF_BRIDGE;
@@ -72,7 +72,8 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 /*
@@ -89,9 +90,12 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port)
 		goto errout;
 
 	err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
-	/* failure implies BUG in br_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in br_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
 errout:
 	if (err < 0)

+ 1 - 0
net/bridge/netfilter/ebt_ip.c

@@ -93,6 +93,7 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask,
 			return -EINVAL;
 		if (info->protocol != IPPROTO_TCP &&
 		    info->protocol != IPPROTO_UDP &&
+		    info->protocol != IPPROTO_UDPLITE &&
 		    info->protocol != IPPROTO_SCTP &&
 		    info->protocol != IPPROTO_DCCP)
 			 return -EINVAL;

+ 1 - 0
net/bridge/netfilter/ebt_log.c

@@ -96,6 +96,7 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum,
 		       NIPQUAD(ih->daddr), ih->tos, ih->protocol);
 		if (ih->protocol == IPPROTO_TCP ||
 		    ih->protocol == IPPROTO_UDP ||
+		    ih->protocol == IPPROTO_UDPLITE ||
 		    ih->protocol == IPPROTO_SCTP ||
 		    ih->protocol == IPPROTO_DCCP) {
 			struct tcpudphdr _ports, *pptr;

+ 5 - 8
net/core/dev.c

@@ -3247,7 +3247,7 @@ void synchronize_net(void)
  *	unregister_netdev() instead of this.
  */
 
-int unregister_netdevice(struct net_device *dev)
+void unregister_netdevice(struct net_device *dev)
 {
 	struct net_device *d, **dp;
 
@@ -3258,7 +3258,9 @@ int unregister_netdevice(struct net_device *dev)
 	if (dev->reg_state == NETREG_UNINITIALIZED) {
 		printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
 				  "was registered\n", dev->name, dev);
-		return -ENODEV;
+
+		WARN_ON(1);
+		return;
 	}
 
 	BUG_ON(dev->reg_state != NETREG_REGISTERED);
@@ -3280,11 +3282,7 @@ int unregister_netdevice(struct net_device *dev)
 			break;
 		}
 	}
-	if (!d) {
-		printk(KERN_ERR "unregister net_device: '%s' not found\n",
-		       dev->name);
-		return -ENODEV;
-	}
+	BUG_ON(!d);
 
 	dev->reg_state = NETREG_UNREGISTERING;
 
@@ -3316,7 +3314,6 @@ int unregister_netdevice(struct net_device *dev)
 	synchronize_net();
 
 	dev_put(dev);
-	return 0;
 }
 
 /**

+ 8 - 1
net/core/dst.c

@@ -99,7 +99,14 @@ static void dst_run_gc(unsigned long dummy)
 	printk("dst_total: %d/%d %ld\n",
 	       atomic_read(&dst_total), delayed,  dst_gc_timer_expires);
 #endif
-	mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
+	/* if the next desired timer is more than 4 seconds in the future
+	 * then round the timer to whole seconds
+	 */
+	if (dst_gc_timer_expires > 4*HZ)
+		mod_timer(&dst_gc_timer,
+			round_jiffies(jiffies + dst_gc_timer_expires));
+	else
+		mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
 
 out:
 	spin_unlock(&dst_lock);

+ 9 - 5
net/core/fib_rules.c

@@ -331,7 +331,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
 	if (nlh == NULL)
-		return -1;
+		return -EMSGSIZE;
 
 	frh = nlmsg_data(nlh);
 	frh->table = rule->table;
@@ -359,7 +359,8 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
@@ -405,9 +406,12 @@ static void notify_rule_change(int event, struct fib_rule *rule,
 		goto errout;
 
 	err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
-	/* failure implies BUG in fib_rule_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in fib_rule_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
 errout:
 	if (err < 0)

+ 19 - 10
net/core/neighbour.c

@@ -696,7 +696,10 @@ next_elt:
 	if (!expire)
 		expire = 1;
 
- 	mod_timer(&tbl->gc_timer, now + expire);
+	if (expire>HZ)
+		mod_timer(&tbl->gc_timer, round_jiffies(now + expire));
+	else
+		mod_timer(&tbl->gc_timer, now + expire);
 
 	write_unlock(&tbl->lock);
 }
@@ -1637,7 +1640,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ndtmsg = nlmsg_data(nlh);
 
@@ -1706,7 +1709,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
 
 nla_put_failure:
 	read_unlock_bh(&tbl->lock);
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int neightbl_fill_param_info(struct sk_buff *skb,
@@ -1720,7 +1724,7 @@ static int neightbl_fill_param_info(struct sk_buff *skb,
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ndtmsg = nlmsg_data(nlh);
 
@@ -1737,7 +1741,8 @@ static int neightbl_fill_param_info(struct sk_buff *skb,
 	return nlmsg_end(skb, nlh);
 errout:
 	read_unlock_bh(&tbl->lock);
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
  
 static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
@@ -1955,7 +1960,7 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ndm = nlmsg_data(nlh);
 	ndm->ndm_family	 = neigh->ops->family;
@@ -1987,7 +1992,8 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 
@@ -2429,9 +2435,12 @@ static void __neigh_notify(struct neighbour *n, int type, int flags)
 		goto errout;
 
 	err = neigh_fill_info(skb, n, 0, 0, type, flags);
-	/* failure implies BUG in neigh_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
 errout:
 	if (err < 0)

+ 15 - 8
net/core/rtnetlink.c

@@ -320,7 +320,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ifm = nlmsg_data(nlh);
 	ifm->ifi_family = AF_UNSPEC;
@@ -384,7 +384,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
@@ -633,9 +634,12 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
 	err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
 			       NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
-	/* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in if_nlmsg_size */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(nskb);
+		goto errout;
+	}
 	err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
 errout:
 	kfree(iw_buf);
@@ -678,9 +682,12 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
 		goto errout;
 
 	err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
-	/* failure implies BUG in if_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in if_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
 errout:
 	if (err < 0)

+ 3 - 2
net/dccp/ccids/ccid3.c

@@ -479,7 +479,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 
 			ccid3_pr_debug("%s(%p), s=%u, w_init=%llu, "
 				       "R_sample=%dus, X=%u\n", dccp_role(sk),
-				       sk, hctx->ccid3hctx_s, w_init,
+				       sk, hctx->ccid3hctx_s,
+				       (unsigned long long)w_init,
 				       (int)r_sample,
 				       (unsigned)(hctx->ccid3hctx_x >> 6));
 
@@ -1005,7 +1006,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
 		DCCP_BUG_ON(r_sample < 0);
 		if (unlikely(r_sample <= t_elapsed))
 			DCCP_WARN("r_sample=%ldus, t_elapsed=%ldus\n",
-				  r_sample, t_elapsed);
+				  (long)r_sample, (long)t_elapsed);
 		else
 			r_sample -= t_elapsed;
 		CCID3_RTT_SANITY_CHECK(r_sample);

+ 1 - 1
net/dccp/ipv4.c

@@ -72,7 +72,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	tmp = ip_route_connect(&rt, nexthop, inet->saddr,
 			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
 			       IPPROTO_DCCP,
-			       inet->sport, usin->sin_port, sk);
+			       inet->sport, usin->sin_port, sk, 1);
 	if (tmp < 0)
 		return tmp;
 

+ 1 - 1
net/dccp/ipv6.c

@@ -1041,7 +1041,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-	err = xfrm_lookup(&dst, &fl, sk, 0);
+	err = xfrm_lookup(&dst, &fl, sk, 1);
 	if (err < 0)
 		goto failure;
 

+ 2 - 2
net/dccp/proto.c

@@ -1024,7 +1024,6 @@ static int __init dccp_init(void)
 	do {
 		dccp_hashinfo.ehash_size = (1UL << ehash_order) * PAGE_SIZE /
 					sizeof(struct inet_ehash_bucket);
-		dccp_hashinfo.ehash_size >>= 1;
 		while (dccp_hashinfo.ehash_size &
 		       (dccp_hashinfo.ehash_size - 1))
 			dccp_hashinfo.ehash_size--;
@@ -1037,9 +1036,10 @@ static int __init dccp_init(void)
 		goto out_free_bind_bucket_cachep;
 	}
 
-	for (i = 0; i < (dccp_hashinfo.ehash_size << 1); i++) {
+	for (i = 0; i < dccp_hashinfo.ehash_size; i++) {
 		rwlock_init(&dccp_hashinfo.ehash[i].lock);
 		INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain);
+		INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].twchain);
 	}
 
 	bhash_order = ehash_order;

+ 9 - 5
net/decnet/dn_dev.c

@@ -749,7 +749,7 @@ static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ifm = nlmsg_data(nlh);
 	ifm->ifa_family = AF_DECnet;
@@ -768,7 +768,8 @@ static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
@@ -781,9 +782,12 @@ static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
 		goto errout;
 
 	err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
-	/* failure implies BUG in dn_ifaddr_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in dn_ifaddr_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
 errout:
 	if (err < 0)

+ 7 - 4
net/decnet/dn_table.c

@@ -350,7 +350,7 @@ static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 nlmsg_failure:
 rtattr_failure:
         skb_trim(skb, b - skb->data);
-        return -1;
+        return -EMSGSIZE;
 }
 
 
@@ -368,9 +368,12 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
         err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
 			       f->fn_type, f->fn_scope, &f->fn_key, z,
 			       DN_FIB_INFO(f), 0);
-	/* failure implies BUG in dn_fib_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in dn_fib_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
 errout:
 	if (err < 0)

+ 1 - 1
net/ipv4/af_inet.c

@@ -1007,7 +1007,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)
 			       RT_CONN_FLAGS(sk),
 			       sk->sk_bound_dev_if,
 			       sk->sk_protocol,
-			       inet->sport, inet->dport, sk);
+			       inet->sport, inet->dport, sk, 0);
 	if (err)
 		return err;
 

+ 1 - 1
net/ipv4/datagram.c

@@ -49,7 +49,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
 			       RT_CONN_FLAGS(sk), oif,
 			       sk->sk_protocol,
-			       inet->sport, usin->sin_port, sk);
+			       inet->sport, usin->sin_port, sk, 1);
 	if (err)
 		return err;
 	if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {

+ 9 - 5
net/ipv4/devinet.c

@@ -1140,7 +1140,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	ifm = nlmsg_data(nlh);
 	ifm->ifa_family = AF_INET;
@@ -1167,7 +1167,8 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
@@ -1225,9 +1226,12 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
 		goto errout;
 
 	err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
-	/* failure implies BUG in inet_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in inet_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
 errout:
 	if (err < 0)

+ 9 - 5
net/ipv4/fib_semantics.c

@@ -314,9 +314,12 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
 	err = fib_dump_info(skb, info->pid, seq, event, tb_id,
 			    fa->fa_type, fa->fa_scope, key, dst_len,
 			    fa->fa_tos, fa->fa_info, 0);
-	/* failure implies BUG in fib_nlmsg_size() */
-	BUG_ON(err < 0);
-
+	if (err < 0) {
+		/* -EMSGSIZE implies BUG in fib_nlmsg_size() */
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(skb);
+		goto errout;
+	}
 	err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
 			  info->nlh, GFP_KERNEL);
 errout:
@@ -960,7 +963,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 	rtm = nlmsg_data(nlh);
 	rtm->rtm_family = AF_INET;
@@ -1031,7 +1034,8 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 	return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-	return nlmsg_cancel(skb, nlh);
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 /*

+ 2 - 0
net/ipv4/igmp.c

@@ -455,6 +455,8 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
 			skb = add_grhead(skb, pmc, type, &pgr);
 			first = 0;
 		}
+		if (!skb)
+			return NULL;
 		psrc = (__be32 *)skb_put(skb, sizeof(__be32));
 		*psrc = psf->sf_inaddr;
 		scount++; stotal++;

+ 11 - 8
net/ipv4/inet_diag.c

@@ -153,7 +153,7 @@ static int inet_csk_diag_fill(struct sock *sk,
 rtattr_failure:
 nlmsg_failure:
 	skb_trim(skb, b - skb->data);
-	return -1;
+	return -EMSGSIZE;
 }
 
 static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
@@ -209,7 +209,7 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 	return skb->len;
 nlmsg_failure:
 	skb_trim(skb, previous_tail - skb->data);
-	return -1;
+	return -EMSGSIZE;
 }
 
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
@@ -274,11 +274,14 @@ static int inet_diag_get_exact(struct sk_buff *in_skb,
 	if (!rep)
 		goto out;
 
-	if (sk_diag_fill(sk, rep, req->idiag_ext,
-			 NETLINK_CB(in_skb).pid,
-			 nlh->nlmsg_seq, 0, nlh) <= 0)
-		BUG();
-
+	err = sk_diag_fill(sk, rep, req->idiag_ext,
+			   NETLINK_CB(in_skb).pid,
+			   nlh->nlmsg_seq, 0, nlh);
+	if (err < 0) {
+		WARN_ON(err == -EMSGSIZE);
+		kfree_skb(rep);
+		goto out;
+	}
 	err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid,
 			      MSG_DONTWAIT);
 	if (err > 0)
@@ -775,7 +778,7 @@ next_normal:
 			struct inet_timewait_sock *tw;
 
 			inet_twsk_for_each(tw, node,
-				    &hashinfo->ehash[i + hashinfo->ehash_size].chain) {
+				    &head->twchain) {
 
 				if (num < s_num)
 					goto next_dying;

+ 1 - 1
net/ipv4/inet_hashtables.c

@@ -212,7 +212,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
 	write_lock(&head->lock);
 
 	/* Check TIME-WAIT sockets first. */
-	sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {
+	sk_for_each(sk2, node, &head->twchain) {
 		tw = inet_twsk(sk2);
 
 		if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {

+ 2 - 2
net/ipv4/inet_timewait_sock.c

@@ -78,8 +78,8 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 	if (__sk_del_node_init(sk))
 		sock_prot_dec_use(sk->sk_prot);
 
-	/* Step 3: Hash TW into TIMEWAIT half of established hash table. */
-	inet_twsk_add_node(tw, &(ehead + hashinfo->ehash_size)->chain);
+	/* Step 3: Hash TW into TIMEWAIT chain. */
+	inet_twsk_add_node(tw, &ehead->twchain);
 	atomic_inc(&tw->tw_refcnt);
 
 	write_unlock(&ehead->lock);

+ 2 - 1
net/ipv4/ip_gre.c

@@ -1008,7 +1008,8 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 				goto done;
 			dev = t->dev;
 		}
-		err = unregister_netdevice(dev);
+		unregister_netdevice(dev);
+		err = 0;
 		break;
 
 	default:

+ 2 - 1
net/ipv4/ipip.c

@@ -754,7 +754,8 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 				goto done;
 			dev = t->dev;
 		}
-		err = unregister_netdevice(dev);
+		unregister_netdevice(dev);
+		err = 0;
 		break;
 
 	default:

+ 0 - 26
net/ipv4/netfilter/Kconfig

@@ -361,32 +361,6 @@ config IP_NF_TARGET_ULOG
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_TARGET_TCPMSS
-	tristate "TCPMSS target support"
-	depends on IP_NF_IPTABLES
-	---help---
-	  This option adds a `TCPMSS' target, which allows you to alter the
-	  MSS value of TCP SYN packets, to control the maximum size for that
-	  connection (usually limiting it to your outgoing interface's MTU
-	  minus 40).
-
-	  This is used to overcome criminally braindead ISPs or servers which
-	  block ICMP Fragmentation Needed packets.  The symptoms of this
-	  problem are that everything works fine from your Linux
-	  firewall/router, but machines behind it can never exchange large
-	  packets:
-	  	1) Web browsers connect, then hang with no data received.
-	  	2) Small mail works fine, but large emails hang.
-	  	3) ssh works fine, but scp hangs after initial handshaking.
-
-	  Workaround: activate this option and add a rule to your firewall
-	  configuration like:
-
-	  iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-	  		 -j TCPMSS --clamp-mss-to-pmtu
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
 # NAT + specific targets: ip_conntrack
 config IP_NF_NAT
 	tristate "Full NAT"

+ 0 - 1
net/ipv4/netfilter/Makefile

@@ -103,7 +103,6 @@ obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
-obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
 

+ 15 - 25
net/ipv4/netfilter/ip_conntrack_proto_tcp.c

@@ -50,12 +50,9 @@ static DEFINE_RWLOCK(tcp_lock);
     If it's non-zero, we mark only out of window RST segments as INVALID. */
 int ip_ct_tcp_be_liberal __read_mostly = 0;
 
-/* When connection is picked up from the middle, how many packets are required
-   to pass in each direction when we assume we are in sync - if any side uses
-   window scaling, we lost the game. 
-   If it is set to zero, we disable picking up already established 
+/* If it is set to zero, we disable picking up already established
    connections. */
-int ip_ct_tcp_loose __read_mostly = 3;
+int ip_ct_tcp_loose __read_mostly = 1;
 
 /* Max number of the retransmitted packets without receiving an (acceptable) 
    ACK from the destination. If this number is reached, a shorter timer 
@@ -694,11 +691,10 @@ static int tcp_in_window(struct ip_ct_tcp *state,
 	    	before(sack, receiver->td_end + 1),
 	    	after(ack, receiver->td_end - MAXACKWINDOW(sender)));
 	
-	if (sender->loose || receiver->loose ||
-	    (before(seq, sender->td_maxend + 1) &&
-	     after(end, sender->td_end - receiver->td_maxwin - 1) &&
-	     before(sack, receiver->td_end + 1) &&
-	     after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
+	if (before(seq, sender->td_maxend + 1) &&
+	    after(end, sender->td_end - receiver->td_maxwin - 1) &&
+	    before(sack, receiver->td_end + 1) &&
+	    after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
 	    	/*
 		 * Take into account window scaling (RFC 1323).
 		 */
@@ -743,15 +739,13 @@ static int tcp_in_window(struct ip_ct_tcp *state,
 				state->retrans = 0;
 			}
 		}
-		/*
-		 * Close the window of disabled window tracking :-)
-		 */
-		if (sender->loose)
-			sender->loose--;
-		
 		res = 1;
 	} else {
-		if (LOG_INVALID(IPPROTO_TCP))
+		res = 0;
+		if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
+		    ip_ct_tcp_be_liberal)
+			res = 1;
+		if (!res && LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
 			"ip_ct_tcp: %s ",
 			before(seq, sender->td_maxend + 1) ?
@@ -762,8 +756,6 @@ static int tcp_in_window(struct ip_ct_tcp *state,
 			: "ACK is over the upper bound (ACKed data not seen yet)"
 			: "SEQ is under the lower bound (already ACKed data retransmitted)"
 			: "SEQ is over the upper bound (over the window of the receiver)");
-
-		res = ip_ct_tcp_be_liberal;
   	}
   
 	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
@@ -1105,8 +1097,6 @@ static int tcp_new(struct ip_conntrack *conntrack,
 
 		tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]);
 		conntrack->proto.tcp.seen[1].flags = 0;
-		conntrack->proto.tcp.seen[0].loose = 
-		conntrack->proto.tcp.seen[1].loose = 0;
 	} else if (ip_ct_tcp_loose == 0) {
 		/* Don't try to pick up connections. */
 		return 0;
@@ -1127,11 +1117,11 @@ static int tcp_new(struct ip_conntrack *conntrack,
 			conntrack->proto.tcp.seen[0].td_maxwin;
 		conntrack->proto.tcp.seen[0].td_scale = 0;
 
-		/* We assume SACK. Should we assume window scaling too? */
+		/* We assume SACK and liberal window checking to handle
+		 * window scaling */
 		conntrack->proto.tcp.seen[0].flags =
-		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
-		conntrack->proto.tcp.seen[0].loose = 
-		conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
+		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM |
+						     IP_CT_TCP_FLAG_BE_LIBERAL;
 	}
     
 	conntrack->proto.tcp.seen[1].td_end = 0;

+ 10 - 2
net/ipv4/netfilter/ip_nat_core.c

@@ -246,8 +246,9 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
 	if (maniptype == IP_NAT_MANIP_SRC) {
 		if (find_appropriate_src(orig_tuple, tuple, range)) {
 			DEBUGP("get_unique_tuple: Found current src map\n");
-			if (!ip_nat_used_tuple(tuple, conntrack))
-				return;
+			if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
+				if (!ip_nat_used_tuple(tuple, conntrack))
+					return;
 		}
 	}
 
@@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
 
 	proto = ip_nat_proto_find_get(orig_tuple->dst.protonum);
 
+	/* Change protocol info to have some randomization */
+	if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) {
+		proto->unique_tuple(tuple, range, maniptype, conntrack);
+		ip_nat_proto_put(proto);
+		return;
+	}
+
 	/* Only bother mapping if it's not already in range and unique */
 	if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
 	     || proto->in_range(tuple, maniptype, &range->min, &range->max))

+ 1 - 1
net/ipv4/netfilter/ip_nat_helper.c

@@ -183,7 +183,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
 	datalen = (*pskb)->len - iph->ihl*4;
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		tcph->check = 0;
-		tcph->check = tcp_v4_check(tcph, datalen,
+		tcph->check = tcp_v4_check(datalen,
 					   iph->saddr, iph->daddr,
 					   csum_partial((char *)tcph,
 					   		datalen, 0));

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác