Quellcode durchsuchen

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 vor 18 Jahren
Ursprung
Commit
f049274b01
100 geänderte Dateien mit 4914 neuen und 5039 gelöschten Zeilen
  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)
   Kartikey Mahendra Bhatt (CAST6)
   Jon Oberheide (ARC4)
   Jon Oberheide (ARC4)
   Jouni Malinen (Michael MIC)
   Jouni Malinen (Michael MIC)
+  NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
 
 
 SHA1 algorithm contributors:
 SHA1 algorithm contributors:
   Jean-Francois Dive
   Jean-Francois Dive
@@ -246,6 +247,9 @@ Tiger algorithm contributors:
 VIA PadLock contributors:
 VIA PadLock contributors:
   Michal Ludvig
   Michal Ludvig
 
 
+Camellia algorithm contributors:
+  NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
+
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 
 Please send any credits updates or corrections to:
 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_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_NET_KEY=y
 CONFIG_NET_KEY=y
+CONFIG_IUCV=m
+CONFIG_AFIUCV=m
 CONFIG_INET=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -508,7 +510,6 @@ CONFIG_NET_ETHERNET=y
 #
 #
 CONFIG_LCS=m
 CONFIG_LCS=m
 CONFIG_CTC=m
 CONFIG_CTC=m
-CONFIG_IUCV=m
 # CONFIG_NETIUCV is not set
 # CONFIG_NETIUCV is not set
 # CONFIG_SMSGIUCV is not set
 # CONFIG_SMSGIUCV is not set
 # CONFIG_CLAW is not set
 # CONFIG_CLAW is not set

+ 31 - 0
crypto/Kconfig

@@ -149,6 +149,15 @@ config CRYPTO_CBC
 	  CBC: Cipher Block Chaining mode
 	  CBC: Cipher Block Chaining mode
 	  This block cipher algorithm is required for IPSec.
 	  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
 config CRYPTO_LRW
 	tristate "LRW support (EXPERIMENTAL)"
 	tristate "LRW support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	depends on EXPERIMENTAL
@@ -168,6 +177,13 @@ config CRYPTO_DES
 	help
 	help
 	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 	  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
 config CRYPTO_BLOWFISH
 	tristate "Blowfish cipher algorithm"
 	tristate "Blowfish cipher algorithm"
 	select CRYPTO_ALGAPI
 	select CRYPTO_ALGAPI
@@ -409,6 +425,21 @@ config CRYPTO_CRC32C
 	  See Castagnoli93.  This implementation uses lib/libcrc32c.
 	  See Castagnoli93.  This implementation uses lib/libcrc32c.
           Module will be crc32c.
           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
 config CRYPTO_TEST
 	tristate "Testing module"
 	tristate "Testing module"
 	depends on m
 	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_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
+obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
 obj-$(CONFIG_CRYPTO_AES) += aes.o
 obj-$(CONFIG_CRYPTO_AES) += aes.o
+obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
 obj-$(CONFIG_CRYPTO_ARC4) += arc4.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);
 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 *alg;
 	struct crypto_alg *alg2;
 	struct crypto_alg *alg2;
@@ -396,10 +397,18 @@ struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
 		return ERR_PTR(-EAGAIN);
 		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))
 	if (IS_ERR(tfm))
-		crypto_mod_put(alg);
+		goto out_put_alg;
+
+	return tfm;
 
 
+out_put_alg:
+	crypto_mod_put(alg);
 	return tfm;
 	return tfm;
 }
 }
 EXPORT_SYMBOL_GPL(crypto_spawn_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);
 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)) {
 	switch (crypto_tfm_alg_type(tfm)) {
 	case CRYPTO_ALG_TYPE_CIPHER:
 	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;
 	unsigned int len;
 
 
 	len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
 	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) {
 	switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
 	default:
 	default:
 		BUG();
 		BUG();
 
 
 	case CRYPTO_ALG_TYPE_CIPHER:
 	case CRYPTO_ALG_TYPE_CIPHER:
-		len += crypto_cipher_ctxsize(alg, flags);
+		len += crypto_cipher_ctxsize(alg);
 		break;
 		break;
 		
 		
 	case CRYPTO_ALG_TYPE_DIGEST:
 	case CRYPTO_ALG_TYPE_DIGEST:
-		len += crypto_digest_ctxsize(alg, flags);
+		len += crypto_digest_ctxsize(alg);
 		break;
 		break;
 		
 		
 	case CRYPTO_ALG_TYPE_COMPRESS:
 	case CRYPTO_ALG_TYPE_COMPRESS:
-		len += crypto_compress_ctxsize(alg, flags);
+		len += crypto_compress_ctxsize(alg);
 		break;
 		break;
 	}
 	}
 
 
@@ -322,24 +303,21 @@ void crypto_shoot_alg(struct crypto_alg *alg)
 }
 }
 EXPORT_SYMBOL_GPL(crypto_shoot_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;
 	struct crypto_tfm *tfm = NULL;
 	unsigned int tfm_size;
 	unsigned int tfm_size;
 	int err = -ENOMEM;
 	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);
 	tfm = kzalloc(tfm_size, GFP_KERNEL);
 	if (tfm == NULL)
 	if (tfm == NULL)
 		goto out_err;
 		goto out_err;
 
 
 	tfm->__crt_alg = alg;
 	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)
 	if (err)
 		goto out_free_tfm;
 		goto out_free_tfm;
 
 
@@ -362,31 +340,6 @@ out:
 }
 }
 EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
 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
  *	crypto_alloc_base - Locate algorithm and allocate transform
  *	@alg_name: Name of algorithm
  *	@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;
 			goto err;
 		}
 		}
 
 
-		tfm = __crypto_alloc_tfm(alg, 0);
+		tfm = __crypto_alloc_tfm(alg, type, mask);
 		if (!IS_ERR(tfm))
 		if (!IS_ERR(tfm))
 			return tfm;
 			return tfm;
 
 
@@ -466,7 +419,6 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
 	kfree(tfm);
 	kfree(tfm);
 }
 }
 
 
-EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
 EXPORT_SYMBOL_GPL(crypto_free_tfm);
 EXPORT_SYMBOL_GPL(crypto_free_tfm);
 
 
 int crypto_has_alg(const char *name, u32 type, u32 mask)
 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/crypto.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
 #include <linux/scatterlist.h>
@@ -313,6 +314,9 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
 	struct crypto_blkcipher *tfm = desc->tfm;
 	struct crypto_blkcipher *tfm = desc->tfm;
 	unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
 	unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
 
 
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
 	walk->nbytes = walk->total;
 	walk->nbytes = walk->total;
 	if (unlikely(!walk->total))
 	if (unlikely(!walk->total))
 		return 0;
 		return 0;
@@ -345,7 +349,8 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key,
 	return cipher->setkey(tfm, key, keylen);
 	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;
 	struct blkcipher_alg *cipher = &alg->cra_blkcipher;
 	unsigned int len = alg->cra_ctxsize;
 	unsigned int len = alg->cra_ctxsize;
@@ -358,7 +363,7 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg)
 	return len;
 	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_tfm *crt = &tfm->crt_blkcipher;
 	struct blkcipher_alg *alg = &tfm->__crt_alg->cra_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_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
 	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_cipher *cipher;
 
 
 	switch (crypto_tfm_alg_blocksize(tfm)) {
 	switch (crypto_tfm_alg_blocksize(tfm)) {
 	case 8:
 	case 8:
@@ -260,11 +261,11 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
 			ctx->xor = xor_quad;
 			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;
 	return 0;
 }
 }
 
 

+ 3 - 444
crypto/cipher.c

@@ -12,274 +12,13 @@
  * any later version.
  * any later version.
  *
  *
  */
  */
-#include <linux/compiler.h>
+
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/crypto.h>
 #include <linux/crypto.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
+#include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <linux/string.h>
-#include <asm/scatterlist.h>
 #include "internal.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)
 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);
 		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 *,
 static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
 					      const u8 *),
 					      const u8 *),
 				   struct crypto_tfm *tfm,
 				   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 crypto_init_cipher_ops(struct crypto_tfm *tfm)
 {
 {
-	int ret = 0;
 	struct cipher_tfm *ops = &tfm->crt_cipher;
 	struct cipher_tfm *ops = &tfm->crt_cipher;
 	struct cipher_alg *cipher = &tfm->__crt_alg->cra_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) ?
 	ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ?
 		cipher_decrypt_unaligned : cipher->cia_decrypt;
 		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)
 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);
 	                                                   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)
 int crypto_init_compress_ops(struct crypto_tfm *tfm)
 {
 {
 	struct compress_tfm *ops = &tfm->crt_compress;
 	struct compress_tfm *ops = &tfm->crt_compress;

+ 16 - 8
crypto/digest.c

@@ -14,7 +14,9 @@
 
 
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 #include <linux/highmem.h>
 #include <linux/highmem.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
 #include <linux/scatterlist.h>
 
 
@@ -29,8 +31,8 @@ static int init(struct hash_desc *desc)
 	return 0;
 	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);
 	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
 	unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
 	unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
@@ -81,6 +83,14 @@ static int update(struct hash_desc *desc,
 	return 0;
 	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)
 static int final(struct hash_desc *desc, u8 *out)
 {
 {
 	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
 	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,
 static int digest(struct hash_desc *desc,
 		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
 		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
 {
 {
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
 	init(desc);
 	init(desc);
-	update(desc, sg, nbytes);
+	update2(desc, sg, nbytes);
 	return final(desc, out);
 	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)
 int crypto_init_digest_ops(struct crypto_tfm *tfm)
 {
 {
 	struct hash_tfm *ops = &tfm->crt_hash;
 	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_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm);
 	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;
 	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"
 #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;
 	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_tfm *crt = &tfm->crt_hash;
 	struct hash_alg *alg = &tfm->__crt_alg->cra_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)
 static int hmac_init_tfm(struct crypto_tfm *tfm)
 {
 {
+	struct crypto_hash *hash;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
 	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;
 	return 0;
 }
 }
 
 

+ 6 - 21
crypto/internal.h

@@ -83,8 +83,7 @@ static inline void crypto_exit_proc(void)
 { }
 { }
 #endif
 #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;
 	unsigned int len = alg->cra_ctxsize;
 
 
@@ -96,23 +95,12 @@ static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
 	return len;
 	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;
 	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_lookup(const char *name, u32 type, u32 mask);
 struct crypto_alg *crypto_alg_mod_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_digest_ops(struct crypto_tfm *tfm);
 int crypto_init_cipher_ops(struct crypto_tfm *tfm);
 int crypto_init_cipher_ops(struct crypto_tfm *tfm);
 int crypto_init_compress_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_larval_error(const char *name, u32 type, u32 mask);
 
 
 void crypto_shoot_alg(struct crypto_alg *alg);
 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,
 int crypto_register_instance(struct crypto_template *tmpl,
 			     struct crypto_instance *inst);
 			     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)
 static int init_tfm(struct crypto_tfm *tfm)
 {
 {
+	struct crypto_cipher *cipher;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct priv *ctx = crypto_tfm_ctx(tfm);
 	struct priv *ctx = crypto_tfm_ctx(tfm);
 	u32 *flags = &tfm->crt_flags;
 	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;
 		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	return 0;
 	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)
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  * 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>)
  * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
  * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
  * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
  *
  *
@@ -71,7 +72,8 @@ static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
 	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
 	"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)
 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);
 	memcpy(tvmem, deflate_comp_tv_template, tsize);
 	tv = (void *)tvmem;
 	tv = (void *)tvmem;
 
 
-	tfm = crypto_alloc_tfm("deflate", 0);
+	tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC);
 	if (tfm == NULL) {
 	if (tfm == NULL) {
 		printk("failed to load transform for deflate\n");
 		printk("failed to load transform for deflate\n");
 		return;
 		return;
@@ -964,6 +966,26 @@ static void do_test(void)
 		test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template,
 		test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template,
 			    XETA_DEC_TEST_VECTORS);
 			    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("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
@@ -980,6 +1002,10 @@ static void do_test(void)
 			  HMAC_SHA1_TEST_VECTORS);
 			  HMAC_SHA1_TEST_VECTORS);
 		test_hash("hmac(sha256)", hmac_sha256_tv_template,
 		test_hash("hmac(sha256)", hmac_sha256_tv_template,
 			  HMAC_SHA256_TEST_VECTORS);
 			  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,
 		test_hash("xcbc(aes)", aes_xcbc128_tv_template,
 			  XCBC_AES_TEST_VECTORS);
 			  XCBC_AES_TEST_VECTORS);
@@ -1177,6 +1203,28 @@ static void do_test(void)
 			    XETA_DEC_TEST_VECTORS);
 			    XETA_DEC_TEST_VECTORS);
 		break;
 		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:
 	case 100:
 		test_hash("hmac(md5)", hmac_md5_tv_template,
 		test_hash("hmac(md5)", hmac_md5_tv_template,
 			  HMAC_MD5_TEST_VECTORS);
 			  HMAC_MD5_TEST_VECTORS);
