diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/Kconfig | 3 | ||||
-rw-r--r-- | arch/s390/crypto/Kconfig | 60 | ||||
-rw-r--r-- | arch/s390/crypto/aes_s390.c | 229 | ||||
-rw-r--r-- | arch/s390/crypto/prng.c | 4 | ||||
-rw-r--r-- | arch/s390/hypfs/inode.c | 13 | ||||
-rw-r--r-- | arch/s390/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/s390/kernel/early.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/head64.S | 2 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 1035 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 18 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 15 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 139 | ||||
-rw-r--r-- | arch/s390/kernel/signal.c | 20 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 575 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 20 | ||||
-rw-r--r-- | arch/s390/kernel/vmlinux.lds.S | 20 | ||||
-rw-r--r-- | arch/s390/lib/spinlock.c | 35 | ||||
-rw-r--r-- | arch/s390/mm/extmem.c | 2 | ||||
-rw-r--r-- | arch/s390/mm/vmem.c | 26 |
20 files changed, 1425 insertions, 799 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 1330061020a..6ef54d27fc0 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -276,9 +276,6 @@ source "kernel/Kconfig.preempt" source "mm/Kconfig" -config HOLES_IN_ZONE - def_bool y - comment "I/O subsystem configuration" config MACHCHK_WARNING diff --git a/arch/s390/crypto/Kconfig b/arch/s390/crypto/Kconfig deleted file mode 100644 index d1defbbfcd8..00000000000 --- a/arch/s390/crypto/Kconfig +++ /dev/null @@ -1,60 +0,0 @@ -config CRYPTO_SHA1_S390 - tristate "SHA1 digest algorithm" - depends on S390 - select CRYPTO_ALGAPI - help - This is the s390 hardware accelerated implementation of the - SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). - -config CRYPTO_SHA256_S390 - tristate "SHA256 digest algorithm" - depends on S390 - select CRYPTO_ALGAPI - help - This is the s390 hardware accelerated implementation of the - SHA256 secure hash standard (DFIPS 180-2). - - This version of SHA implements a 256 bit hash with 128 bits of - security against collision attacks. - -config CRYPTO_DES_S390 - tristate "DES and Triple DES cipher algorithms" - depends on S390 - select CRYPTO_ALGAPI - select CRYPTO_BLKCIPHER - help - This us the s390 hardware accelerated implementation of the - DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). - -config CRYPTO_AES_S390 - tristate "AES cipher algorithms" - depends on S390 - select CRYPTO_ALGAPI - select CRYPTO_BLKCIPHER - help - This is the s390 hardware accelerated implementation of the - AES cipher algorithms (FIPS-197). AES uses the Rijndael - algorithm. - - Rijndael appears to be consistently a very good performer in - both hardware and software across a wide range of computing - environments regardless of its use in feedback or non-feedback - modes. Its key setup time is excellent, and its key agility is - good. Rijndael's very low memory requirements make it very well - suited for restricted-space environments, in which it also - demonstrates excellent performance. Rijndael's operations are - among the easiest to defend against power and timing attacks. - - On s390 the System z9-109 currently only supports the key size - of 128 bit. - -config S390_PRNG - tristate "Pseudo random number generator device driver" - depends on S390 - default "m" - help - Select this option if you want to use the s390 pseudo random number - generator. The PRNG is part of the cryptographic processor functions - and uses triple-DES to generate secure random numbers like the - ANSI X9.17 standard. The PRNG is usable via the char device - /dev/prandom. diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 512669691ad..a3f67f8b542 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -6,6 +6,7 @@ * s390 Version: * Copyright IBM Corp. 2005,2007 * Author(s): Jan Glauber (jang@de.ibm.com) + * Sebastian Siewior (sebastian@breakpoint.cc> SW-Fallback * * Derived from "crypto/aes_generic.c" * @@ -16,17 +17,13 @@ * */ +#include <crypto/aes.h> #include <crypto/algapi.h> +#include <linux/err.h> #include <linux/module.h> #include <linux/init.h> #include "crypt_s390.h" -#define AES_MIN_KEY_SIZE 16 -#define AES_MAX_KEY_SIZE 32 - -/* data block size for all key lengths */ -#define AES_BLOCK_SIZE 16 - #define AES_KEYLEN_128 1 #define AES_KEYLEN_192 2 #define AES_KEYLEN_256 4 @@ -39,45 +36,89 @@ struct s390_aes_ctx { long enc; long dec; int key_len; + union { + struct crypto_blkcipher *blk; + struct crypto_cipher *cip; + } fallback; }; -static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) +/* + * Check if the key_len is supported by the HW. + * Returns 0 if it is, a positive number if it is not and software fallback is + * required or a negative number in case the key size is not valid + */ +static int need_fallback(unsigned int key_len) { - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; - switch (key_len) { case 16: if (!(keylen_flag & AES_KEYLEN_128)) - goto fail; + return 1; break; case 24: if (!(keylen_flag & AES_KEYLEN_192)) - goto fail; - + return 1; break; case 32: if (!(keylen_flag & AES_KEYLEN_256)) - goto fail; + return 1; break; default: - goto fail; + return -1; break; } + return 0; +} + +static int setkey_fallback_cip(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + int ret; + + sctx->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; + sctx->fallback.blk->base.crt_flags |= (tfm->crt_flags & + CRYPTO_TFM_REQ_MASK); + + ret = crypto_cipher_setkey(sctx->fallback.cip, in_key, key_len); + if (ret) { + tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; + tfm->crt_flags |= (sctx->fallback.blk->base.crt_flags & + CRYPTO_TFM_RES_MASK); + } + return ret; +} + +static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + u32 *flags = &tfm->crt_flags; + int ret; + + ret = need_fallback(key_len); + if (ret < 0) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } sctx->key_len = key_len; - memcpy(sctx->key, in_key, key_len); - return 0; -fail: - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; - return -EINVAL; + if (!ret) { + memcpy(sctx->key, in_key, key_len); + return 0; + } + + return setkey_fallback_cip(tfm, in_key, key_len); } static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + if (unlikely(need_fallback(sctx->key_len))) { + crypto_cipher_encrypt_one(sctx->fallback.cip, out, in); + return; + } + switch (sctx->key_len) { case 16: crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, @@ -98,6 +139,11 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + if (unlikely(need_fallback(sctx->key_len))) { + crypto_cipher_decrypt_one(sctx->fallback.cip, out, in); + return; + } + switch (sctx->key_len) { case 16: crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, @@ -114,6 +160,29 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) } } +static int fallback_init_cip(struct crypto_tfm *tfm) +{ + const char *name = tfm->__crt_alg->cra_name; + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + + sctx->fallback.cip = crypto_alloc_cipher(name, 0, + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK); + + if (IS_ERR(sctx->fallback.cip)) { + printk(KERN_ERR "Error allocating fallback algo %s\n", name); + return PTR_ERR(sctx->fallback.blk); + } + + return 0; +} + +static void fallback_exit_cip(struct crypto_tfm *tfm) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + + crypto_free_cipher(sctx->fallback.cip); + sctx->fallback.cip = NULL; +} static struct crypto_alg aes_alg = { .cra_name = "aes", @@ -125,6 +194,8 @@ static struct crypto_alg aes_alg = { .cra_ctxsize = sizeof(struct s390_aes_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_init = fallback_init_cip, + .cra_exit = fallback_exit_cip, .cra_u = { .cipher = { .cia_min_keysize = AES_MIN_KEY_SIZE, @@ -136,10 +207,70 @@ static struct crypto_alg aes_alg = { } }; +static int setkey_fallback_blk(struct crypto_tfm *tfm, const u8 *key, + unsigned int len) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + unsigned int ret; + + sctx->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; + sctx->fallback.blk->base.crt_flags |= (tfm->crt_flags & + CRYPTO_TFM_REQ_MASK); + + ret = crypto_blkcipher_setkey(sctx->fallback.blk, key, len); + if (ret) { + tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; + tfm->crt_flags |= (sctx->fallback.blk->base.crt_flags & + CRYPTO_TFM_RES_MASK); + } + return ret; +} + +static int fallback_blk_dec(struct blkcipher_desc *desc, + struct scatterlist *dst, struct scatterlist *src, + unsigned int nbytes) +{ + unsigned int ret; + struct crypto_blkcipher *tfm; + struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); + + tfm = desc->tfm; + desc->tfm = sctx->fallback.blk; + + ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes); + + desc->tfm = tfm; + return ret; +} + +static int fallback_blk_enc(struct blkcipher_desc *desc, + struct scatterlist *dst, struct scatterlist *src, + unsigned int nbytes) +{ + unsigned int ret; + struct crypto_blkcipher *tfm; + struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); + + tfm = desc->tfm; + desc->tfm = sctx->fallback.blk; + + ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes); + + desc->tfm = tfm; + return ret; +} + static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + int ret; + + ret = need_fallback(key_len); + if (ret > 0) { + sctx->key_len = key_len; + return setkey_fallback_blk(tfm, in_key, key_len); + } switch (key_len) { case 16: @@ -188,6 +319,9 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc, struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); struct blkcipher_walk walk; + if (unlikely(need_fallback(sctx->key_len))) + return fallback_blk_enc(desc, dst, src, nbytes); + blkcipher_walk_init(&walk, dst, src, nbytes); return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk); } @@ -199,10 +333,37 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc, struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); struct blkcipher_walk walk; + if (unlikely(need_fallback(sctx->key_len))) + return fallback_blk_dec(desc, dst, src, nbytes); + blkcipher_walk_init(&walk, dst, src, nbytes); return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk); } +static int fallback_init_blk(struct crypto_tfm *tfm) +{ + const char *name = tfm->__crt_alg->cra_name; + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + + sctx->fallback.blk = crypto_alloc_blkcipher(name, 0, + CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK); + + if (IS_ERR(sctx->fallback.blk)) { + printk(KERN_ERR "Error allocating fallback algo %s\n", name); + return PTR_ERR(sctx->fallback.blk); + } + + return 0; +} + +static void fallback_exit_blk(struct crypto_tfm *tfm) +{ + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + + crypto_free_blkcipher(sctx->fallback.blk); + sctx->fallback.blk = NULL; +} + static struct crypto_alg ecb_aes_alg = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-s390", @@ -214,6 +375,8 @@ static struct crypto_alg ecb_aes_alg = { .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list), + .cra_init = fallback_init_blk, + .cra_exit = fallback_exit_blk, .cra_u = { .blkcipher = { .min_keysize = AES_MIN_KEY_SIZE, @@ -229,6 +392,13 @@ static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + int ret; + + ret = need_fallback(key_len); + if (ret > 0) { + sctx->key_len = key_len; + return setkey_fallback_blk(tfm, in_key, key_len); + } switch (key_len) { case 16: @@ -283,6 +453,9 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc, struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); struct blkcipher_walk walk; + if (unlikely(need_fallback(sctx->key_len))) + return fallback_blk_enc(desc, dst, src, nbytes); + blkcipher_walk_init(&walk, dst, src, nbytes); return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk); } @@ -294,6 +467,9 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc, struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); struct blkcipher_walk walk; + if (unlikely(need_fallback(sctx->key_len))) + return fallback_blk_dec(desc, dst, src, nbytes); + blkcipher_walk_init(&walk, dst, src, nbytes); return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk); } @@ -309,6 +485,8 @@ static struct crypto_alg cbc_aes_alg = { .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list), + .cra_init = fallback_init_blk, + .cra_exit = fallback_exit_blk, .cra_u = { .blkcipher = { .min_keysize = AES_MIN_KEY_SIZE, @@ -336,14 +514,10 @@ static int __init aes_init(void) return -EOPNOTSUPP; /* z9 109 and z9 BC/EC only support 128 bit key length */ - if (keylen_flag == AES_KEYLEN_128) { - aes_alg.cra_u.cipher.cia_max_keysize = AES_MIN_KEY_SIZE; - ecb_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE; - cbc_aes_alg.cra_u.blkcipher.max_keysize = AES_MIN_KEY_SIZE; + if (keylen_flag == AES_KEYLEN_128) printk(KERN_INFO - "aes_s390: hardware acceleration only available for" + "aes_s390: hardware acceleration only available for " "128 bit keys\n"); - } ret = crypto_register_alg(&aes_alg); if (ret) @@ -382,4 +556,3 @@ MODULE_ALIAS("aes"); MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); MODULE_LICENSE("GPL"); - diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c index 8eb3a1aedc2..0cfefddd837 100644 --- a/arch/s390/crypto/prng.c +++ b/arch/s390/crypto/prng.c @@ -90,7 +90,7 @@ static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes, int ret = 0; int tmp; - /* nbytes can be arbitrary long, we spilt it into chunks */ + /* nbytes can be arbitrary length, we split it into chunks */ while (nbytes) { /* same as in extract_entropy_user in random.c */ if (need_resched()) { @@ -146,7 +146,7 @@ static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes, return ret; } -static struct file_operations prng_fops = { +static const struct file_operations prng_fops = { .owner = THIS_MODULE, .open = &prng_open, .release = NULL, diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index 5245717295b..4b010ff814c 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -490,7 +490,7 @@ static struct super_operations hypfs_s_ops = { .show_options = hypfs_show_options, }; -static decl_subsys(s390, NULL, NULL); +static struct kobject *s390_kobj; static int __init hypfs_init(void) { @@ -506,17 +506,18 @@ static int __init hypfs_init(void) goto fail_diag; } } - kobj_set_kset_s(&s390_subsys, hypervisor_subsys); - rc = subsystem_register(&s390_subsys); - if (rc) + s390_kobj = kobject_create_and_add("s390", hypervisor_kobj); + if (!s390_kobj) { + rc = -ENOMEM;; goto fail_sysfs; + } rc = register_filesystem(&hypfs_type); if (rc) goto fail_filesystem; return 0; fail_filesystem: - subsystem_unregister(&s390_subsys); + kobject_put(s390_kobj); fail_sysfs: if (!MACHINE_IS_VM) hypfs_diag_exit(); @@ -530,7 +531,7 @@ static void __exit hypfs_exit(void) if (!MACHINE_IS_VM) hypfs_diag_exit(); unregister_filesystem(&hypfs_type); - subsystem_unregister(&s390_subsys); + kobject_put(s390_kobj); } module_init(hypfs_init) diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 56cb71007cd..b3b650a93c7 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -31,7 +31,3 @@ S390_KEXEC_OBJS := machine_kexec.o crash.o S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS) -# -# This is just to get the dependencies... -# -binfmt_elf32.o: $(TOPDIR)/fs/binfmt_elf.c diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 1b3af7dab81..9f7b73b180f 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -276,7 +276,7 @@ void __init startup_init(void) create_kernel_nss(); sort_main_extable(); setup_lowcore_early(); - sclp_readinfo_early(); + sclp_read_info_early(); sclp_facilities_detect(); memsize = sclp_memory_detect(); #ifndef CONFIG_64BIT diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index a87b1976d40..79dccd206a6 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -157,7 +157,7 @@ startup_continue: .long 0xb2b10000 # store facility list tm 0xc8,0x08 # check bit for clearing-by-ASCE bno 0f-.LPG1(%r13) - lhi %r1,2094 + lhi %r1,2048 lhi %r2,0 .long 0xb98e2001 oi 7(%r12),0x80 # set IDTE flag diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index ce0856d3250..db28cca81fe 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -2,7 +2,7 @@ * arch/s390/kernel/ipl.c * ipl/reipl/dump support for Linux on s390. * - * Copyright (C) IBM Corp. 2005,2006 + * Copyright IBM Corp. 2005,2007 * Author(s): Michael Holzheu <holzheu@de.ibm.com> * Heiko Carstens <heiko.carstens@de.ibm.com> * Volker Sameske <sameske@de.ibm.com> @@ -31,6 +31,43 @@ #define IPL_FCP_DUMP_STR "fcp_dump" #define IPL_NSS_STR "nss" +#define DUMP_CCW_STR "ccw" +#define DUMP_FCP_STR "fcp" +#define DUMP_NONE_STR "none" + +/* + * Four shutdown trigger types are supported: + * - panic + * - halt + * - power off + * - reipl + */ +#define ON_PANIC_STR "on_panic" +#define ON_HALT_STR "on_halt" +#define ON_POFF_STR "on_poff" +#define ON_REIPL_STR "on_reboot" + +struct shutdown_action; +struct shutdown_trigger { + char *name; + struct shutdown_action *action; +}; + +/* + * Five shutdown action types are supported: + */ +#define SHUTDOWN_ACTION_IPL_STR "ipl" +#define SHUTDOWN_ACTION_REIPL_STR "reipl" +#define SHUTDOWN_ACTION_DUMP_STR "dump" +#define SHUTDOWN_ACTION_VMCMD_STR "vmcmd" +#define SHUTDOWN_ACTION_STOP_STR "stop" + +struct shutdown_action { + char *name; + void (*fn) (struct shutdown_trigger *trigger); + int (*init) (void); +}; + static char *ipl_type_str(enum ipl_type type) { switch (type) { @@ -54,10 +91,6 @@ enum dump_type { DUMP_TYPE_FCP = 4, }; -#define DUMP_NONE_STR "none" -#define DUMP_CCW_STR "ccw" -#define DUMP_FCP_STR "fcp" - static char *dump_type_str(enum dump_type type) { switch (type) { @@ -99,30 +132,6 @@ enum dump_method { DUMP_METHOD_FCP_DIAG, }; -enum shutdown_action { - SHUTDOWN_REIPL, - SHUTDOWN_DUMP, - SHUTDOWN_STOP, -}; - -#define SHUTDOWN_REIPL_STR "reipl" -#define SHUTDOWN_DUMP_STR "dump" -#define SHUTDOWN_STOP_STR "stop" - -static char *shutdown_action_str(enum shutdown_action action) -{ - switch (action) { - case SHUTDOWN_REIPL: - return SHUTDOWN_REIPL_STR; - case SHUTDOWN_DUMP: - return SHUTDOWN_DUMP_STR; - case SHUTDOWN_STOP: - return SHUTDOWN_STOP_STR; - default: - return NULL; - } -} - static int diag308_set_works = 0; static int reipl_capabilities = IPL_TYPE_UNKNOWN; @@ -140,8 +149,6 @@ static enum dump_method dump_method = DUMP_METHOD_NONE; static struct ipl_parameter_block *dump_block_fcp; static struct ipl_parameter_block *dump_block_ccw; -static enum shutdown_action on_panic_action = SHUTDOWN_STOP; - static struct sclp_ipl_info sclp_ipl_info; int diag308(unsigned long subcode, void *addr) @@ -162,22 +169,25 @@ EXPORT_SYMBOL_GPL(diag308); /* SYSFS */ #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \ -static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \ +static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, \ char *page) \ { \ return sprintf(page, _format, _value); \ } \ -static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ +static struct kobj_attribute sys_##_prefix##_##_name##_attr = \ __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL); #define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \ -static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \ +static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, \ char *page) \ { \ return sprintf(page, _fmt_out, \ (unsigned long long) _value); \ } \ -static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \ +static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \ + struct kobj_attribute *attr, \ const char *buf, size_t len) \ { \ unsigned long long value; \ @@ -186,25 +196,27 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \ _value = value; \ return len; \ } \ -static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ +static struct kobj_attribute sys_##_prefix##_##_name##_attr = \ __ATTR(_name,(S_IRUGO | S_IWUSR), \ sys_##_prefix##_##_name##_show, \ sys_##_prefix##_##_name##_store); #define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\ -static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \ +static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, \ char *page) \ { \ return sprintf(page, _fmt_out, _value); \ } \ -static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \ +static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \ + struct kobj_attribute *attr, \ const char *buf, size_t len) \ { \ - if (sscanf(buf, _fmt_in, _value) != 1) \ - return -EINVAL; \ + strncpy(_value, buf, sizeof(_value) - 1); \ + strstrip(_value); \ return len; \ } \ -static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ +static struct kobj_attribute sys_##_prefix##_##_name##_attr = \ __ATTR(_name,(S_IRUGO | S_IWUSR), \ sys_##_prefix##_##_name##_show, \ sys_##_prefix##_##_name##_store); @@ -240,44 +252,19 @@ static __init enum ipl_type get_ipl_type(void) return IPL_TYPE_FCP; } -void __init setup_ipl_info(void) -{ - ipl_info.type = get_ipl_type(); - switch (ipl_info.type) { - case IPL_TYPE_CCW: - ipl_info.data.ccw.dev_id.devno = ipl_devno; - ipl_info.data.ccw.dev_id.ssid = 0; - break; - case IPL_TYPE_FCP: - case IPL_TYPE_FCP_DUMP: - ipl_info.data.fcp.dev_id.devno = - IPL_PARMBLOCK_START->ipl_info.fcp.devno; - ipl_info.data.fcp.dev_id.ssid = 0; - ipl_info.data.fcp.wwpn = IPL_PARMBLOCK_START->ipl_info.fcp.wwpn; - ipl_info.data.fcp.lun = IPL_PARMBLOCK_START->ipl_info.fcp.lun; - break; - case IPL_TYPE_NSS: - strncpy(ipl_info.data.nss.name, kernel_nss_name, - sizeof(ipl_info.data.nss.name)); - break; - case IPL_TYPE_UNKNOWN: - default: - /* We have no info to copy */ - break; - } -} - struct ipl_info ipl_info; EXPORT_SYMBOL_GPL(ipl_info); -static ssize_t ipl_type_show(struct kset *kset, char *page) +static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr, + char *page) { return sprintf(page, "%s\n", ipl_type_str(ipl_info.type)); } -static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); +static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); -static ssize_t sys_ipl_device_show(struct kset *kset, char *page) +static ssize_t sys_ipl_device_show(struct kobject *kobj, + struct kobj_attribute *attr, char *page) { struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; @@ -292,7 +279,7 @@ static ssize_t sys_ipl_device_show(struct kset *kset, char *page) } } -static struct subsys_attribute sys_ipl_device_attr = +static struct kobj_attribute sys_ipl_device_attr = __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL); static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr, @@ -367,7 +354,8 @@ static struct attribute_group ipl_fcp_attr_group = { /* CCW ipl device attributes */ -static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page) +static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj, + struct kobj_attribute *attr, char *page) { char loadparm[LOADPARM_LEN + 1] = {}; @@ -379,7 +367,7 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page) return sprintf(page, "%s\n", loadparm); } -static struct subsys_attribute sys_ipl_ccw_loadparm_attr = +static struct kobj_attribute sys_ipl_ccw_loadparm_attr = __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); static struct attribute *ipl_ccw_attrs[] = { @@ -418,10 +406,76 @@ static struct attribute_group ipl_unknown_attr_group = { .attrs = ipl_unknown_attrs, }; -static decl_subsys(ipl, NULL, NULL); +static struct kset *ipl_kset; + +static int __init ipl_register_fcp_files(void) +{ + int rc; + + rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group); + if (rc) + goto out; + rc = sysfs_create_bin_file(&ipl_kset->kobj, &ipl_parameter_attr); + if (rc) + goto out_ipl_parm; + rc = sysfs_create_bin_file(&ipl_kset->kobj, &ipl_scp_data_attr); + if (!rc) + goto out; + + sysfs_remove_bin_file(&ipl_kset->kobj, &ipl_parameter_attr); + +out_ipl_parm: + sysfs_remove_group(&ipl_kset->kobj, &ipl_fcp_attr_group); +out: + return rc; +} + +static void ipl_run(struct shutdown_trigger *trigger) +{ + diag308(DIAG308_IPL, NULL); + if (MACHINE_IS_VM) + __cpcmd("IPL", NULL, 0, NULL); + else if (ipl_info.type == IPL_TYPE_CCW) + reipl_ccw_dev(&ipl_info.data.ccw.dev_id); +} + +static int ipl_init(void) +{ + int rc; + + ipl_kset = kset_create_and_add("ipl", NULL, firmware_kobj); + if (!ipl_kset) { + rc = -ENOMEM; + goto out; + } + switch (ipl_info.type) { + case IPL_TYPE_CCW: + rc = sysfs_create_group(&ipl_kset->kobj, &ipl_ccw_attr_group); + break; + case IPL_TYPE_FCP: + case IPL_TYPE_FCP_DUMP: + rc = ipl_register_fcp_files(); + break; + case IPL_TYPE_NSS: + rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nss_attr_group); + break; + default: + rc = sysfs_create_group(&ipl_kset->kobj, + &ipl_unknown_attr_group); + break; + } +out: + if (rc) + panic("ipl_init failed: rc = %i\n", rc); + + return 0; +} + +static struct shutdown_action ipl_action = {SHUTDOWN_ACTION_IPL_STR, ipl_run, + ipl_init}; /* - * reipl section + * reipl shutdown action: Reboot Linux on shutdown. */ /* FCP reipl device attributes */ @@ -465,7 +519,8 @@ static void reipl_get_ascii_loadparm(char *loadparm) strstrip(loadparm); } -static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page) +static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj, + struct kobj_attribute *attr, char *page) { char buf[LOADPARM_LEN + 1]; @@ -473,7 +528,8 @@ static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page) return sprintf(page, "%s\n", buf); } -static ssize_t reipl_ccw_loadparm_store(struct kset *kset, +static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t len) { int i, lp_len; @@ -500,7 +556,7 @@ static ssize_t reipl_ccw_loadparm_store(struct kset *kset, return len; } -static struct subsys_attribute sys_reipl_ccw_loadparm_attr = +static struct kobj_attribute sys_reipl_ccw_loadparm_attr = __ATTR(loadparm, 0644, reipl_ccw_loadparm_show, reipl_ccw_loadparm_store); @@ -539,7 +595,9 @@ static int reipl_set_type(enum ipl_type type) switch(type) { case IPL_TYPE_CCW: - if (MACHINE_IS_VM) + if (diag308_set_works) + reipl_method = REIPL_METHOD_CCW_DIAG; + else if (MACHINE_IS_VM) reipl_method = REIPL_METHOD_CCW_VM; else reipl_method = REIPL_METHOD_CCW_CIO; @@ -568,13 +626,15 @@ static int reipl_set_type(enum ipl_type type) return 0; } -static ssize_t reipl_type_show(struct kset *kset, char *page) +static ssize_t reipl_type_show(struct kobject *kobj, + struct kobj_attribute *attr, char *page) { return sprintf(page, "%s\n", ipl_type_str(reipl_type)); } -static ssize_t reipl_type_store(struct kset *kset, const char *buf, - size_t len) +static ssize_t reipl_type_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t len) { int rc = -EINVAL; @@ -587,140 +647,12 @@ static ssize_t reipl_type_store(struct kset *kset, const char *buf, return (rc != 0) ? rc : len; } -static struct subsys_attribute reipl_type_attr = - __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store); - -static decl_subsys(reipl, NULL, NULL); - -/* - * dump section - */ - -/* FCP dump device attributes */ - -DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n", - dump_block_fcp->ipl_info.fcp.wwpn); -DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n", - dump_block_fcp->ipl_info.fcp.lun); -DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n", - dump_block_fcp->ipl_info.fcp.bootprog); -DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n", - dump_block_fcp->ipl_info.fcp.br_lba); -DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n", - dump_block_fcp->ipl_info.fcp.devno); - -static struct attribute *dump_fcp_attrs[] = { - &sys_dump_fcp_device_attr.attr, - &sys_dump_fcp_wwpn_attr.attr, - &sys_dump_fcp_lun_attr.attr, - &sys_dump_fcp_bootprog_attr.attr, |