@@ -1192,6 +1240,16 @@ static void do_test(void)
 			  HMAC_SHA256_TEST_VECTORS);
 			  HMAC_SHA256_TEST_VECTORS);
 		break;
 		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:
 	case 200:
 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
@@ -1260,6 +1318,17 @@ static void do_test(void)
 				  des_speed_template);
 				  des_speed_template);
 		break;
 		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:
 	case 300:
 		/* fall through */
 		/* fall through */
 
 

+ 537 - 1
crypto/tcrypt.h

@@ -12,6 +12,7 @@
  * Software Foundation; either version 2 of the License, or (at your option)
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  * 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>
  * 2004-08-09 Cipher speed tests by Reyk Floeter <reyk@vantronix.net>
  * 2003-09-14 Changes by Kartikey Mahendra Bhatt
  * 2003-09-14 Changes by Kartikey Mahendra Bhatt
  *
  *
@@ -27,7 +28,7 @@
 
 
 struct hash_testvec {
 struct hash_testvec {
 	/* only used with keyed hash algorithms */
 	/* only used with keyed hash algorithms */
-	char key[128] __attribute__ ((__aligned__(4)));
+	char key[132] __attribute__ ((__aligned__(4)));
 	char plaintext[240];
 	char plaintext[240];
 	char digest[MAX_DIGEST_SIZE];
 	char digest[MAX_DIGEST_SIZE];
 	unsigned char tap[MAX_TAP];
 	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.
  * 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.
  * Compression stuff.
  */
  */
@@ -3769,4 +4284,25 @@ static struct hash_speed generic_hash_speed_template[] = {
 	{  .blen = 0,	.plen = 0, }
 	{  .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 */
 #endif	/* _CRYPTO_TCRYPT_H */

+ 38 - 22
crypto/xcbc.c

@@ -21,6 +21,7 @@
 
 
 #include <linux/crypto.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
 #include <linux/err.h>
+#include <linux/hardirq.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/mm.h>
 #include <linux/rtnetlink.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_xcbc_ctx {
-	struct crypto_tfm *child;
+	struct crypto_cipher *child;
 	u8 *odds;
 	u8 *odds;
 	u8 *prev;
 	u8 *prev;
 	u8 *key;
 	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)))
 	if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen)))
 	    return err;
 	    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);
 	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);
 	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;
 		return -EINVAL;
 
 
 	ctx->keylen = keylen;
 	ctx->keylen = keylen;
@@ -108,13 +108,13 @@ static int crypto_xcbc_digest_init(struct hash_desc *pdesc)
 	return 0;
 	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_hash *parent = pdesc->tfm;
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
 	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 bs = crypto_hash_blocksize(parent);
 	unsigned int i = 0;
 	unsigned int i = 0;
 
 
@@ -142,7 +142,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 					offset += len;
 					offset += len;
 
 
 				crypto_kunmap(p, 0);
 				crypto_kunmap(p, 0);
-				crypto_yield(tfm->crt_flags);
+				crypto_yield(pdesc->flags);
 				continue;
 				continue;
 			}
 			}
 
 
@@ -152,7 +152,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 			p += bs - ctx->len;
 			p += bs - ctx->len;
 
 
 			ctx->xor(ctx->prev, ctx->odds, bs);
 			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 */
 			/* clearing the length */
 			ctx->len = 0;
 			ctx->len = 0;
@@ -160,7 +160,8 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 			/* encrypting the rest of data */
 			/* encrypting the rest of data */
 			while (len > bs) {
 			while (len > bs) {
 				ctx->xor(ctx->prev, p, 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;
 				p += bs;
 				len -= bs;
 				len -= bs;
 			}
 			}
@@ -171,7 +172,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 				ctx->len = len;
 				ctx->len = len;
 			}
 			}
 			crypto_kunmap(p, 0);
 			crypto_kunmap(p, 0);
-			crypto_yield(tfm->crt_flags);
+			crypto_yield(pdesc->flags);
 			slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
 			slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
 			offset = 0;
 			offset = 0;
 			pg++;
 			pg++;
@@ -183,11 +184,20 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
 	return 0;
 	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)
 static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
 {
 {
 	struct crypto_hash *parent = pdesc->tfm;
 	struct crypto_hash *parent = pdesc->tfm;
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
 	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 bs = crypto_hash_blocksize(parent);
 	int err = 0;
 	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)
 		if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
 			return err;
 			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, ctx->odds, bs);
 		ctx->xor(ctx->prev, key2, bs);
 		ctx->xor(ctx->prev, key2, bs);
 		_crypto_xcbc_digest_setkey(parent, ctx);
 		_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 {
 	} else {
 		u8 key3[bs];
 		u8 key3[bs];
 		unsigned int rlen;
 		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)
 		if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
 			return err;
 			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, ctx->odds, bs);
 		ctx->xor(ctx->prev, key3, bs);
 		ctx->xor(ctx->prev, key3, bs);
 
 
 		_crypto_xcbc_digest_setkey(parent, ctx);
 		_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;
 	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,
 static int crypto_xcbc_digest(struct hash_desc *pdesc,
 		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
 		  struct scatterlist *sg, unsigned int nbytes, u8 *out)
 {
 {
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
 	crypto_xcbc_digest_init(pdesc);
 	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);
 	return crypto_xcbc_digest_final(pdesc, out);
 }
 }
 
 
 static int xcbc_init_tfm(struct crypto_tfm *tfm)
 static int xcbc_init_tfm(struct crypto_tfm *tfm)
 {
 {
+	struct crypto_cipher *cipher;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
 	struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
 	int bs = crypto_hash_blocksize(__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) {
 	switch(bs) {
 	case 16:
 	case 16:
@@ -258,7 +274,7 @@ static int xcbc_init_tfm(struct crypto_tfm *tfm)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	ctx->child = crypto_cipher_cast(tfm);
+	ctx->child = cipher;
 	ctx->odds = (u8*)(ctx+1);
 	ctx->odds = (u8*)(ctx+1);
 	ctx->prev = ctx->odds + bs;
 	ctx->prev = ctx->odds + bs;
 	ctx->key = ctx->prev + 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
 static int __init
 geode_aes_init(void)
 geode_aes_init(void)
 {
 {
-	return pci_module_init(&geode_aes_driver);
+	return pci_register_driver(&geode_aes_driver);
 }
 }
 
 
 static void __exit
 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));
 	spin_lock_init(&(bond_info->tx_hashtbl_lock));
 
 
-	new_hashtbl = kmalloc(size, GFP_KERNEL);
+	new_hashtbl = kzalloc(size, GFP_KERNEL);
 	if (!new_hashtbl) {
 	if (!new_hashtbl) {
 		printk(KERN_ERR DRV_NAME
 		printk(KERN_ERR DRV_NAME
 		       ": %s: Error: Failed to allocate TLB hash table\n",
 		       ": %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;
 	bond_info->tx_hashtbl = new_hashtbl;
 
 
-	memset(bond_info->tx_hashtbl, 0, size);
-
 	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
 	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
 		tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
 		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);
 			"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) {
 	if (!new_slave) {
 		res = -ENOMEM;
 		res = -ENOMEM;
 		goto err_undo_flags;
 		goto err_undo_flags;
 	}
 	}
 
 
-	memset(new_slave, 0, sizeof(struct slave));
-
 	/* save slave's original flags before calling
 	/* save slave's original flags before calling
 	 * netdev_set_master and dev_open
 	 * 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");
 	printk(KERN_INFO "SLIP linefill/keepalive option.\n");
 #endif
 #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) {
 	if (!slip_devs) {
 		printk(KERN_ERR "SLIP: Can't allocate slip devices array!  Uaargh! (-> No SLIP available)\n");
 		printk(KERN_ERR "SLIP: Can't allocate slip devices array!  Uaargh! (-> No SLIP available)\n");
 		return -ENOMEM;
 		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 */
 	/* Fill in our line protocol discipline, and register it */
 	if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
 	if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
 		printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
 		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:
 next_pkt_nopost:
 		sw_idx++;
 		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 */
 		/* Refresh hw_idx to see if there is new work */
 		if (sw_idx == hw_idx) {
 		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.
  * 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>
  * Author: Gerald Schaefer <geraldsc@de.ibm.com>
  */
  */
@@ -22,7 +22,7 @@
 #include <asm/ebcdic.h>
 #include <asm/ebcdic.h>
 #include <asm/extmem.h>
 #include <asm/extmem.h>
 #include <linux/poll.h>
 #include <linux/poll.h>
-#include "../net/iucv.h"
+#include <net/iucv/iucv.h>
 
 
 
 
 //#define MON_DEBUG			/* Debug messages on/off */
 //#define MON_DEBUG			/* Debug messages on/off */
@@ -50,14 +50,13 @@ static char mon_dcss_name[9] = "MONDCSS\0";
 struct mon_msg {
 struct mon_msg {
 	u32 pos;
 	u32 pos;
 	u32 mca_offset;
 	u32 mca_offset;
-	iucv_MessagePending local_eib;
+	struct iucv_message msg;
 	char msglim_reached;
 	char msglim_reached;
 	char replied_msglim;
 	char replied_msglim;
 };
 };
 
 
 struct mon_private {
 struct mon_private {
-	u16 pathid;
-	iucv_handle_t iucv_handle;
+	struct iucv_path *path;
 	struct mon_msg *msg_array[MON_MSGLIM];
 	struct mon_msg *msg_array[MON_MSGLIM];
 	unsigned int   write_index;
 	unsigned int   write_index;
 	unsigned int   read_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_read_wait_queue);
 static DECLARE_WAIT_QUEUE_HEAD(mon_conn_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] = {
 static u8 user_data_connect[16] = {
 	/* Version code, must be 0x01 for shared mode */
 	/* Version code, must be 0x01 for shared mode */
 	0x01,
 	0x01,
@@ -100,8 +97,7 @@ static u8 user_data_sever[16] = {
  * Create the 8 bytes EBCDIC DCSS segment name from
  * Create the 8 bytes EBCDIC DCSS segment name from
  * an ASCII name, incl. padding
  * 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;
 	int i;
 
 
@@ -119,8 +115,7 @@ dcss_mkname(char *ascii_name, char *ebcdic_name)
  * print appropriate error message for segment_load()/segment_type()
  * print appropriate error message for segment_load()/segment_type()
  * return code
  * return code
  */
  */
-static void
-mon_segment_warn(int rc, char* seg_name)
+static void mon_segment_warn(int rc, char* seg_name)
 {
 {
 	switch (rc) {
 	switch (rc) {
 	case -ENOENT:
 	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);
 	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;
 	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));
 	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));
 	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)) ||
 	if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
 	    (mon_rec_start(monmsg) < mon_dcss_start) ||
 	    (mon_rec_start(monmsg) < mon_dcss_start) ||
@@ -221,20 +209,17 @@ mon_check_mca(struct mon_msg *monmsg)
 	return 0;
 	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;
 	int rc;
 
 
 	P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
 	P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
 		"0x%08X\n\n",
 		"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);
 	atomic_dec(&monpriv->msglim_count);
 	if (likely(!monmsg->msglim_reached)) {
 	if (likely(!monmsg->msglim_reached)) {
 		monmsg->pos = 0;
 		monmsg->pos = 0;
@@ -251,10 +236,19 @@ mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
 	return 0;
 	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;
 	struct mon_private *monpriv;
 
 
 	monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
 	monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
@@ -267,16 +261,15 @@ mon_alloc_mem(void)
 						    GFP_KERNEL);
 						    GFP_KERNEL);
 		if (!monpriv->msg_array[i]) {
 		if (!monpriv->msg_array[i]) {
 			P_ERROR("open, no memory for msg_array\n");
 			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 NULL;
 		}
 		}
 	}
 	}
 	return monpriv;
 	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
 #ifdef MON_DEBUG
 	u8 msg_type[2], mca_type;
 	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;
 	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);
 	EBCASC(msg_type, 2);
 	mca_type = mon_mca_type(monmsg, 0);
 	mca_type = mon_mca_type(monmsg, 0);
 	EBCASC(&mca_type, 1);
 	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",
 	P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
 		monpriv->read_index, monpriv->write_index);
 		monpriv->read_index, monpriv->write_index);
 	P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
 	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",
 	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',
 		msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
 		mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
 		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
 #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))
 	if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
 		return;
 		return;
@@ -316,8 +307,7 @@ mon_next_mca(struct mon_msg *monmsg)
 	monmsg->pos = 0;
 	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;
 	struct mon_msg *monmsg;
 
 
@@ -342,39 +332,37 @@ mon_next_message(struct mon_private *monpriv)
 /******************************************************************************
 /******************************************************************************
  *                               IUCV handler                                 *
  *                               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 connection completed\n");
 	P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
 	P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
 		"0x%02X, Sample = 0x%02X\n",
 		"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);
 	atomic_set(&monpriv->iucv_connected, 1);
 	wake_up(&mon_conn_wait_queue);
 	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);
 	atomic_set(&monpriv->iucv_severed, 1);
 	wake_up(&mon_conn_wait_queue);
 	wake_up(&mon_conn_wait_queue);
 	wake_up_interruptible(&mon_read_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");
 	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) {
 	if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
 		P_WARNING("IUCV message pending, message limit (%i) reached\n",
 		P_WARNING("IUCV message pending, message limit (%i) reached\n",
 			  MON_MSGLIM);
 			  MON_MSGLIM);
@@ -385,54 +373,45 @@ mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
 	wake_up_interruptible(&mon_read_wait_queue);
 	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                              *
  *                               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;
 	struct mon_private *monpriv;
+	int rc;
 
 
 	/*
 	/*
 	 * only one user allowed
 	 * only one user allowed
 	 */
 	 */
+	rc = -EBUSY;
 	if (test_and_set_bit(MON_IN_USE, &mon_in_use))
 	if (test_and_set_bit(MON_IN_USE, &mon_in_use))
-		return -EBUSY;
+		goto out;
 
 
+	rc = -ENOMEM;
 	monpriv = mon_alloc_mem();
 	monpriv = mon_alloc_mem();
 	if (!monpriv)
 	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) {
 	if (rc) {
 		P_ERROR("iucv connection to *MONITOR failed with "
 		P_ERROR("iucv connection to *MONITOR failed with "
 			"IPUSER SEVER code = %i\n", rc);
 			"IPUSER SEVER code = %i\n", rc);
 		rc = -EIO;
 		rc = -EIO;
-		goto out_unregister;
+		goto out_path;
 	}
 	}
 	/*
 	/*
 	 * Wait for connection confirmation
 	 * 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_severed, 0);
 		atomic_set(&monpriv->iucv_connected, 0);
 		atomic_set(&monpriv->iucv_connected, 0);
 		rc = -EIO;
 		rc = -EIO;
-		goto out_unregister;
+		goto out_path;
 	}
 	}
 	P_INFO("open, established connection to *MONITOR service\n\n");
 	P_INFO("open, established connection to *MONITOR service\n\n");
 	filp->private_data = monpriv;
 	filp->private_data = monpriv;
 	return nonseekable_open(inode, filp);
 	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);
 	clear_bit(MON_IN_USE, &mon_in_use);
+out:
 	return rc;
 	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;
 	int rc, i;
 	struct mon_private *monpriv = filp->private_data;
 	struct mon_private *monpriv = filp->private_data;
@@ -469,18 +447,12 @@ mon_close(struct inode *inode, struct file *filp)
 	/*
 	/*
 	 * Close IUCV connection and unregister
 	 * Close IUCV connection and unregister
 	 */
 	 */
-	rc = iucv_sever(monpriv->pathid, user_data_sever);
+	rc = iucv_path_sever(monpriv->path, user_data_sever);
 	if (rc)
 	if (rc)
 		P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
 		P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
 	else
 	else
 		P_INFO("close, terminated connection to *MONITOR service\n");
 		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_severed, 0);
 	atomic_set(&monpriv->iucv_connected, 0);
 	atomic_set(&monpriv->iucv_connected, 0);
 	atomic_set(&monpriv->read_ready, 0);
 	atomic_set(&monpriv->read_ready, 0);
@@ -495,8 +467,8 @@ mon_close(struct inode *inode, struct file *filp)
 	return 0;
 	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_private *monpriv = filp->private_data;
 	struct mon_msg *monmsg;
 	struct mon_msg *monmsg;
@@ -563,8 +535,7 @@ out_copy:
 	return count;
 	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;
 	struct mon_private *monpriv = filp->private_data;
 
 
@@ -593,8 +564,7 @@ static struct miscdevice mon_dev = {
 /******************************************************************************
 /******************************************************************************
  *                              module init/exit                              *
  *                              module init/exit                              *
  *****************************************************************************/
  *****************************************************************************/
-static int __init
-mon_init(void)
+static int __init mon_init(void)
 {
 {
 	int rc;
 	int rc;
 
 
@@ -603,22 +573,34 @@ mon_init(void)
 		return -ENODEV;
 		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);
 	rc = segment_type(mon_dcss_name);
 	if (rc < 0) {
 	if (rc < 0) {
 		mon_segment_warn(rc, mon_dcss_name);
 		mon_segment_warn(rc, mon_dcss_name);
-		return rc;
+		goto out_iucv;
 	}
 	}
 	if (rc != SEG_TYPE_SC) {
 	if (rc != SEG_TYPE_SC) {
 		P_ERROR("segment %s has unsupported type, should be SC\n",
 		P_ERROR("segment %s has unsupported type, should be SC\n",
 			mon_dcss_name);
 			mon_dcss_name);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out_iucv;
 	}
 	}
 
 
 	rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
 	rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
 			  &mon_dcss_start, &mon_dcss_end);
 			  &mon_dcss_start, &mon_dcss_end);
 	if (rc < 0) {
 	if (rc < 0) {
 		mon_segment_warn(rc, mon_dcss_name);
 		mon_segment_warn(rc, mon_dcss_name);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out_iucv;
 	}
 	}
 	dcss_mkname(mon_dcss_name, &user_data_connect[8]);
 	dcss_mkname(mon_dcss_name, &user_data_connect[8]);
 
 
@@ -634,14 +616,16 @@ mon_init(void)
 
 
 out:
 out:
 	segment_unload(mon_dcss_name);
 	segment_unload(mon_dcss_name);
+out_iucv:
+	iucv_unregister(&monreader_iucv_handler, 1);
 	return rc;
 	return rc;
 }
 }
 
 
-static void __exit
-mon_exit(void)
+static void __exit mon_exit(void)
 {
 {
 	segment_unload(mon_dcss_name);
 	segment_unload(mon_dcss_name);
 	WARN_ON(misc_deregister(&mon_dev) != 0);
 	WARN_ON(misc_deregister(&mon_dev) != 0);
+	iucv_unregister(&monreader_iucv_handler, 1);
 	return;
 	return;
 }
 }
 
 

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

@@ -3,7 +3,7 @@
  *	character device driver for reading z/VM system service records
  *	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,
  *	character device driver for reading z/VM system service records,
  *	Version 1.0
  *	Version 1.0
  *	Author(s): Xenia Tkatschow <xenia@us.ibm.com>
  *	Author(s): Xenia Tkatschow <xenia@us.ibm.com>
@@ -21,7 +21,7 @@
 #include <asm/cpcmd.h>
 #include <asm/cpcmd.h>
 #include <asm/debug.h>
 #include <asm/debug.h>
 #include <asm/ebcdic.h>
 #include <asm/ebcdic.h>
-#include "../net/iucv.h"
+#include <net/iucv/iucv.h>
 #include <linux/kmod.h>
 #include <linux/kmod.h>
 #include <linux/cdev.h>
 #include <linux/cdev.h>
 #include <linux/device.h>
 #include <linux/device.h>
@@ -60,12 +60,11 @@ struct vmlogrdr_priv_t {
 	char system_service[8];
 	char system_service[8];
 	char internal_name[8];
 	char internal_name[8];
 	char recording_name[8];
 	char recording_name[8];
-	u16 pathid;
+	struct iucv_path *path;
 	int connection_established;
 	int connection_established;
 	int iucv_path_severed;
 	int iucv_path_severed;
-	iucv_MessagePending local_interrupt_buffer;
+	struct iucv_message local_interrupt_buffer;
 	atomic_t receive_ready;
 	atomic_t receive_ready;
-	iucv_handle_t iucv_handle;
 	int minor_num;
 	int minor_num;
 	char * buffer;
 	char * buffer;
 	char * current_position;
 	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(conn_wait_queue);
 static DECLARE_WAIT_QUEUE_HEAD(read_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 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);
 	spin_lock(&logptr->priv_lock);
 	logptr->connection_established = 1;
 	logptr->connection_established = 1;
 	spin_unlock(&logptr->priv_lock);
 	spin_unlock(&logptr->priv_lock);
 	wake_up(&conn_wait_queue);
 	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"
 	printk (KERN_ERR "vmlogrdr: connection severed with"
 		" reason %i\n", reason);
 		" reason %i\n", reason);
 
 
+	iucv_path_sever(path, NULL);
+	kfree(path);
+	logptr->path = NULL;
+
 	spin_lock(&logptr->priv_lock);
 	spin_lock(&logptr->priv_lock);
 	logptr->connection_established = 0;
 	logptr->connection_established = 0;
 	logptr->iucv_path_severed = 1;
 	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.
 	 * 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
 	 * the usage count
 	 */
 	 */
 	spin_lock(&logptr->priv_lock);
 	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);
 	atomic_inc(&logptr->receive_ready);
 	spin_unlock(&logptr->priv_lock);
 	spin_unlock(&logptr->priv_lock);
 	wake_up_interruptible(&read_wait_queue);
 	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_command[]="QUERY COMMAND RECORDING ";
 	char cp_response[80];
 	char cp_response[80];
 	char *tail;
 	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_command[80];
 	char cp_response[160];
 	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;
 	int dev_num = 0;
 	struct vmlogrdr_priv_t * logptr = NULL;
 	struct vmlogrdr_priv_t * logptr = NULL;
@@ -328,10 +310,7 @@ vmlogrdr_open (struct inode *inode, struct file *filp)
 	dev_num = iminor(inode);
 	dev_num = iminor(inode);
 	if (dev_num > MAXMINOR)
 	if (dev_num > MAXMINOR)
 		return -ENODEV;
 		return -ENODEV;
-
 	logptr = &sys_ser[dev_num];
 	logptr = &sys_ser[dev_num];
-	if (logptr == NULL)
-		return -ENODEV;
 
 
 	/*
 	/*
 	 * only allow for blocking reads to be open
 	 * 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)	{
 	if (logptr->dev_in_use)	{
 		spin_unlock_bh(&logptr->priv_lock);
 		spin_unlock_bh(&logptr->priv_lock);
 		return -EBUSY;
 		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);
 	atomic_set(&logptr->receive_ready, 0);
 	logptr->buffer_free = 1;
 	logptr->buffer_free = 1;
+	spin_unlock_bh(&logptr->priv_lock);
 
 
 	/* set the file options */
 	/* set the file options */
 	filp->private_data = logptr;
 	filp->private_data = logptr;
 	filp->f_op = &vmlogrdr_fops;
 	filp->f_op = &vmlogrdr_fops;
 
 
 	/* start recording for this service*/
 	/* start recording for this service*/
-	ret=0;
-	if (logptr->autorecording)
+	if (logptr->autorecording) {
 		ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
 		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 */
 	/* 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) {
 	if (connect_rc) {
 		printk (KERN_ERR "vmlogrdr: iucv connection to %s "
 		printk (KERN_ERR "vmlogrdr: iucv connection to %s "
 			"failed with rc %i \n", logptr->system_service,
 			"failed with rc %i \n", logptr->system_service,
 			connect_rc);
 			connect_rc);
-		goto not_connected;
+		goto out_path;
 	}
 	}
 
 
 	/* We've issued the connect and now we must wait for a
 	/* 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)
 	wait_event(conn_wait_queue, (logptr->connection_established)
 		   || (logptr->iucv_path_severed));
 		   || (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);
  	return nonseekable_open(inode, filp);
 
 
-not_connected:
-	iucv_unregister_program(logptr->iucv_handle);
-	logptr->iucv_handle = NULL;
-not_registered:
+out_record:
 	if (logptr->autorecording)
 	if (logptr->autorecording)
 		vmlogrdr_recording(logptr,0,logptr->autopurge);
 		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;
 	logptr->dev_in_use = 0;
 	return -EIO;
 	return -EIO;
-
-
 }
 }
 
 
 
 
-static int
-vmlogrdr_release (struct inode *inode, struct file *filp)
+static int vmlogrdr_release (struct inode *inode, struct file *filp)
 {
 {
 	int ret;
 	int ret;
 
 
 	struct vmlogrdr_priv_t * logptr = filp->private_data;
 	struct vmlogrdr_priv_t * logptr = filp->private_data;
 
 
-	iucv_unregister_program(logptr->iucv_handle);
-	logptr->iucv_handle = NULL;
-
 	if (logptr->autorecording) {
 	if (logptr->autorecording) {
 		ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
 		ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
 		if (ret)
 		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;
 	int rc, *temp;
 	/* we need to keep track of two data sizes here:
 	/* we need to keep track of two data sizes here:
 	 * The number of bytes we need to receive from iucv and
 	 * 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
 			 * We need to return the total length of the record
                          * + size of FENCE in the first 4 bytes of the buffer.
                          * + 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);
 			user_data_count = sizeof(int);
 			temp = (int*)priv->buffer;
 			temp = (int*)priv->buffer;
 			*temp= iucv_data_count + sizeof(FENCE);
 			*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)
 		if (iucv_data_count > NET_BUFFER_SIZE)
 			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);
 		spin_unlock_bh(&priv->priv_lock);
 		/* An rc of 5 indicates that the record was bigger then
 		/* An rc of 5 indicates that the record was bigger then
 		 * the buffer, which is OK for us. A 9 indicates that the
 		 * 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;
 	int rc;
 	struct vmlogrdr_priv_t * priv = filp->private_data;
 	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;
 	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;
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret = count;
 	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;
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	return sprintf(buf, "%u\n", priv->autopurge);
 	return sprintf(buf, "%u\n", priv->autopurge);
 }
 }
@@ -576,8 +533,10 @@ static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,
 		   vmlogrdr_autopurge_store);
 		   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_command[80];
 	char cp_response[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 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;
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret = count;
 	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;
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	return sprintf(buf, "%u\n", priv->autorecording);
 	return sprintf(buf, "%u\n", priv->autorecording);
 }
 }
@@ -648,9 +610,10 @@ static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,
 		   vmlogrdr_autorecording_store);
 		   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;
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret;
 	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 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 ";
 	char cp_command[] = "QUERY RECORDING ";
 	int len;
 	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;
 	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);
 	ret = driver_register(&vmlogrdr_driver);
 	if (ret) {
 	if (ret) {
 		printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
 		printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
-		return ret;
+		goto out_iucv;
 	}
 	}
 
 
 	ret = driver_create_file(&vmlogrdr_driver,
 	ret = driver_create_file(&vmlogrdr_driver,
 				 &driver_attr_recording_status);
 				 &driver_attr_recording_status);
 	if (ret) {
 	if (ret) {
 		printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
 		printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
-		goto unregdriver;
+		goto out_driver;
 	}
 	}
 
 
 	vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
 	vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
 	if (IS_ERR(vmlogrdr_class)) {
 	if (IS_ERR(vmlogrdr_class)) {
 		printk(KERN_ERR "vmlogrdr: failed to create class.\n");
 		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;
 	return 0;
 
 
-unregattr:
+out_attr:
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
-unregdriver:
+out_driver:
 	driver_unregister(&vmlogrdr_driver);
 	driver_unregister(&vmlogrdr_driver);
+out_iucv:
+	iucv_unregister(&vmlogrdr_iucv_handler, 1);
+out:
 	return ret;
 	return ret;
 }
 }
 
 
 
 
-static void
-vmlogrdr_unregister_driver(void) {
+static void vmlogrdr_unregister_driver(void)
+{
 	class_destroy(vmlogrdr_class);
 	class_destroy(vmlogrdr_class);
 	vmlogrdr_class = NULL;
 	vmlogrdr_class = NULL;
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
 	driver_unregister(&vmlogrdr_driver);
 	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;
 	struct device *dev;
 	int ret;
 	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) {
 	if (priv->device != NULL) {
 		sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
 		sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
 		device_unregister(priv->device);
 		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;
 	int rc = 0;
 	vmlogrdr_cdev = cdev_alloc();
 	vmlogrdr_cdev = cdev_alloc();
 	if (!vmlogrdr_cdev) {
 	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;
         int i;
+
 	if (vmlogrdr_cdev) {
 	if (vmlogrdr_cdev) {
 		cdev_del(vmlogrdr_cdev);
 		cdev_del(vmlogrdr_cdev);
 		vmlogrdr_cdev=NULL;
 		vmlogrdr_cdev=NULL;
@@ -855,8 +832,7 @@ vmlogrdr_cleanup(void) {
 }
 }
 
 
 
 
-static int
-vmlogrdr_init(void)
+static int vmlogrdr_init(void)
 {
 {
 	int rc;
 	int rc;
 	int i;
 	int i;
@@ -906,8 +882,7 @@ cleanup:
 }
 }
 
 
 
 
-static void
-vmlogrdr_exit(void)
+static void vmlogrdr_exit(void)
 {
 {
 	vmlogrdr_cleanup();
 	vmlogrdr_cleanup();
 	printk (KERN_INFO "vmlogrdr: driver unloaded\n");
 	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
 	  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".
 	  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
 config NETIUCV
 	tristate "IUCV network device support (VM only)"
 	tristate "IUCV network device support (VM only)"
 	depends on IUCV && NETDEVICES
 	depends on IUCV && NETDEVICES

+ 0 - 1
drivers/s390/net/Makefile

@@ -4,7 +4,6 @@
 
 
 ctc-objs := ctcmain.o ctcdbug.o
 ctc-objs := ctcmain.o ctcdbug.o
 
 
-obj-$(CONFIG_IUCV) += iucv.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
 obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
 obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
 obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.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]);

Datei-Diff unterdrückt, da er zu groß ist
+ 343 - 337
drivers/s390/net/netiucv.c


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

@@ -1,7 +1,7 @@
 /*
 /*
  * IUCV special message driver
  * 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)
  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * This program is free software; you can redistribute it and/or modify
@@ -23,10 +23,10 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/device.h>
 #include <linux/device.h>
+#include <net/iucv/iucv.h>
 #include <asm/cpcmd.h>
 #include <asm/cpcmd.h>
 #include <asm/ebcdic.h>
 #include <asm/ebcdic.h>
-
-#include "iucv.h"
+#include "smsgiucv.h"
 
 
 struct smsg_callback {
 struct smsg_callback {
 	struct list_head list;
 	struct list_head list;
@@ -39,38 +39,46 @@ MODULE_AUTHOR
    ("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)");
    ("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)");
 MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver");
 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 DEFINE_SPINLOCK(smsg_list_lock);
 static struct list_head smsg_list = LIST_HEAD_INIT(smsg_list);
 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;
 	struct smsg_callback *cb;
-	unsigned char *msg;
+	unsigned char *buffer;
 	unsigned char sender[9];
 	unsigned char sender[9];
-	unsigned short len;
 	int rc, i;
 	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;
 		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) {
 	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;
 		sender[8] = 0;
 		/* Remove trailing whitespace from the sender name. */
 		/* Remove trailing whitespace from the sender name. */
 		for (i = 7; i >= 0; i--) {
 		for (i = 7; i >= 0; i--) {
@@ -80,27 +88,17 @@ smsg_message_pending(iucv_MessagePending *eib, void *pgm_data)
 		}
 		}
 		spin_lock(&smsg_list_lock);
 		spin_lock(&smsg_list_lock);
 		list_for_each_entry(cb, &smsg_list, list)
 		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;
 				break;
 			}
 			}
 		spin_unlock(&smsg_list_lock);
 		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;
 	struct smsg_callback *cb;
 
 
@@ -110,18 +108,18 @@ smsg_register_callback(char *prefix, void (*callback)(char *from, char *str))
 	cb->prefix = prefix;
 	cb->prefix = prefix;
 	cb->len = strlen(prefix);
 	cb->len = strlen(prefix);
 	cb->callback = callback;
 	cb->callback = callback;
-	spin_lock(&smsg_list_lock);
+	spin_lock_bh(&smsg_list_lock);
 	list_add_tail(&cb->list, &smsg_list);
 	list_add_tail(&cb->list, &smsg_list);
-	spin_unlock(&smsg_list_lock);
+	spin_unlock_bh(&smsg_list_lock);
 	return 0;
 	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;
 	struct smsg_callback *cb, *tmp;
 
 
-	spin_lock(&smsg_list_lock);
+	spin_lock_bh(&smsg_list_lock);
 	cb = NULL;
 	cb = NULL;
 	list_for_each_entry(tmp, &smsg_list, list)
 	list_for_each_entry(tmp, &smsg_list, list)
 		if (tmp->callback == callback &&
 		if (tmp->callback == callback &&
@@ -130,55 +128,58 @@ smsg_unregister_callback(char *prefix, void (*callback)(char *from, char *str))
 			list_del(&cb->list);
 			list_del(&cb->list);
 			break;
 			break;
 		}
 		}
-	spin_unlock(&smsg_list_lock);
+	spin_unlock_bh(&smsg_list_lock);
 	kfree(cb);
 	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;
 	int rc;
 
 
 	rc = driver_register(&smsg_driver);
 	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");
 		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) {
 	if (rc) {
 		printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
 		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);
 	cpcmd("SET SMSG IUCV", NULL, 0, NULL);
 	return 0;
 	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);
 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);
 		mutex_unlock(&crypt_stat->cs_tfm_mutex);
 		goto out;
 		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);
 	mutex_unlock(&crypt_stat->cs_tfm_mutex);
 	rc = 0;
 	rc = 0;
 out:
 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_FILE_SIZE_BYTES 8
 #define ECRYPTFS_DEFAULT_CIPHER "aes"
 #define ECRYPTFS_DEFAULT_CIPHER "aes"
 #define ECRYPTFS_DEFAULT_KEY_BYTES 16
 #define ECRYPTFS_DEFAULT_KEY_BYTES 16
-#define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC
 #define ECRYPTFS_DEFAULT_HASH "md5"
 #define ECRYPTFS_DEFAULT_HASH "md5"
 #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
 #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
 #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED
 #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED

+ 21 - 3
include/crypto/algapi.h

@@ -18,8 +18,8 @@ struct module;
 struct seq_file;
 struct seq_file;
 
 
 struct crypto_type {
 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 (*exit)(struct crypto_tfm *tfm);
 	void (*show)(struct seq_file *m, struct crypto_alg *alg);
 	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,
 int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
 		      struct crypto_instance *inst);
 		      struct crypto_instance *inst);
 void crypto_drop_spawn(struct crypto_spawn *spawn);
 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,
 struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
 				       u32 type, u32 mask);
 				       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);
 	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)
 static inline struct cipher_alg *crypto_cipher_alg(struct crypto_cipher *tfm)
 {
 {
 	return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher;
 	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)
 static inline void *crypto_hash_ctx_aligned(struct crypto_hash *tfm)
 {
 {
 	return crypto_tfm_ctx_aligned(&tfm->base);
 	return crypto_tfm_ctx_aligned(&tfm->base);

+ 0 - 2
include/linux/atmarp.h

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

+ 14 - 134
include/linux/crypto.h

@@ -51,15 +51,9 @@
 /*
 /*
  * Transform masks and values (for crt_flags).
  * Transform masks and values (for crt_flags).
  */
  */
-#define CRYPTO_TFM_MODE_MASK		0x000000ff
 #define CRYPTO_TFM_REQ_MASK		0x000fff00
 #define CRYPTO_TFM_REQ_MASK		0x000fff00
 #define CRYPTO_TFM_RES_MASK		0xfff00000
 #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_WEAK_KEY		0x00000100
 #define CRYPTO_TFM_REQ_MAY_SLEEP	0x00000200
 #define CRYPTO_TFM_REQ_MAY_SLEEP	0x00000200
 #define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
 #define CRYPTO_TFM_RES_WEAK_KEY		0x00100000
@@ -71,12 +65,8 @@
 /*
 /*
  * Miscellaneous stuff.
  * Miscellaneous stuff.
  */
  */
-#define CRYPTO_UNSPEC			0
 #define CRYPTO_MAX_ALG_NAME		64
 #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
  * 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
  * declaration) is used to ensure that the crypto_tfm context structure is
@@ -148,19 +138,6 @@ struct cipher_alg {
 	                  unsigned int keylen);
 	                  unsigned int keylen);
 	void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 	void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 	void (*cia_decrypt)(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 {
 struct digest_alg {
@@ -243,11 +220,6 @@ int crypto_unregister_alg(struct crypto_alg *alg);
 #ifdef CONFIG_CRYPTO
 #ifdef CONFIG_CRYPTO
 int crypto_has_alg(const char *name, u32 type, u32 mask);
 int crypto_has_alg(const char *name, u32 type, u32 mask);
 #else
 #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)
 static inline int crypto_has_alg(const char *name, u32 type, u32 mask)
 {
 {
 	return 0;
 	return 0;
@@ -339,13 +311,18 @@ struct crypto_tfm {
 	void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
 	void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
 };
 };
 
 
-#define crypto_cipher crypto_tfm
-#define crypto_comp crypto_tfm
-
 struct crypto_blkcipher {
 struct crypto_blkcipher {
 	struct crypto_tfm base;
 	struct crypto_tfm base;
 };
 };
 
 
+struct crypto_cipher {
+	struct crypto_tfm base;
+};
+
+struct crypto_comp {
+	struct crypto_tfm base;
+};
+
 struct crypto_hash {
 struct crypto_hash {
 	struct crypto_tfm base;
 	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;
 	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)
 static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
 {
 {
 	return tfm->__crt_alg->cra_blocksize;
 	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)
 static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm)
 {
 {
 	return tfm->__crt_alg->cra_alignmask;
 	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)
 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)
 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);
 	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)
 static inline struct crypto_comp *__crypto_comp_cast(struct crypto_tfm *tfm)
 {
 {
 	return (struct crypto_comp *)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)
 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)
 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,
                                        const u8 *src, unsigned int slen,
                                        u8 *dst, unsigned int *dlen)
                                        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,
 static inline int crypto_comp_decompress(struct crypto_comp *tfm,
                                          const u8 *src, unsigned int slen,
                                          const u8 *src, unsigned int slen,
                                          u8 *dst, unsigned int *dlen)
                                          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 */
 #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_RX_RING			5
 #define PACKET_STATISTICS		6
 #define PACKET_STATISTICS		6
 #define PACKET_COPY_THRESH		7
 #define PACKET_COPY_THRESH		7
+#define PACKET_AUXDATA			8
 
 
 struct tpacket_stats
 struct tpacket_stats
 {
 {
@@ -48,6 +49,15 @@ struct tpacket_stats
 	unsigned int	tp_drops;
 	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
 struct tpacket_hdr
 {
 {
 	unsigned long	tp_status;
 	unsigned long	tp_status;

+ 1 - 1
include/linux/net.h

@@ -24,7 +24,7 @@
 struct poll_table_struct;
 struct poll_table_struct;
 struct inode;
 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_SOCKET	1		/* sys_socket(2)		*/
 #define SYS_BIND	2		/* sys_bind(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_close(struct net_device *dev);
 extern int		dev_queue_xmit(struct sk_buff *skb);
 extern int		dev_queue_xmit(struct sk_buff *skb);
 extern int		register_netdevice(struct net_device *dev);
 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		free_netdev(struct net_device *dev);
 extern void		synchronize_net(void);
 extern void		synchronize_net(void);
 extern int 		register_netdevice_notifier(struct notifier_block *nb);
 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_tcpudp.h
 header-y += xt_SECMARK.h
 header-y += xt_SECMARK.h
 header-y += xt_CONNSECMARK.h
 header-y += xt_CONNSECMARK.h
+header-y += xt_TCPMSS.h
 
 
 unifdef-y += nf_conntrack_common.h
 unifdef-y += nf_conntrack_common.h
 unifdef-y += nf_conntrack_ftp.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 */
 /* This sender sent FIN first */
 #define IP_CT_TCP_FLAG_CLOSE_INIT		0x04
 #define IP_CT_TCP_FLAG_CLOSE_INIT		0x04
 
 
+/* Be liberal in window checking */
+#define IP_CT_TCP_FLAG_BE_LIBERAL		0x08
+
 #ifdef __KERNEL__
 #ifdef __KERNEL__
 
 
 struct ip_ct_tcp_state {
 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_maxend;	/* max of ack + max(win, 1) */
 	u_int32_t	td_maxwin;	/* max(win) */
 	u_int32_t	td_maxwin;	/* max(win) */
 	u_int8_t	td_scale;	/* window scale factor */
 	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 */
 	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_MAP_IPS 1
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
+#define IP_NAT_RANGE_PROTO_RANDOM 4 /* add randomness to "port" selection */
 
 
 /* NAT sequence number modifications */
 /* NAT sequence number modifications */
 struct ip_nat_seq {
 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>
 #include <linux/init.h>
 extern void ipt_init(void) __init;
 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);
 			      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. */
 /* Standard entry. */
 struct ipt_standard
 struct ipt_standard
@@ -315,7 +299,7 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb,
 				 unsigned int hook,
 				 unsigned int hook,
 				 const struct net_device *in,
 				 const struct net_device *in,
 				 const struct net_device *out,
 				 const struct net_device *out,
-				 struct ipt_table *table);
+				 struct xt_table *table);
 
 
 #define IPT_ALIGN(s) XT_ALIGN(s)
 #define IPT_ALIGN(s) XT_ALIGN(s)
 
 

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

@@ -1,10 +1,9 @@
 #ifndef _IPT_TCPMSS_H
 #ifndef _IPT_TCPMSS_H
 #define _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*/
 #endif /*_IPT_TCPMSS_H*/

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

@@ -104,6 +104,25 @@ struct ip6t_entry
 	unsigned char elems[0];
 	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.
  * 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
  * 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>
 #include <linux/init.h>
 extern void ip6t_init(void) __init;
 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);
 			       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,
 extern unsigned int ip6t_do_table(struct sk_buff **pskb,
 				  unsigned int hook,
 				  unsigned int hook,
 				  const struct net_device *in,
 				  const struct net_device *in,
 				  const struct net_device *out,
 				  const struct net_device *out,
-				  struct ip6t_table *table);
+				  struct xt_table *table);
 
 
 /* Check for an extension */
 /* Check for an extension */
 extern int ip6t_ext_hdr(u8 nexthdr);
 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_SPDEXPIRE	21
 #define SADB_X_SPDDELETE2	22
 #define SADB_X_SPDDELETE2	22
 #define SADB_X_NAT_T_NEW_MAPPING	23
 #define SADB_X_NAT_T_NEW_MAPPING	23
-#define SADB_MAX		23
+#define SADB_X_MIGRATE		24
+#define SADB_MAX		24
 
 
 /* Security Association flags */
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS	1
 #define SADB_SAFLAGS_PFS	1
@@ -297,6 +298,7 @@ struct sadb_x_sec_ctx {
 #define SADB_X_EALG_BLOWFISHCBC		7
 #define SADB_X_EALG_BLOWFISHCBC		7
 #define SADB_EALG_NULL			11
 #define SADB_EALG_NULL			11
 #define SADB_X_EALG_AESCBC		12
 #define SADB_X_EALG_AESCBC		12
+#define SADB_X_EALG_CAMELLIACBC		22
 #define SADB_EALG_MAX                   253 /* last EALG */
 #define SADB_EALG_MAX                   253 /* last EALG */
 /* private allocations should use 249-255 (RFC2407) */
 /* private allocations should use 249-255 (RFC2407) */
 #define SADB_X_EALG_SERPENTCBC  252     /* draft-ietf-ipsec-ciph-aes-cbc-00 */
 #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_LLC		26	/* Linux LLC			*/
 #define AF_TIPC		30	/* TIPC sockets			*/
 #define AF_TIPC		30	/* TIPC sockets			*/
 #define AF_BLUETOOTH	31	/* Bluetooth 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. */
 /* Protocol families, same as address families. */
 #define PF_UNSPEC	AF_UNSPEC
 #define PF_UNSPEC	AF_UNSPEC
@@ -220,6 +221,7 @@ struct ucred {
 #define PF_LLC		AF_LLC
 #define PF_LLC		AF_LLC
 #define PF_TIPC		AF_TIPC
 #define PF_TIPC		AF_TIPC
 #define PF_BLUETOOTH	AF_BLUETOOTH
 #define PF_BLUETOOTH	AF_BLUETOOTH
+#define PF_IUCV		AF_IUCV
 #define PF_MAX		AF_MAX
 #define PF_MAX		AF_MAX
 
 
 /* Maximum queue length specifiable by listen.  */
 /* 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_CALL_REQUEST_TIMEOUT=2,
 	NET_X25_RESET_REQUEST_TIMEOUT=3,
 	NET_X25_RESET_REQUEST_TIMEOUT=3,
 	NET_X25_CLEAR_REQUEST_TIMEOUT=4,
 	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 */
 /* /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 duplicate_sack[1]; /* D-SACK block */
 	struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
 	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 */
 	/* from STCP, retrans queue hinting */
 	struct sk_buff* lost_skb_hint;
 	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 */
 /* Public functions available for device drivers */
 extern int register_wan_device(struct wan_device *wandev);
 extern int register_wan_device(struct wan_device *wandev);
 extern int unregister_wan_device(char *name);
 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! */
 /* Proc interface functions. These must not be called by the drivers! */
 extern int wanrouter_proc_init(void);
 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_proc_delete(struct wan_device *wandev);
 extern int wanrouter_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
 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 */
 /* Public Data */
 /* list of registered devices */
 /* list of registered devices */
 extern struct wan_device *wanrouter_router_devlist;
 extern struct wan_device *wanrouter_router_devlist;

+ 19 - 0
include/linux/xfrm.h

@@ -178,6 +178,9 @@ enum {
 	XFRM_MSG_REPORT,
 	XFRM_MSG_REPORT,
 #define XFRM_MSG_REPORT XFRM_MSG_REPORT
 #define XFRM_MSG_REPORT XFRM_MSG_REPORT
 
 
+	XFRM_MSG_MIGRATE,
+#define XFRM_MSG_MIGRATE XFRM_MSG_MIGRATE
+
 	__XFRM_MSG_MAX
 	__XFRM_MSG_MAX
 };
 };
 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -256,6 +259,7 @@ enum xfrm_attr_type_t {
 	XFRMA_COADDR,		/* xfrm_address_t */
 	XFRMA_COADDR,		/* xfrm_address_t */
 	XFRMA_LASTUSED,
 	XFRMA_LASTUSED,
 	XFRMA_POLICY_TYPE,	/* struct xfrm_userpolicy_type */
 	XFRMA_POLICY_TYPE,	/* struct xfrm_userpolicy_type */
+	XFRMA_MIGRATE,
 	__XFRMA_MAX
 	__XFRMA_MAX
 
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -351,6 +355,19 @@ struct xfrm_user_report {
 	struct xfrm_selector		sel;
 	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__
 #ifndef __KERNEL__
 /* backwards compatibility for userspace */
 /* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
 #define XFRMGRP_ACQUIRE		1
@@ -375,6 +392,8 @@ enum xfrm_nlgroups {
 #define XFRMNLGRP_AEVENTS	XFRMNLGRP_AEVENTS
 #define XFRMNLGRP_AEVENTS	XFRMNLGRP_AEVENTS
 	XFRMNLGRP_REPORT,
 	XFRMNLGRP_REPORT,
 #define XFRMNLGRP_REPORT	XFRMNLGRP_REPORT
 #define XFRMNLGRP_REPORT	XFRMNLGRP_REPORT
+	XFRMNLGRP_MIGRATE,
+#define XFRMNLGRP_MIGRATE	XFRMNLGRP_MIGRATE
 	__XFRMNLGRP_MAX
 	__XFRMNLGRP_MAX
 };
 };
 #define XFRMNLGRP_MAX	(__XFRMNLGRP_MAX - 1)
 #define XFRMNLGRP_MAX	(__XFRMNLGRP_MAX - 1)

+ 5 - 5
include/net/inet_hashtables.h

@@ -34,12 +34,13 @@
 #include <asm/byteorder.h>
 #include <asm/byteorder.h>
 
 
 /* This is for all connections with a full identity, no wildcards.
 /* 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 {
 struct inet_ehash_bucket {
 	rwlock_t	  lock;
 	rwlock_t	  lock;
 	struct hlist_head chain;
 	struct hlist_head chain;
+	struct hlist_head twchain;
 };
 };
 
 
 /* There are a few simple rules, which allow for local port reuse by
 /* 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
 	 *          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;
 	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. */
 	/* 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))
 		if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
 			goto hit;
 			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_ftp.h>
 #include <linux/netfilter/nf_conntrack_pptp.h>
 #include <linux/netfilter/nf_conntrack_pptp.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
 #include <linux/netfilter/nf_conntrack_h323.h>
+#include <linux/netfilter/nf_conntrack_sane.h>
 
 
 /* per conntrack: application helper private data */
 /* per conntrack: application helper private data */
 union nf_conntrack_help {
 union nf_conntrack_help {
@@ -52,6 +53,7 @@ union nf_conntrack_help {
 	struct nf_ct_ftp_master ct_ftp_info;
 	struct nf_ct_ftp_master ct_ftp_info;
 	struct nf_ct_pptp_master ct_pptp_info;
 	struct nf_ct_pptp_master ct_pptp_info;
 	struct nf_ct_h323_master ct_h323_info;
 	struct nf_ct_h323_master ct_h323_info;
+	struct nf_ct_sane_master ct_sane_info;
 };
 };
 
 
 #include <linux/types.h>
 #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_MAP_IPS 1
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
 #define IP_NAT_RANGE_PROTO_SPECIFIED 2
+#define IP_NAT_RANGE_PROTO_RANDOM 4
 
 
 /* NAT sequence number modifications */
 /* NAT sequence number modifications */
 struct nf_nat_seq {
 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,
 static inline int ip_route_connect(struct rtable **rp, __be32 dst,
 				   __be32 src, u32 tos, int oif, u8 protocol,
 				   __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,
 	struct flowi fl = { .oif = oif,
 			    .nl_u = { .ip4_u = { .daddr = dst,
 			    .nl_u = { .ip4_u = { .daddr = dst,
@@ -168,7 +169,7 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
 		*rp = NULL;
 		*rp = NULL;
 	}
 	}
 	security_sk_classify_flow(sk, &fl);
 	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,
 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
  * 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);
 	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 */
 	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)
 static inline struct x25_sock *x25_sk(const struct sock *sk)
 {
 {
 	return (struct x25_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_reset_request_timeout;
 extern int  sysctl_x25_clear_request_timeout;
 extern int  sysctl_x25_clear_request_timeout;
 extern int  sysctl_x25_ack_holdback_timeout;
 extern int  sysctl_x25_ack_holdback_timeout;
+extern int  sysctl_x25_forward;
 
 
 extern int  x25_addr_ntoa(unsigned char *, struct x25_address *,
 extern int  x25_addr_ntoa(unsigned char *, struct x25_address *,
 			  struct x25_address *);
 			  struct x25_address *);
@@ -198,6 +207,13 @@ extern int x25_negotiate_facilities(struct sk_buff *, struct sock *,
 				struct x25_dte_facilities *);
 				struct x25_dte_facilities *);
 extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
 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 */
 /* x25_in.c */
 extern int  x25_process_rx_frame(struct sock *, struct sk_buff *);
 extern int  x25_process_rx_frame(struct sock *, struct sk_buff *);
 extern int  x25_backlog_rcv(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 rwlock_t x25_list_lock;
 extern struct list_head x25_route_list;
 extern struct list_head x25_route_list;
 extern rwlock_t x25_route_list_lock;
 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 int x25_proc_init(void);
 extern void x25_proc_exit(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);
 						xfrm_address_t *daddr, xfrm_address_t *saddr);
 	int			(*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
 	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			(*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_register_afinfo(struct xfrm_state_afinfo *afinfo);
 extern int xfrm_state_unregister_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);
 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_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
 #define XFRM_KM_TIMEOUT                30
 /* which seqno */
 /* which seqno */
 #define XFRM_REPLAY_SEQ		1
 #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			(*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			(*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			(*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);
 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);
 			  struct flowi *fl, int family, int strict);
 extern void xfrm_init_pmtu(struct dst_entry *dst);
 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 wait_queue_head_t km_waitq;
 extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
 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);
 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);
 		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 */
 #endif	/* _NET_XFRM_H */

+ 1 - 0
net/Kconfig

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

+ 1 - 0
net/Makefile

@@ -47,6 +47,7 @@ obj-$(CONFIG_IP_SCTP)		+= sctp/
 obj-$(CONFIG_IEEE80211)		+= ieee80211/
 obj-$(CONFIG_IEEE80211)		+= ieee80211/
 obj-$(CONFIG_TIPC)		+= tipc/
 obj-$(CONFIG_TIPC)		+= tipc/
 obj-$(CONFIG_NETLABEL)		+= netlabel/
 obj-$(CONFIG_NETLABEL)		+= netlabel/
+obj-$(CONFIG_IUCV)		+= iucv/
 
 
 ifeq ($(CONFIG_NET),y)
 ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_SYSCTL)		+= sysctl_net.o
 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);
 	proto_unregister(&vcc_proto);
 }
 }
 
 
-module_init(atm_init);
+subsys_initcall(atm_init);
+
 module_exit(atm_exit);
 module_exit(atm_exit);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 7 - 22
net/bridge/br_netfilter.c

@@ -949,44 +949,29 @@ static ctl_table brnf_net_table[] = {
 };
 };
 #endif
 #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;
 		return ret;
-	}
-
 #ifdef CONFIG_SYSCTL
 #ifdef CONFIG_SYSCTL
 	brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0);
 	brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0);
 	if (brnf_sysctl_header == NULL) {
 	if (brnf_sysctl_header == NULL) {
 		printk(KERN_WARNING
 		printk(KERN_WARNING
 		       "br_netfilter: can't register to sysctl.\n");
 		       "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
 #endif
-
 	printk(KERN_NOTICE "Bridge firewalling registered\n");
 	printk(KERN_NOTICE "Bridge firewalling registered\n");
-
 	return 0;
 	return 0;
 }
 }
 
 
 void br_netfilter_fini(void)
 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
 #ifdef CONFIG_SYSCTL
 	unregister_sysctl_table(brnf_sysctl_header);
 	unregister_sysctl_table(brnf_sysctl_header);
 #endif
 #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);
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 
 	hdr = nlmsg_data(nlh);
 	hdr = nlmsg_data(nlh);
 	hdr->ifi_family = AF_BRIDGE;
 	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);
 	return nlmsg_end(skb, nlh);
 
 
 nla_put_failure:
 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;
 		goto errout;
 
 
 	err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
 	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);
 	err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
 errout:
 errout:
 	if (err < 0)
 	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;
 			return -EINVAL;
 		if (info->protocol != IPPROTO_TCP &&
 		if (info->protocol != IPPROTO_TCP &&
 		    info->protocol != IPPROTO_UDP &&
 		    info->protocol != IPPROTO_UDP &&
+		    info->protocol != IPPROTO_UDPLITE &&
 		    info->protocol != IPPROTO_SCTP &&
 		    info->protocol != IPPROTO_SCTP &&
 		    info->protocol != IPPROTO_DCCP)
 		    info->protocol != IPPROTO_DCCP)
 			 return -EINVAL;
 			 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);
 		       NIPQUAD(ih->daddr), ih->tos, ih->protocol);
 		if (ih->protocol == IPPROTO_TCP ||
 		if (ih->protocol == IPPROTO_TCP ||
 		    ih->protocol == IPPROTO_UDP ||
 		    ih->protocol == IPPROTO_UDP ||
+		    ih->protocol == IPPROTO_UDPLITE ||
 		    ih->protocol == IPPROTO_SCTP ||
 		    ih->protocol == IPPROTO_SCTP ||
 		    ih->protocol == IPPROTO_DCCP) {
 		    ih->protocol == IPPROTO_DCCP) {
 			struct tcpudphdr _ports, *pptr;
 			struct tcpudphdr _ports, *pptr;

+ 5 - 8
net/core/dev.c

@@ -3247,7 +3247,7 @@ void synchronize_net(void)
  *	unregister_netdev() instead of this.
  *	unregister_netdev() instead of this.
  */
  */
 
 
-int unregister_netdevice(struct net_device *dev)
+void unregister_netdevice(struct net_device *dev)
 {
 {
 	struct net_device *d, **dp;
 	struct net_device *d, **dp;
 
 
@@ -3258,7 +3258,9 @@ int unregister_netdevice(struct net_device *dev)
 	if (dev->reg_state == NETREG_UNINITIALIZED) {
 	if (dev->reg_state == NETREG_UNINITIALIZED) {
 		printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
 		printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
 				  "was registered\n", dev->name, dev);
 				  "was registered\n", dev->name, dev);
-		return -ENODEV;
+
+		WARN_ON(1);
+		return;
 	}
 	}
 
 
 	BUG_ON(dev->reg_state != NETREG_REGISTERED);
 	BUG_ON(dev->reg_state != NETREG_REGISTERED);
@@ -3280,11 +3282,7 @@ int unregister_netdevice(struct net_device *dev)
 			break;
 			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;
 	dev->reg_state = NETREG_UNREGISTERING;
 
 
@@ -3316,7 +3314,6 @@ int unregister_netdevice(struct net_device *dev)
 	synchronize_net();
 	synchronize_net();
 
 
 	dev_put(dev);
 	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",
 	printk("dst_total: %d/%d %ld\n",
 	       atomic_read(&dst_total), delayed,  dst_gc_timer_expires);
 	       atomic_read(&dst_total), delayed,  dst_gc_timer_expires);
 #endif
 #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:
 out:
 	spin_unlock(&dst_lock);
 	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);
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -1;
+		return -EMSGSIZE;
 
 
 	frh = nlmsg_data(nlh);
 	frh = nlmsg_data(nlh);
 	frh->table = rule->table;
 	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);
 	return nlmsg_end(skb, nlh);
 
 
 nla_put_failure:
 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)
 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;
 		goto errout;
 
 
 	err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
 	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);
 	err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
 errout:
 errout:
 	if (err < 0)
 	if (err < 0)

+ 19 - 10
net/core/neighbour.c

@@ -696,7 +696,10 @@ next_elt:
 	if (!expire)
 	if (!expire)
 		expire = 1;
 		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);
 	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);
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 
 	ndtmsg = nlmsg_data(nlh);
 	ndtmsg = nlmsg_data(nlh);
 
 
@@ -1706,7 +1709,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
 
 
 nla_put_failure:
 nla_put_failure:
 	read_unlock_bh(&tbl->lock);
 	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,
 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);
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 
 	ndtmsg = nlmsg_data(nlh);
 	ndtmsg = nlmsg_data(nlh);
 
 
@@ -1737,7 +1741,8 @@ static int neightbl_fill_param_info(struct sk_buff *skb,
 	return nlmsg_end(skb, nlh);
 	return nlmsg_end(skb, nlh);
 errout:
 errout:
 	read_unlock_bh(&tbl->lock);
 	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,
 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);
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 
 	ndm = nlmsg_data(nlh);
 	ndm = nlmsg_data(nlh);
 	ndm->ndm_family	 = neigh->ops->family;
 	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);
 	return nlmsg_end(skb, nlh);
 
 
 nla_put_failure:
 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;
 		goto errout;
 
 
 	err = neigh_fill_info(skb, n, 0, 0, type, flags);
 	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);
 	err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
 errout:
 errout:
 	if (err < 0)
 	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);
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 
 	ifm = nlmsg_data(nlh);
 	ifm = nlmsg_data(nlh);
 	ifm->ifi_family = AF_UNSPEC;
 	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);
 	return nlmsg_end(skb, nlh);
 
 
 nla_put_failure:
 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)
 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,
 	err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
 			       NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
 			       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);
 	err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
 errout:
 errout:
 	kfree(iw_buf);
 	kfree(iw_buf);
@@ -678,9 +682,12 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
 		goto errout;
 		goto errout;
 
 
 	err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
 	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);
 	err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
 errout:
 errout:
 	if (err < 0)
 	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, "
 			ccid3_pr_debug("%s(%p), s=%u, w_init=%llu, "
 				       "R_sample=%dus, X=%u\n", dccp_role(sk),
 				       "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,
 				       (int)r_sample,
 				       (unsigned)(hctx->ccid3hctx_x >> 6));
 				       (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);
 		DCCP_BUG_ON(r_sample < 0);
 		if (unlikely(r_sample <= t_elapsed))
 		if (unlikely(r_sample <= t_elapsed))
 			DCCP_WARN("r_sample=%ldus, t_elapsed=%ldus\n",
 			DCCP_WARN("r_sample=%ldus, t_elapsed=%ldus\n",
-				  r_sample, t_elapsed);
+				  (long)r_sample, (long)t_elapsed);
 		else
 		else
 			r_sample -= t_elapsed;
 			r_sample -= t_elapsed;
 		CCID3_RTT_SANITY_CHECK(r_sample);
 		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,
 	tmp = ip_route_connect(&rt, nexthop, inet->saddr,
 			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
 			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
 			       IPPROTO_DCCP,
 			       IPPROTO_DCCP,
-			       inet->sport, usin->sin_port, sk);
+			       inet->sport, usin->sin_port, sk, 1);
 	if (tmp < 0)
 	if (tmp < 0)
 		return tmp;
 		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)
 	if (final_p)
 		ipv6_addr_copy(&fl.fl6_dst, 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)
 	if (err < 0)
 		goto failure;
 		goto failure;
 
 

+ 2 - 2
net/dccp/proto.c

@@ -1024,7 +1024,6 @@ static int __init dccp_init(void)
 	do {
 	do {
 		dccp_hashinfo.ehash_size = (1UL << ehash_order) * PAGE_SIZE /
 		dccp_hashinfo.ehash_size = (1UL << ehash_order) * PAGE_SIZE /
 					sizeof(struct inet_ehash_bucket);
 					sizeof(struct inet_ehash_bucket);
-		dccp_hashinfo.ehash_size >>= 1;
 		while (dccp_hashinfo.ehash_size &
 		while (dccp_hashinfo.ehash_size &
 		       (dccp_hashinfo.ehash_size - 1))
 		       (dccp_hashinfo.ehash_size - 1))
 			dccp_hashinfo.ehash_size--;
 			dccp_hashinfo.ehash_size--;
@@ -1037,9 +1036,10 @@ static int __init dccp_init(void)
 		goto out_free_bind_bucket_cachep;
 		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);
 		rwlock_init(&dccp_hashinfo.ehash[i].lock);
 		INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain);
 		INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain);
+		INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].twchain);
 	}
 	}
 
 
 	bhash_order = ehash_order;
 	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);
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 
 	ifm = nlmsg_data(nlh);
 	ifm = nlmsg_data(nlh);
 	ifm->ifa_family = AF_DECnet;
 	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);
 	return nlmsg_end(skb, nlh);
 
 
 nla_put_failure:
 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)
 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;
 		goto errout;
 
 
 	err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
 	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);
 	err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
 errout:
 errout:
 	if (err < 0)
 	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:
 nlmsg_failure:
 rtattr_failure:
 rtattr_failure:
         skb_trim(skb, b - skb->data);
         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,
         err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
 			       f->fn_type, f->fn_scope, &f->fn_key, z,
 			       f->fn_type, f->fn_scope, &f->fn_key, z,
 			       DN_FIB_INFO(f), 0);
 			       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);
 	err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
 errout:
 errout:
 	if (err < 0)
 	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),
 			       RT_CONN_FLAGS(sk),
 			       sk->sk_bound_dev_if,
 			       sk->sk_bound_dev_if,
 			       sk->sk_protocol,
 			       sk->sk_protocol,
-			       inet->sport, inet->dport, sk);
+			       inet->sport, inet->dport, sk, 0);
 	if (err)
 	if (err)
 		return 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,
 	err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
 			       RT_CONN_FLAGS(sk), oif,
 			       RT_CONN_FLAGS(sk), oif,
 			       sk->sk_protocol,
 			       sk->sk_protocol,
-			       inet->sport, usin->sin_port, sk);
+			       inet->sport, usin->sin_port, sk, 1);
 	if (err)
 	if (err)
 		return err;
 		return err;
 	if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
 	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);
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 
 	ifm = nlmsg_data(nlh);
 	ifm = nlmsg_data(nlh);
 	ifm->ifa_family = AF_INET;
 	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);
 	return nlmsg_end(skb, nlh);
 
 
 nla_put_failure:
 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)
 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;
 		goto errout;
 
 
 	err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
 	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);
 	err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
 errout:
 errout:
 	if (err < 0)
 	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,
 	err = fib_dump_info(skb, info->pid, seq, event, tb_id,
 			    fa->fa_type, fa->fa_scope, key, dst_len,
 			    fa->fa_type, fa->fa_scope, key, dst_len,
 			    fa->fa_tos, fa->fa_info, 0);
 			    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,
 	err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
 			  info->nlh, GFP_KERNEL);
 			  info->nlh, GFP_KERNEL);
 errout:
 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);
 	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
 	if (nlh == NULL)
 	if (nlh == NULL)
-		return -ENOBUFS;
+		return -EMSGSIZE;
 
 
 	rtm = nlmsg_data(nlh);
 	rtm = nlmsg_data(nlh);
 	rtm->rtm_family = AF_INET;
 	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);
 	return nlmsg_end(skb, nlh);
 
 
 nla_put_failure:
 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);
 			skb = add_grhead(skb, pmc, type, &pgr);
 			first = 0;
 			first = 0;
 		}
 		}
+		if (!skb)
+			return NULL;
 		psrc = (__be32 *)skb_put(skb, sizeof(__be32));
 		psrc = (__be32 *)skb_put(skb, sizeof(__be32));
 		*psrc = psf->sf_inaddr;
 		*psrc = psf->sf_inaddr;
 		scount++; stotal++;
 		scount++; stotal++;

+ 11 - 8
net/ipv4/inet_diag.c

@@ -153,7 +153,7 @@ static int inet_csk_diag_fill(struct sock *sk,
 rtattr_failure:
 rtattr_failure:
 nlmsg_failure:
 nlmsg_failure:
 	skb_trim(skb, b - skb->data);
 	skb_trim(skb, b - skb->data);
-	return -1;
+	return -EMSGSIZE;
 }
 }
 
 
 static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
 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;
 	return skb->len;
 nlmsg_failure:
 nlmsg_failure:
 	skb_trim(skb, previous_tail - skb->data);
 	skb_trim(skb, previous_tail - skb->data);
-	return -1;
+	return -EMSGSIZE;
 }
 }
 
 
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
 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)
 	if (!rep)
 		goto out;
 		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,
 	err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid,
 			      MSG_DONTWAIT);
 			      MSG_DONTWAIT);
 	if (err > 0)
 	if (err > 0)
@@ -775,7 +778,7 @@ next_normal:
 			struct inet_timewait_sock *tw;
 			struct inet_timewait_sock *tw;
 
 
 			inet_twsk_for_each(tw, node,
 			inet_twsk_for_each(tw, node,
-				    &hashinfo->ehash[i + hashinfo->ehash_size].chain) {
+				    &head->twchain) {
 
 
 				if (num < s_num)
 				if (num < s_num)
 					goto next_dying;
 					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);
 	write_lock(&head->lock);
 
 
 	/* Check TIME-WAIT sockets first. */
 	/* 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);
 		tw = inet_twsk(sk2);
 
 
 		if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
 		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))
 	if (__sk_del_node_init(sk))
 		sock_prot_dec_use(sk->sk_prot);
 		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);
 	atomic_inc(&tw->tw_refcnt);
 
 
 	write_unlock(&ehead->lock);
 	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;
 				goto done;
 			dev = t->dev;
 			dev = t->dev;
 		}
 		}
-		err = unregister_netdevice(dev);
+		unregister_netdevice(dev);
+		err = 0;
 		break;
 		break;
 
 
 	default:
 	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;
 				goto done;
 			dev = t->dev;
 			dev = t->dev;
 		}
 		}
-		err = unregister_netdevice(dev);
+		unregister_netdevice(dev);
+		err = 0;
 		break;
 		break;
 
 
 	default:
 	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.
 	  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
 # NAT + specific targets: ip_conntrack
 config IP_NF_NAT
 config IP_NF_NAT
 	tristate "Full 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_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.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_CLUSTERIP) += ipt_CLUSTERIP.o
 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.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. */
     If it's non-zero, we mark only out of window RST segments as INVALID. */
 int ip_ct_tcp_be_liberal __read_mostly = 0;
 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. */
    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) 
 /* Max number of the retransmitted packets without receiving an (acceptable) 
    ACK from the destination. If this number is reached, a shorter timer 
    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),
 	    	before(sack, receiver->td_end + 1),
 	    	after(ack, receiver->td_end - MAXACKWINDOW(sender)));
 	    	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).
 		 * Take into account window scaling (RFC 1323).
 		 */
 		 */
@@ -743,15 +739,13 @@ static int tcp_in_window(struct ip_ct_tcp *state,
 				state->retrans = 0;
 				state->retrans = 0;
 			}
 			}
 		}
 		}
-		/*
-		 * Close the window of disabled window tracking :-)
-		 */
-		if (sender->loose)
-			sender->loose--;
-		
 		res = 1;
 		res = 1;
 	} else {
 	} 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,
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
 			"ip_ct_tcp: %s ",
 			"ip_ct_tcp: %s ",
 			before(seq, sender->td_maxend + 1) ?
 			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)"
 			: "ACK is over the upper bound (ACKed data not seen yet)"
 			: "SEQ is under the lower bound (already ACKed data retransmitted)"
 			: "SEQ is under the lower bound (already ACKed data retransmitted)"
 			: "SEQ is over the upper bound (over the window of the receiver)");
 			: "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 "
 	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]);
 		tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]);
 		conntrack->proto.tcp.seen[1].flags = 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) {
 	} else if (ip_ct_tcp_loose == 0) {
 		/* Don't try to pick up connections. */
 		/* Don't try to pick up connections. */
 		return 0;
 		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_maxwin;
 		conntrack->proto.tcp.seen[0].td_scale = 0;
 		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[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;
 	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 (maniptype == IP_NAT_MANIP_SRC) {
 		if (find_appropriate_src(orig_tuple, tuple, range)) {
 		if (find_appropriate_src(orig_tuple, tuple, range)) {
 			DEBUGP("get_unique_tuple: Found current src map\n");
 			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);
 	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 */
 	/* Only bother mapping if it's not already in range and unique */
 	if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
 	if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
 	     || proto->in_range(tuple, maniptype, &range->min, &range->max))
 	     || 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;
 	datalen = (*pskb)->len - iph->ihl*4;
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
 		tcph->check = 0;
 		tcph->check = 0;
-		tcph->check = tcp_v4_check(tcph, datalen,
+		tcph->check = tcp_v4_check(datalen,
 					   iph->saddr, iph->daddr,
 					   iph->saddr, iph->daddr,
 					   csum_partial((char *)tcph,
 					   csum_partial((char *)tcph,
 					   		datalen, 0));
 					   		datalen, 0));

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.