Skip to contentSkip to conversation

Pending patches in the s390 2.6.25 merge queue.

PATCH In review Martin Schwidefsky 6 participants 14 messages Nov 16, 2007 – Nov 19, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover Pending patches in the s390 2.6.25 merge queue.

The current set of patches queue for the next merge window with more to come. The shortlog:

Heiko Carstens (3):
[S390] sclp: call sclp_init() from start_kernel().
[S390] Standby cpu activation/deactivation.
[S390] sclp: convert channel path configure code to use sync interface.

Michael Ernst (1):
[S390] sclp: sysfs interface for SCLP cpi

Michael Holzheu (1):
[S390] kernel: Shutdown Actions Interface

Peter Oberparleiter (1):
[S390] cio: Extend adapter interrupt interface.

Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#1 lore raw

PATCH 1/6 sclp: sysfs interface for SCLP cpi

From: Michael Ernst <[email protected]>

---

 drivers/s390/char/Makefile       |    2 
 drivers/s390/char/sclp_cpi.c     |  246 +-----------------------
 drivers/s390/char/sclp_cpi_sys.c |  390 +++++++++++++++++++++++++++++++++++++++
 drivers/s390/char/sclp_cpi_sys.h |   15 +
 4 files changed, 422 insertions(+), 231 deletions(-)
drivers/s390/char/Makefile +1 -1
diff -urpN linux-2.6/drivers/s390/char/Makefile linux-2.6-patched/drivers/s390/char/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
-	 sclp_info.o sclp_config.o sclp_chp.o
+	 sclp_info.o sclp_config.o sclp_chp.o sclp_cpi_sys.o
 
 obj-$(CONFIG_TN3270) += raw3270.o
 obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
drivers/s390/char/sclp_cpi.c +16 -230

271 lines not on this page · raw message

drivers/s390/char/sclp_cpi_sys.c +390 -0

390 lines not on this page · raw message

drivers/s390/char/sclp_cpi_sys.h +15 -0
diff -urpN linux-2.6/drivers/s390/char/sclp_cpi_sys.h linux-2.6-patched/drivers/s390/char/sclp_cpi_sys.h
@@ -0,0 +1,15 @@
+/*
+ *  drivers/s390/char/sclp_cpi_sys.h
+ *    SCLP control program identification sysfs interface
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Michael Ernst <[email protected]>
+ */
+
+#ifndef __SCLP_CPI_SYS_H__
+#define __SCLP_CPI_SYS_H__
+
+int sclp_cpi_set_data(const char *system, const char *sysplex,
+		      const char *type, u64 level);
+
+#endif	 /* __SCLP_CPI_SYS_H__ */
Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#2 lore raw

Re: [patch 1/6] sclp: sysfs interface for SCLP cpi

drivers/s390/char/sclp_cpi_sys.c line 350

Quoted 3 lines · Martin Schwidefsky
drivers/s390/char/sclp_cpi_sys.c +3 -0
+
+static decl_subsys(cpi, NULL, NULL);
+

decl_subsys() and all other static kset cruft called "subsys" will be gone with 2.6.25.
The patch series doing this is in -mm, and this patch will need (trivial) adaption to the
new interfaces.

Thanks,
Kay

#3 lore raw

Re: [patch 1/6] sclp: sysfs interface for SCLP cpi

Quoted 10 lines · Kay Sievers

drivers/s390/char/sclp_cpi_sys.c line 350

Quoted 3 lines · Martin Schwidefsky
drivers/s390/char/sclp_cpi_sys.c +3 -0
+
+static decl_subsys(cpi, NULL, NULL);
+

decl_subsys() and all other static kset cruft called "subsys" will be gone with 2.6.25.
The patch series doing this is in -mm, and this patch will need (trivial) adaption to the
new interfaces.

Andrew has this one in his lineup:

http://www.eu.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.24-rc2/2.6.24-rc2-mm1/broken-out/adapt-sclp_cpi_sysc-to-the-kobject-kset-changes.patch

#4 lore raw

Re: [patch 1/6] sclp: sysfs interface for SCLP cpi

In reply to Kay Sievers
Quoted 10 lines · Kay Sievers

drivers/s390/char/sclp_cpi_sys.c line 350

Quoted 3 lines · Martin Schwidefsky
drivers/s390/char/sclp_cpi_sys.c +3 -0
+
+static decl_subsys(cpi, NULL, NULL);
+

decl_subsys() and all other static kset cruft called "subsys" will be gone with 2.6.25.
The patch series doing this is in -mm, and this patch will need (trivial) adaption to the
new interfaces.

The "trainwreck" how Andrew has called it..
We have two git repositories with new code, both are against the mainline git. After both repositories are merged we have push another patch with the adaptions for the s390 code. The usual upstream fixing I would say. Thanks for the hint.

Signature · 4 lines
blue skies,
  Martin.

"Reality continues to ruin my life." - Calvin.
#5 lore raw

PATCH 2/6 cio: Extend adapter interrupt interface.

In reply to Martin Schwidefsky

From: Peter Oberparleiter <[email protected]>
From: Cornelia Huck <[email protected]>

Change the adapter interrupt interface in order to allow multiple adapter interrupt handlers to be registered. Indicators are now allocated by cio instead of the device driver.

The qdio parts have been

---

 Documentation/DocBook/s390-drivers.tmpl |    1 
 drivers/s390/cio/airq.c                 |  177 +++++++++++++++++++++-----------
 drivers/s390/cio/airq.h                 |   10 -
 drivers/s390/cio/cio.c                  |    2 
 drivers/s390/cio/cio.h                  |    1 
 drivers/s390/cio/qdio.c                 |   35 +++---
 include/asm-s390/airq.h                 |   19 +++
 7 files changed, 157 insertions(+), 88 deletions(-)
Documentation/DocBook/s390-drivers.tmpl +1 -0
diff -urpN linux-2.6/Documentation/DocBook/s390-drivers.tmpl linux-2.6-patched/Documentation/DocBook/s390-drivers.tmpl
@@ -116,6 +116,7 @@
 !Iinclude/asm-s390/ccwdev.h
 !Edrivers/s390/cio/device.c
 !Edrivers/s390/cio/device_ops.c
+!Edrivers/s390/cio/airq.c
     </sect1>
     <sect1 id="cmf">
      <title>The channel-measurement facility</title>
drivers/s390/cio/airq.c +118 -59

202 lines not on this page · raw message

drivers/s390/cio/airq.h +0 -10
diff -urpN linux-2.6/drivers/s390/cio/airq.h linux-2.6-patched/drivers/s390/cio/airq.h
@@ -1,10 +0,0 @@
-#ifndef S390_AINTERRUPT_H
-#define S390_AINTERRUPT_H
-
-typedef	int (*adapter_int_handler_t)(void);
-
-extern int s390_register_adapter_interrupt(adapter_int_handler_t handler);
-extern int s390_unregister_adapter_interrupt(adapter_int_handler_t handler);
-extern void do_adapter_IO (void);
-
-#endif
drivers/s390/cio/cio.c +1 -1
diff -urpN linux-2.6/drivers/s390/cio/cio.c linux-2.6-patched/drivers/s390/cio/cio.c
@@ -23,7 +23,7 @@
 #include <asm/reset.h>
 #include <asm/ipl.h>
 #include <asm/chpid.h>
-#include "airq.h"
+#include <asm/airq.h>
 #include "cio.h"
 #include "css.h"
 #include "chsc.h"
drivers/s390/cio/cio.h +1 -0
diff -urpN linux-2.6/drivers/s390/cio/cio.h linux-2.6-patched/drivers/s390/cio/cio.h
@@ -125,6 +125,7 @@ extern int cio_get_options (struct subch
 extern int cio_modify (struct subchannel *);
 
 int cio_create_sch_lock(struct subchannel *);
+void do_adapter_IO(void);
 
 /* Use with care. */
 #ifdef CONFIG_CCW_CONSOLE
drivers/s390/cio/qdio.c +17 -18
diff -urpN linux-2.6/drivers/s390/cio/qdio.c linux-2.6-patched/drivers/s390/cio/qdio.c
@@ -48,11 +48,11 @@
 #include <asm/debug.h>
 #include <asm/s390_rdev.h>
 #include <asm/qdio.h>
+#include <asm/airq.h>
 
 #include "cio.h"
 #include "css.h"
 #include "device.h"
-#include "airq.h"
 #include "qdio.h"
 #include "ioasm.h"
 #include "chsc.h"
@@ -96,7 +96,7 @@ static debug_info_t *qdio_dbf_slsb_in;
 static volatile struct qdio_q *tiq_list=NULL; /* volatile as it could change
 						 during a while loop */
 static DEFINE_SPINLOCK(ttiq_list_lock);
-static int register_thinint_result;
+static void *tiqdio_ind;
 static void tiqdio_tl(unsigned long);
 static DECLARE_TASKLET(tiqdio_tasklet,tiqdio_tl,0);
 
@@ -399,7 +399,7 @@ qdio_get_indicator(void)
 {
 	int i;
 
-	for (i=1;i<INDICATORS_PER_CACHELINE;i++)
+	for (i = 0; i < INDICATORS_PER_CACHELINE; i++)
 		if (!indicator_used[i]) {
 			indicator_used[i]=1;
 			return indicators+i;
@@ -1911,8 +1911,7 @@ qdio_fill_thresholds(struct qdio_irq *ir
 	}
 }
 
-static int
-tiqdio_thinint_handler(void)
+static void tiqdio_thinint_handler(void *ind, void *drv_data)
 {
 	QDIO_DBF_TEXT4(0,trace,"thin_int");
 
@@ -1925,7 +1924,6 @@ tiqdio_thinint_handler(void)
 		tiqdio_clear_global_summary();
 
 	tiqdio_inbound_checks();
-	return 0;
 }
 
 static void
@@ -2445,7 +2443,7 @@ tiqdio_set_subchannel_ind(struct qdio_ir
 		real_addr_dev_st_chg_ind=0;
 	} else {
 		real_addr_local_summary_bit=
-			virt_to_phys((volatile void *)indicators);
+			virt_to_phys((volatile void *)tiqdio_ind);
 		real_addr_dev_st_chg_ind=
 			virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind);
 	}
@@ -3740,23 +3738,25 @@ static void
 tiqdio_register_thinints(void)
 {
 	char dbf_text[20];
-	register_thinint_result=
-		s390_register_adapter_interrupt(&tiqdio_thinint_handler);
-	if (register_thinint_result) {
-		sprintf(dbf_text,"regthn%x",(register_thinint_result&0xff));
+
+	tiqdio_ind =
+		s390_register_adapter_interrupt(&tiqdio_thinint_handler, NULL);
+	if (IS_ERR(tiqdio_ind)) {
+		sprintf(dbf_text, "regthn%lx", PTR_ERR(tiqdio_ind));
 		QDIO_DBF_TEXT0(0,setup,dbf_text);
 		QDIO_PRINT_ERR("failed to register adapter handler " \
-			       "(rc=%i).\nAdapter interrupts might " \
+			       "(rc=%li).\nAdapter interrupts might " \
 			       "not work. Continuing.\n",
-			       register_thinint_result);
+			       PTR_ERR(tiqdio_ind));
+		tiqdio_ind = NULL;
 	}
 }
 
 static void
 tiqdio_unregister_thinints(void)
 {
-	if (!register_thinint_result)
-		s390_unregister_adapter_interrupt(&tiqdio_thinint_handler);
+	if (tiqdio_ind)
+		s390_unregister_adapter_interrupt(tiqdio_ind);
 }
 
 static int
@@ -3768,8 +3768,8 @@ qdio_get_qdio_memory(void)
 	for (i=1;i<INDICATORS_PER_CACHELINE;i++)
 		indicator_used[i]=0;
 	indicators = kzalloc(sizeof(__u32)*(INDICATORS_PER_CACHELINE),
-				   GFP_KERNEL);
-       	if (!indicators)
+			     GFP_KERNEL);
+	if (!indicators)
 		return -ENOMEM;
 	return 0;
 }
@@ -3780,7 +3780,6 @@ qdio_release_qdio_memory(void)
 	kfree(indicators);
 }
 
-
 static void
 qdio_unregister_dbf_views(void)
 {
include/asm-s390/airq.h +19 -0
diff -urpN linux-2.6/include/asm-s390/airq.h linux-2.6-patched/include/asm-s390/airq.h
@@ -0,0 +1,19 @@
+/*
+ *  include/asm-s390/airq.h
+ *
+ *    Copyright IBM Corp. 2002,2007
+ *    Author(s): Ingo Adlung <[email protected]>
+ *		 Cornelia Huck <[email protected]>
+ *		 Arnd Bergmann <[email protected]>
+ *		 Peter Oberparleiter <[email protected]>
+ */
+
+#ifndef _ASM_S390_AIRQ_H
+#define _ASM_S390_AIRQ_H
+
+typedef void (*adapter_int_handler_t)(void *, void *);
+
+void *s390_register_adapter_interrupt(adapter_int_handler_t, void *);
+void s390_unregister_adapter_interrupt(void *);
+
+#endif /* _ASM_S390_AIRQ_H */
Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#6 lore raw

PATCH 3/6 sclp: call sclp_init() from start_kernel().

In reply to Martin Schwidefsky

From: Heiko Carstens <[email protected]>

This is needed since the sclp must be initialized before cpus are brought online and after interrupts are enabled. The sclp interface is used figure out which cpus are present and can be brought online. Adding an sclp_init() call to __cpu_up() is not a valid option.

---

 drivers/s390/char/sclp.c |   12 ++----------
 init/main.c              |    6 ++++++
 2 files changed, 8 insertions(+), 10 deletions(-)
drivers/s390/char/sclp.c +2 -10
diff -urpN linux-2.6/drivers/s390/char/sclp.c linux-2.6-patched/drivers/s390/char/sclp.c
@@ -95,7 +95,7 @@ static volatile enum sclp_mask_state_t {
 static void sclp_process_queue(void);
 static void __sclp_make_read_req(void);
 static int sclp_init_mask(int calculate);
-static int sclp_init(void);
+int sclp_init(void);
 
 /* Perform service call. Return 0 on success, non-zero otherwise. */
 int
@@ -877,8 +877,7 @@ static struct notifier_block sclp_reboot
 
 /* Initialize SCLP driver. Return zero if driver is operational, non-zero
  * otherwise. */
-static int
-sclp_init(void)
+int sclp_init(void)
 {
 	unsigned long flags;
 	int rc;
@@ -930,10 +929,3 @@ sclp_init(void)
 	sclp_init_mask(1);
 	return 0;
 }
-
-static __init int sclp_initcall(void)
-{
-	return sclp_init();
-}
-
-arch_initcall(sclp_initcall);
init/main.c +6 -0
diff -urpN linux-2.6/init/main.c linux-2.6-patched/init/main.c
@@ -94,6 +94,11 @@ extern void acpi_early_init(void);
 #else
 static inline void acpi_early_init(void) { }
 #endif
+#ifdef CONFIG_S390
+extern int sclp_init(void);
+#else
+static inline int sclp_init(void) {return 0;}
+#endif
 #ifndef CONFIG_DEBUG_RODATA
 static inline void mark_rodata_ro(void) { }
 #endif
@@ -643,6 +648,7 @@ asmlinkage void __init start_kernel(void
 	check_bugs();
 
 	acpi_early_init(); /* before LAPIC and SMP init */
+	sclp_init();
 
 	/* Do the rest non-__init'ed, we're now alive */
 	rest_init();
Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#7 lore raw

Re: [patch 3/6] sclp: call sclp_init() from start_kernel().

Quoted 12 lines · Martin Schwidefsky

#else
static inline void acpi_early_init(void) { }
#endif

init/main.c +5 -0
+#ifdef CONFIG_S390
+extern int sclp_init(void);
+#else
+static inline int sclp_init(void) {return 0;}
+#endif
 #ifndef CONFIG_DEBUG_RODATA
 static inline void mark_rodata_ro(void) { }
 #endif

init/main.c asmlinkage void __init start_kernel(void · line 651

Quoted 4 lines
init/main.c +1 -0
@@ -643,6 +648,7 @@ asmlinkage void __init start_kernel(void
 	check_bugs();
 
 	acpi_early_init(); /* before LAPIC and SMP init */
+	sclp_init();

What happens if sclp_init fails? The other early init calls explicitely returns void and handels the error internal.

Bastian

Signature · 2 lines
Time is fluid ... like a river with currents, eddies, backwash.
		-- Spock, "The City on the Edge of Forever", stardate 3134.0
#8 lore raw

Re: [patch 3/6] sclp: call sclp_init() from start_kernel().

Quoted 15 lines · Bastian Blank
Quoted 14 lines · Martin Schwidefsky

#else
static inline void acpi_early_init(void) { }
#endif

init/main.c +5 -0
+#ifdef CONFIG_S390
+extern int sclp_init(void);
+#else
+static inline int sclp_init(void) {return 0;}
+#endif
 #ifndef CONFIG_DEBUG_RODATA
 static inline void mark_rodata_ro(void) { }
 #endif
@@ -643,6 +648,7 @@ asmlinkage void __init start_kernel(void
 	check_bugs();
 
Quoted 5 lines

init/main.c asmlinkage void __init start_kernel(void · line 651

Quoted 2 lines
init/main.c +1 -0
 	acpi_early_init(); /* before LAPIC and SMP init */
+	sclp_init();

What happens if sclp_init fails? The other early init calls explicitely returns void and handels the error internal.

Nothing. I used to have an sclp call within __cpu_up() but that is gone since I rewrote the patch that follows this one.
So this patch is just a leftover and I forgot that it isn't needed anymore. Will be dropped.

Thanks for the hint!

#9 lore raw

PATCH 4/6 Standby cpu activation/deactivation.

In reply to Martin Schwidefsky

From: Heiko Carstens <[email protected]>

Use the sclp interface so that also standby cpus can be activated and deactivated. CPUs that are brought offline will be automatically put in standby state.
If a logical cpu is brought online the first cpu in stopped state will be used. If none is available the first standby cpu will be used. On IPL only configured cpus will be used. And on reboot/shutdown all cpus will remain in their current state (configured/standby).

---

 arch/s390/kernel/early.c      |    3 
 arch/s390/kernel/setup.c      |    2 
 arch/s390/kernel/smp.c        |  401 ++++++++++++++++++++++++++++++++++--------
 drivers/s390/char/Makefile    |    2 
 drivers/s390/char/sclp.h      |    4 
 drivers/s390/char/sclp_cmd.c  |  319 +++++++++++++++++++++++++++++++++
 drivers/s390/char/sclp_info.c |  116 ------------
 include/asm-s390/sclp.h       |   21 ++
 8 files changed, 675 insertions(+), 193 deletions(-)
arch/s390/kernel/early.c +2 -1
diff -urpN linux-2.6/arch/s390/kernel/early.c linux-2.6-patched/arch/s390/kernel/early.c
@@ -276,8 +276,9 @@ void __init startup_init(void)
 	create_kernel_nss();
 	sort_main_extable();
 	setup_lowcore_early();
-	sclp_readinfo_early();
+	sclp_read_info_early();
 	sclp_facilities_detect();
+	sclp_read_cpu_info_early();
 	memsize = sclp_memory_detect();
 #ifndef CONFIG_64BIT
 	/*
arch/s390/kernel/setup.c +1 -1
diff -urpN linux-2.6/arch/s390/kernel/setup.c linux-2.6-patched/arch/s390/kernel/setup.c
@@ -922,7 +922,7 @@ setup_arch(char **cmdline_p)
 
 void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
 {
-   printk("cpu %d "
+   printk(KERN_INFO "cpu %d "
 #ifdef CONFIG_SMP
            "phys_idx=%d "
 #endif
arch/s390/kernel/smp.c +330 -71

529 lines not on this page · raw message

drivers/s390/char/Makefile +1 -1
diff -urpN linux-2.6/drivers/s390/char/Makefile linux-2.6-patched/drivers/s390/char/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
-	 sclp_info.o sclp_config.o sclp_chp.o sclp_cpi_sys.o
+	 sclp_cmd.o sclp_config.o sclp_chp.o sclp_cpi_sys.o
 
 obj-$(CONFIG_TN3270) += raw3270.o
 obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
drivers/s390/char/sclp_cmd.c +319 -0

319 lines not on this page · raw message

drivers/s390/char/sclp.h +2 -2
diff -urpN linux-2.6/drivers/s390/char/sclp.h linux-2.6-patched/drivers/s390/char/sclp.h
@@ -56,8 +56,6 @@ typedef unsigned int sclp_cmdw_t;
 #define SCLP_CMDW_READ_EVENT_DATA	0x00770005
 #define SCLP_CMDW_WRITE_EVENT_DATA	0x00760005
 #define SCLP_CMDW_WRITE_EVENT_MASK	0x00780005
-#define SCLP_CMDW_READ_SCP_INFO		0x00020001
-#define SCLP_CMDW_READ_SCP_INFO_FORCED	0x00120001
 
 #define GDS_ID_MDSMU		0x1310
 #define GDS_ID_MDSROUTEINFO	0x1311
@@ -83,6 +81,8 @@ extern u64 sclp_facilities;
 
 #define SCLP_HAS_CHP_INFO	(sclp_facilities & 0x8000000000000000ULL)
 #define SCLP_HAS_CHP_RECONFIG	(sclp_facilities & 0x2000000000000000ULL)
+#define SCLP_HAS_CPU_INFO	(sclp_facilities & 0x0800000000000000ULL)
+#define SCLP_HAS_CPU_RECONFIG	(sclp_facilities & 0x0400000000000000ULL)
 
 struct gds_subvector {
 	u8	length;
drivers/s390/char/sclp_info.c +0 -116

116 lines not on this page · raw message

include/asm-s390/sclp.h +20 -1
diff -urpN linux-2.6/include/asm-s390/sclp.h linux-2.6-patched/include/asm-s390/sclp.h
@@ -27,7 +27,26 @@ struct sclp_ipl_info {
 	char loadparm[LOADPARM_LEN];
 };
 
-void sclp_readinfo_early(void);
+struct sclp_cpu_entry {
+	u8 address;
+	u8 reserved0[13];
+	u8 type;
+	u8 reserved1;
+} __attribute__((packed));
+
+struct sclp_cpu_info {
+	unsigned int configured;
+	unsigned int standby;
+	unsigned int combined;
+	int has_cpu_type;
+	struct sclp_cpu_entry cpu[255];
+};
+
+int sclp_get_cpu_info(struct sclp_cpu_info *info);
+int sclp_cpu_configure(u8 cpu);
+int sclp_cpu_deconfigure(u8 cpu);
+void sclp_read_info_early(void);
+void sclp_read_cpu_info_early(void);
 void sclp_facilities_detect(void);
 unsigned long long sclp_memory_detect(void);
 int sclp_sdias_blk_count(void);
Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#10 lore raw

PATCH 5/6 sclp: convert channel path configure code to use sync interface.

In reply to Martin Schwidefsky

From: Heiko Carstens <[email protected]>

---

 drivers/s390/char/Makefile   |    2 
 drivers/s390/char/sclp_chp.c |  200 -------------------------------------------
 drivers/s390/char/sclp_cmd.c |  123 ++++++++++++++++++++++++++
 3 files changed, 123 insertions(+), 202 deletions(-)
drivers/s390/char/Makefile +1 -1
diff -urpN linux-2.6/drivers/s390/char/Makefile linux-2.6-patched/drivers/s390/char/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
-	 sclp_cmd.o sclp_config.o sclp_chp.o sclp_cpi_sys.o
+	 sclp_cmd.o sclp_config.o sclp_cpi_sys.o
 
 obj-$(CONFIG_TN3270) += raw3270.o
 obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
drivers/s390/char/sclp_chp.c +0 -200

200 lines not on this page · raw message

drivers/s390/char/sclp_cmd.c +122 -1

138 lines not on this page · raw message

Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#11 lore raw

PATCH 6/6 kernel: Shutdown Actions Interface

In reply to Martin Schwidefsky

From: Michael Holzheu <[email protected]>

In case of a kernel panic it is currently possible to specify that a dump should be created, the system should be rebooted or stopped. Virtual sysfs files under the directory /sys/firmware/ are used for that configuration. In addition to that, there are kernel parameters 'vmhalt', 'vmpoff' and 'vmpanic', which can be used to specify z/VM commands, which are automatically executed in case of halt, power off or a kernel panic. This patch combines both functionalities and allows to specify the z/VM CP commands also via sysfs attributes. In addition to that, it enhances the existing handling of shutdown triggers (e.g. halt or panic) and associated shutdown actions (e.g. dump or reipl) and makes it more flexible.

---

 arch/s390/kernel/ipl.c   |  923 ++++++++++++++++++++++++++++++-----------------
 arch/s390/kernel/setup.c |  103 -----
 arch/s390/kernel/smp.c   |   27 -
 include/asm-s390/ipl.h   |    4 
 4 files changed, 595 insertions(+), 462 deletions(-)
arch/s390/kernel/ipl.c +591 -332
diff -urpN linux-2.6/arch/s390/kernel/ipl.c linux-2.6-patched/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 <[email protected]>
  *		 Heiko Carstens <[email protected]>
  *		 Volker Sameske <[email protected]>
@@ -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 = DU
 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)
@@ -200,8 +207,8 @@ static ssize_t sys_##_prefix##_##_name##
 static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset,	\
 		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 =		\
@@ -240,33 +247,6 @@ static __init enum ipl_type get_ipl_type
 	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);
 
@@ -420,8 +400,77 @@ static struct attribute_group ipl_unknow
 
 static decl_subsys(ipl, NULL, NULL);
 
+static int __init ipl_register_fcp_files(void)
+{
+	int rc;
+
+	rc = sysfs_create_group(&ipl_subsys.kobj,
+				&ipl_fcp_attr_group);
+	if (rc)
+		goto out;
+	rc = sysfs_create_bin_file(&ipl_subsys.kobj,
+				   &ipl_parameter_attr);
+	if (rc)
+		goto out_ipl_parm;
+	rc = sysfs_create_bin_file(&ipl_subsys.kobj,
+				   &ipl_scp_data_attr);
+	if (!rc)
+		goto out;
+
+	sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr);
+
+out_ipl_parm:
+	sysfs_remove_group(&ipl_subsys.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;
+
+	rc = firmware_register(&ipl_subsys);
+	if (rc)
+		goto out;
+	switch (ipl_info.type) {
+	case IPL_TYPE_CCW:
+		rc = sysfs_create_group(&ipl_subsys.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_subsys.kobj,
+					&ipl_nss_attr_group);
+		break;
+	default:
+		rc = sysfs_create_group(&ipl_subsys.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 */
@@ -592,135 +641,7 @@ static struct subsys_attribute reipl_typ
 
 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,
-	&sys_dump_fcp_br_lba_attr.attr,
-	NULL,
-};
-
-static struct attribute_group dump_fcp_attr_group = {
-	.name  = IPL_FCP_STR,
-	.attrs = dump_fcp_attrs,
-};
-
-/* CCW dump device attributes */
-
-DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
-		   dump_block_ccw->ipl_info.ccw.devno);
-
-static struct attribute *dump_ccw_attrs[] = {
-	&sys_dump_ccw_device_attr.attr,
-	NULL,
-};
-
-static struct attribute_group dump_ccw_attr_group = {
-	.name  = IPL_CCW_STR,
-	.attrs = dump_ccw_attrs,
-};
-
-/* dump type */
-
-static int dump_set_type(enum dump_type type)
-{
-	if (!(dump_capabilities & type))
-		return -EINVAL;
-	switch(type) {
-	case DUMP_TYPE_CCW:
-		if (MACHINE_IS_VM)
-			dump_method = DUMP_METHOD_CCW_VM;
-		else if (diag308_set_works)
-			dump_method = DUMP_METHOD_CCW_DIAG;
-		else
-			dump_method = DUMP_METHOD_CCW_CIO;
-		break;
-	case DUMP_TYPE_FCP:
-		dump_method = DUMP_METHOD_FCP_DIAG;
-		break;
-	default:
-		dump_method = DUMP_METHOD_NONE;
-	}
-	dump_type = type;
-	return 0;
-}
-
-static ssize_t dump_type_show(struct kset *kset, char *page)
-{
-	return sprintf(page, "%s\n", dump_type_str(dump_type));
-}
-
-static ssize_t dump_type_store(struct kset *kset, const char *buf,
-			       size_t len)
-{
-	int rc = -EINVAL;
-
-	if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
-		rc = dump_set_type(DUMP_TYPE_NONE);
-	else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
-		rc = dump_set_type(DUMP_TYPE_CCW);
-	else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
-		rc = dump_set_type(DUMP_TYPE_FCP);
-	return (rc != 0) ? rc : len;
-}
-
-static struct subsys_attribute dump_type_attr =
-		__ATTR(dump_type, 0644, dump_type_show, dump_type_store);
-
-static decl_subsys(dump, NULL, NULL);
-
-/*
- * Shutdown actions section
- */
-
-static decl_subsys(shutdown_actions, NULL, NULL);
-
-/* on panic */
-
-static ssize_t on_panic_show(struct kset *kset, char *page)
-{
-	return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
-}
-
-static ssize_t on_panic_store(struct kset *kset, const char *buf,
-			      size_t len)
-{
-	if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
-		on_panic_action = SHUTDOWN_REIPL;
-	else if (strncmp(buf, SHUTDOWN_DUMP_STR,
-			 strlen(SHUTDOWN_DUMP_STR)) == 0)
-		on_panic_action = SHUTDOWN_DUMP;
-	else if (strncmp(buf, SHUTDOWN_STOP_STR,
-			 strlen(SHUTDOWN_STOP_STR)) == 0)
-		on_panic_action = SHUTDOWN_STOP;
-	else
-		return -EINVAL;
-
-	return len;
-}
-
-static struct subsys_attribute on_panic_attr =
-		__ATTR(on_panic, 0644, on_panic_show, on_panic_store);
-
-void do_reipl(void)
+void reipl_run(struct shutdown_trigger *trigger)
 {
 	struct ccw_dev_id devid;
 	static char buf[100];
@@ -771,110 +692,18 @@ void do_reipl(void)
 	default:
 		break;
 	}
-	signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
-static void do_dump(void)
+static void __init reipl_probe(void)
 {
-	struct ccw_dev_id devid;
-	static char buf[100];
+	void *buffer;
 
-	switch (dump_method) {
-	case DUMP_METHOD_CCW_CIO:
-		smp_send_stop();
-		devid.devno = dump_block_ccw->ipl_info.ccw.devno;
-		devid.ssid  = 0;
-		reipl_ccw_dev(&devid);
-		break;
-	case DUMP_METHOD_CCW_VM:
-		smp_send_stop();
-		sprintf(buf, "STORE STATUS");
-		__cpcmd(buf, NULL, 0, NULL);
-		sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
-		__cpcmd(buf, NULL, 0, NULL);
-		break;
-	case DUMP_METHOD_CCW_DIAG:
-		diag308(DIAG308_SET, dump_block_ccw);
-		diag308(DIAG308_DUMP, NULL);
-		break;
-	case DUMP_METHOD_FCP_DIAG:
-		diag308(DIAG308_SET, dump_block_fcp);
-		diag308(DIAG308_DUMP, NULL);
-		break;
-	case DUMP_METHOD_NONE:
-	default:
+	buffer = (void *) get_zeroed_page(GFP_KERNEL);
+	if (!buffer)
 		return;
-	}
-	printk(KERN_EMERG "Dump failed!\n");
-}
-
-/* init functions */
-
-static int __init ipl_register_fcp_files(void)
-{
-	int rc;
-
-	rc = sysfs_create_group(&ipl_subsys.kobj,
-				&ipl_fcp_attr_group);
-	if (rc)
-		goto out;
-	rc = sysfs_create_bin_file(&ipl_subsys.kobj,
-				   &ipl_parameter_attr);
-	if (rc)
-		goto out_ipl_parm;
-	rc = sysfs_create_bin_file(&ipl_subsys.kobj,
-				   &ipl_scp_data_attr);
-	if (!rc)
-		goto out;
-
-	sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr);
-
-out_ipl_parm:
-	sysfs_remove_group(&ipl_subsys.kobj, &ipl_fcp_attr_group);
-out:
-	return rc;
-}
-
-static int __init ipl_init(void)
-{
-	int rc;
-
-	rc = firmware_register(&ipl_subsys);
-	if (rc)
-		return rc;
-	switch (ipl_info.type) {
-	case IPL_TYPE_CCW:
-		rc = sysfs_create_group(&ipl_subsys.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_subsys.kobj,
-					&ipl_nss_attr_group);
-		break;
-	default:
-		rc = sysfs_create_group(&ipl_subsys.kobj,
-					&ipl_unknown_attr_group);
-		break;
-	}
-	if (rc)
-		firmware_unregister(&ipl_subsys);
-	return rc;
-}
-
-static void __init reipl_probe(void)
-{
-	void *buffer;
-
-	buffer = (void *) get_zeroed_page(GFP_KERNEL);
-	if (!buffer)
-		return;
-	if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
-		diag308_set_works = 1;
-	free_page((unsigned long)buffer);
+	if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
+		diag308_set_works = 1;
+	free_page((unsigned long)buffer);
 }
 
 static int __init reipl_nss_init(void)
@@ -954,7 +783,7 @@ static int __init reipl_fcp_init(void)
 	return 0;
 }
 
-static int __init reipl_init(void)
+static int reipl_init(void)
 {
 	int rc;
 
@@ -981,6 +810,136 @@ static int __init reipl_init(void)
 	return 0;
 }
 
+static struct shutdown_action reipl_action = {SHUTDOWN_ACTION_REIPL_STR,
+					      reipl_run, reipl_init};
+
+/*
+ * dump shutdown action: Dump Linux on shutdown.
+ */
+
+/* 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,
+	&sys_dump_fcp_br_lba_attr.attr,
+	NULL,
+};
+
+static struct attribute_group dump_fcp_attr_group = {
+	.name  = IPL_FCP_STR,
+	.attrs = dump_fcp_attrs,
+};
+
+/* CCW dump device attributes */
+
+DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
+		   dump_block_ccw->ipl_info.ccw.devno);
+
+static struct attribute *dump_ccw_attrs[] = {
+	&sys_dump_ccw_device_attr.attr,
+	NULL,
+};
+
+static struct attribute_group dump_ccw_attr_group = {
+	.name  = IPL_CCW_STR,
+	.attrs = dump_ccw_attrs,
+};
+
+/* dump type */
+
+static int dump_set_type(enum dump_type type)
+{
+	if (!(dump_capabilities & type))
+		return -EINVAL;
+	switch (type) {
+	case DUMP_TYPE_CCW:
+		if (MACHINE_IS_VM)
+			dump_method = DUMP_METHOD_CCW_VM;
+		else
+			dump_method = DUMP_METHOD_CCW_CIO;
+		break;
+	case DUMP_TYPE_FCP:
+		dump_method = DUMP_METHOD_FCP_DIAG;
+		break;
+	default:
+		dump_method = DUMP_METHOD_NONE;
+	}
+	dump_type = type;
+	return 0;
+}
+
+static ssize_t dump_type_show(struct kset *kset, char *page)
+{
+	return sprintf(page, "%s\n", dump_type_str(dump_type));
+}
+
+static ssize_t dump_type_store(struct kset *kset, const char *buf,
+			       size_t len)
+{
+	int rc = -EINVAL;
+
+	if (strncmp(buf, DUMP_NONE_STR, strlen(DUMP_NONE_STR)) == 0)
+		rc = dump_set_type(DUMP_TYPE_NONE);
+	else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
+		rc = dump_set_type(DUMP_TYPE_CCW);
+	else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
+		rc = dump_set_type(DUMP_TYPE_FCP);
+	return (rc != 0) ? rc : len;
+}
+
+static struct subsys_attribute dump_type_attr =
+		__ATTR(dump_type, 0644, dump_type_show, dump_type_store);
+
+static decl_subsys(dump, NULL, NULL);
+
+static void dump_run(struct shutdown_trigger *trigger)
+{
+	struct ccw_dev_id devid;
+	static char buf[100];
+
+	switch (dump_method) {
+	case DUMP_METHOD_CCW_CIO:
+		smp_send_stop();
+		devid.devno = dump_block_ccw->ipl_info.ccw.devno;
+		devid.ssid  = 0;
+		reipl_ccw_dev(&devid);
+		break;
+	case DUMP_METHOD_CCW_VM:
+		smp_send_stop();
+		sprintf(buf, "STORE STATUS");
+		__cpcmd(buf, NULL, 0, NULL);
+		sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno);
+		__cpcmd(buf, NULL, 0, NULL);
+		break;
+	case DUMP_METHOD_CCW_DIAG:
+		diag308(DIAG308_SET, dump_block_ccw);
+		diag308(DIAG308_DUMP, NULL);
+		break;
+	case DUMP_METHOD_FCP_DIAG:
+		diag308(DIAG308_SET, dump_block_fcp);
+		diag308(DIAG308_DUMP, NULL);
+		break;
+	case DUMP_METHOD_NONE:
+	default:
+		return;
+	}
+	printk(KERN_EMERG "Dump failed!\n");
+}
+
 static int __init dump_ccw_init(void)
 {
 	int rc;
@@ -1026,24 +985,7 @@ static int __init dump_fcp_init(void)
 	return 0;
 }
 
-#define SHUTDOWN_ON_PANIC_PRIO 0
-
-static int shutdown_on_panic_notify(struct notifier_block *self,
-				    unsigned long event, void *data)
-{
-	if (on_panic_action == SHUTDOWN_DUMP)
-		do_dump();
-	else if (on_panic_action == SHUTDOWN_REIPL)
-		do_reipl();
-	return NOTIFY_OK;
-}
-
-static struct notifier_block shutdown_on_panic_nb = {
-	.notifier_call = shutdown_on_panic_notify,
-	.priority = SHUTDOWN_ON_PANIC_PRIO
-};
-
-static int __init dump_init(void)
+static int dump_init(void)
 {
 	int rc;
 
@@ -1065,46 +1007,362 @@ static int __init dump_init(void)
 	return 0;
 }
 
-static int __init shutdown_actions_init(void)
+static struct shutdown_action dump_action = {SHUTDOWN_ACTION_DUMP_STR,
+					     dump_run, dump_init};
+
+/*
+ * vmcmd shutdown action: Trigger vm command on shutdown.
+ */
+
+static char vmcmd_on_reboot[128];
+static char vmcmd_on_panic[128];
+static char vmcmd_on_halt[128];
+static char vmcmd_on_poff[128];
+
+DEFINE_IPL_ATTR_STR_RW(vmcmd, on_reboot, "%s\n", "%s\n", vmcmd_on_reboot);
+DEFINE_IPL_ATTR_STR_RW(vmcmd, on_panic, "%s\n", "%s\n", vmcmd_on_panic);
+DEFINE_IPL_ATTR_STR_RW(vmcmd, on_halt, "%s\n", "%s\n", vmcmd_on_halt);
+DEFINE_IPL_ATTR_STR_RW(vmcmd, on_poff, "%s\n", "%s\n", vmcmd_on_poff);
+
+static struct attribute *vmcmd_attrs[] = {
+	&sys_vmcmd_on_reboot_attr.attr,
+	&sys_vmcmd_on_panic_attr.attr,
+	&sys_vmcmd_on_halt_attr.attr,
+	&sys_vmcmd_on_poff_attr.attr,
+	NULL,
+};
+
+static struct attribute_group vmcmd_attr_group = {
+	.attrs = vmcmd_attrs,
+};
+
+static decl_subsys(vmcmd, NULL, NULL);
+
+static void vmcmd_run(struct shutdown_trigger *trigger)
+{
+	char *cmd, *next_cmd;
+
+	if (strcmp(trigger->name, ON_REIPL_STR) == 0)
+		cmd = vmcmd_on_reboot;
+	else if (strcmp(trigger->name, ON_PANIC_STR) == 0)
+		cmd = vmcmd_on_panic;
+	else if (strcmp(trigger->name, ON_HALT_STR) == 0)
+		cmd = vmcmd_on_halt;
+	else if (strcmp(trigger->name, ON_POFF_STR) == 0)
+		cmd = vmcmd_on_poff;
+	else
+		return;
+
+	if (strlen(cmd) == 0)
+		return;
+	do {
+		next_cmd = strchr(cmd, '\n');
+		if (next_cmd) {
+			next_cmd[0] = 0;
+			next_cmd += 1;
+		}
+		__cpcmd(cmd, NULL, 0, NULL);
+		cmd = next_cmd;
+	} while (cmd != NULL);
+}
+
+static int vmcmd_init(void)
 {
 	int rc;
 
-	rc = firmware_register(&shutdown_actions_subsys);
+	if (!MACHINE_IS_VM)
+		return -ENOTSUPP;
+	rc = firmware_register(&vmcmd_subsys);
 	if (rc)
 		return rc;
-	rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);
-	if (rc) {
-		firmware_unregister(&shutdown_actions_subsys);
-		return rc;
+	return sysfs_create_group(&vmcmd_subsys.kobj, &vmcmd_attr_group);
+}
+
+static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
+					      vmcmd_run, vmcmd_init};
+
+/*
+ * stop shutdown action: Stop Linux on shutdown.
+ */
+
+static void stop_run(struct shutdown_trigger *trigger)
+{
+	signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+	for (;;);
+}
+
+static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
+					     stop_run, NULL};
+
+/* action list */
+
+static struct shutdown_action *shutdown_actions_list[] = {
+	&ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action};
+#define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *))
+
+/*
+ * Trigger section
+ */
+
+static decl_subsys(shutdown_actions, NULL, NULL);
+
+static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
+		       size_t len)
+{
+	int i;
+
+	for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
+		if (!shutdown_actions_list[i])
+			continue;
+		if (strncmp(buf, shutdown_actions_list[i]->name,
+			    strlen(shutdown_actions_list[i]->name)) == 0) {
+			trigger->action = shutdown_actions_list[i];
+			return len;
+		}
 	}
-	atomic_notifier_chain_register(&panic_notifier_list,
-				       &shutdown_on_panic_nb);
-	return 0;
+	return -EINVAL;
 }
 
-static int __init s390_ipl_init(void)
+/* on reipl */
+
+static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
+						    &reipl_action};
+
+static ssize_t on_reboot_show(struct kset *kset, char *page)
 {
-	int rc;
+	return sprintf(page, "%s\n", on_reboot_trigger.action->name);
+}
+
+static ssize_t on_reboot_store(struct kset *kset, const char *buf, size_t len)
+{
+	return set_trigger(buf, &on_reboot_trigger, len);
+}
+
+static struct subsys_attribute on_reboot_attr =
+		__ATTR(on_reboot, 0644, on_reboot_show, on_reboot_store);
+
+static void do_machine_restart(char *__unused)
+{
+	smp_send_stop();
+	on_reboot_trigger.action->fn(&on_reboot_trigger);
+	reipl_run(NULL);
+}
+void (*_machine_restart)(char *command) = do_machine_restart;
+
+/* on panic */
+
+static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
+
+static ssize_t on_panic_show(struct kset *kset, char *page)
+{
+	return sprintf(page, "%s\n", on_panic_trigger.action->name);
+}
+
+static ssize_t on_panic_store(struct kset *kset, const char *buf,
+			      size_t len)
+{
+	return set_trigger(buf, &on_panic_trigger, len);
+}
+
+static struct subsys_attribute on_panic_attr =
+		__ATTR(on_panic, 0644, on_panic_show, on_panic_store);
+
+static void do_panic(void)
+{
+	on_panic_trigger.action->fn(&on_panic_trigger);
+	stop_run(&on_panic_trigger);
+}
+
+/* on halt */
+
+static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
+
+static ssize_t on_halt_show(struct kset *kset, char *page)
+{
+	return sprintf(page, "%s\n", on_halt_trigger.action->name);
+}
+
+static ssize_t on_halt_store(struct kset *kset, const char *buf, size_t len)
+{
+	return set_trigger(buf, &on_halt_trigger, len);
+}
+
+static struct subsys_attribute on_halt_attr =
+		__ATTR(on_halt, 0644, on_halt_show, on_halt_store);
 
-	sclp_get_ipl_info(&sclp_ipl_info);
+
+static void do_machine_halt(void)
+{
+	smp_send_stop();
+	on_halt_trigger.action->fn(&on_halt_trigger);
+	stop_run(&on_halt_trigger);
+}
+void (*_machine_halt)(void) = do_machine_halt;
+
+/* on power off */
+
+static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
+
+static ssize_t on_poff_show(struct kset *kset, char *page)
+{
+	return sprintf(page, "%s\n", on_poff_trigger.action->name);
+}
+
+static ssize_t on_poff_store(struct kset *kset, const char *buf, size_t len)
+{
+	return set_trigger(buf, &on_poff_trigger, len);
+}
+
+static struct subsys_attribute on_poff_attr =
+		__ATTR(on_poff, 0644, on_poff_show, on_poff_store);
+
+
+static void do_machine_power_off(void)
+{
+	smp_send_stop();
+	on_poff_trigger.action->fn(&on_poff_trigger);
+	stop_run(&on_poff_trigger);
+}
+void (*_machine_power_off)(void) = do_machine_power_off;
+
+static void __init shutdown_triggers_init(void)
+{
+	if (firmware_register(&shutdown_actions_subsys))
+		goto fail;
+	if (subsys_create_file(&shutdown_actions_subsys, &on_reboot_attr))
+		goto fail;
+	if (subsys_create_file(&shutdown_actions_subsys, &on_panic_attr))
+		goto fail;
+	if (subsys_create_file(&shutdown_actions_subsys, &on_halt_attr))
+		goto fail;
+	if (subsys_create_file(&shutdown_actions_subsys, &on_poff_attr))
+		goto fail;
+
+	return;
+fail:
+	panic("shutdown_triggers_init failed\n");
+}
+
+static void __init shutdown_actions_init(void)
+{
+	int i;
+
+	for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
+		if (!shutdown_actions_list[i]->init)
+			continue;
+		if (shutdown_actions_list[i]->init())
+			shutdown_actions_list[i] = NULL;
+	}
+}
+
+static int __init s390_ipl_init(void)
+{
 	reipl_probe();
-	rc = ipl_init();
-	if (rc)
-		return rc;
-	rc = reipl_init();
-	if (rc)
-		return rc;
-	rc = dump_init();
-	if (rc)
-		return rc;
-	rc = shutdown_actions_init();
-	if (rc)
-		return rc;
+	shutdown_actions_init();
+	shutdown_triggers_init();
 	return 0;
 }
 
 __initcall(s390_ipl_init);
 
+static void __init strncpy_skip_quote(char *dst, char *src, int n)
+{
+	int sx, dx;
+
+	dx = 0;
+	for (sx = 0; src[sx] != 0; sx++) {
+		if (src[sx] == '"')
+			continue;
+		dst[dx++] = src[sx];
+		if (dx >= n)
+			break;
+	}
+}
+
+static int __init vmcmd_on_reboot_setup(char *str)
+{
+	if (!MACHINE_IS_VM)
+		return 1;
+	strncpy_skip_quote(vmcmd_on_reboot, str, 127);
+	vmcmd_on_reboot[127] = 0;
+	on_panic_trigger.action = &vmcmd_action;
+	return 1;
+}
+__setup("vmreboot=", vmcmd_on_reboot_setup);
+
+static int __init vmcmd_on_panic_setup(char *str)
+{
+	if (!MACHINE_IS_VM)
+		return 1;
+	strncpy_skip_quote(vmcmd_on_panic, str, 127);
+	vmcmd_on_panic[127] = 0;
+	on_panic_trigger.action = &vmcmd_action;
+	return 1;
+}
+__setup("vmpanic=", vmcmd_on_panic_setup);
+
+static int __init vmcmd_on_halt_setup(char *str)
+{
+	if (!MACHINE_IS_VM)
+		return 1;
+	strncpy_skip_quote(vmcmd_on_halt, str, 127);
+	vmcmd_on_halt[127] = 0;
+	on_halt_trigger.action = &vmcmd_action;
+	return 1;
+}
+__setup("vmhalt=", vmcmd_on_halt_setup);
+
+static int __init vmcmd_on_poff_setup(char *str)
+{
+	if (!MACHINE_IS_VM)
+		return 1;
+	strncpy_skip_quote(vmcmd_on_poff, str, 127);
+	vmcmd_on_poff[127] = 0;
+	on_poff_trigger.action = &vmcmd_action;
+	return 1;
+}
+__setup("vmpoff=", vmcmd_on_poff_setup);
+
+static int on_panic_notify(struct notifier_block *self,
+			   unsigned long event, void *data)
+{
+	do_panic();
+	return NOTIFY_OK;
+}
+
+static struct notifier_block on_panic_nb = {
+	.notifier_call = on_panic_notify,
+	.priority = 0,
+};
+
+void __init setup_ipl(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;
+	}
+	atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
+}
+
 void __init ipl_save_parameters(void)
 {
 	struct cio_iplinfo iplinfo;
@@ -1185,3 +1443,4 @@ void s390_reset_system(void)
 
 	do_reset_calls();
 }
+
arch/s390/kernel/setup.c +1 -102

121 lines not on this page · raw message

arch/s390/kernel/smp.c +0 -27
diff -urpN linux-2.6/arch/s390/kernel/smp.c linux-2.6-patched/arch/s390/kernel/smp.c
@@ -234,33 +234,6 @@ void smp_send_stop(void)
 }
 
 /*
- * Reboot, halt and power_off routines for SMP.
- */
-void machine_restart_smp(char *__unused)
-{
-	smp_send_stop();
-	do_reipl();
-}
-
-void machine_halt_smp(void)
-{
-	smp_send_stop();
-	if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
-		__cpcmd(vmhalt_cmd, NULL, 0, NULL);
-	signal_processor(smp_processor_id(), sigp_stop_and_store_status);
-	for (;;);
-}
-
-void machine_power_off_smp(void)
-{
-	smp_send_stop();
-	if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
-		__cpcmd(vmpoff_cmd, NULL, 0, NULL);
-	signal_processor(smp_processor_id(), sigp_stop_and_store_status);
-	for (;;);
-}
-
-/*
  * This is the main routine where commands issued by other
  * cpus are handled.
  */
include/asm-s390/ipl.h +3 -1
diff -urpN linux-2.6/include/asm-s390/ipl.h linux-2.6-patched/include/asm-s390/ipl.h
@@ -83,6 +83,8 @@ extern u32 dump_prefix_page;
 extern unsigned int zfcpdump_prefix_array[];
 
 extern void do_reipl(void);
+extern void do_halt(void);
+extern void do_poff(void);
 extern void ipl_save_parameters(void);
 
 enum {
@@ -118,7 +120,7 @@ struct ipl_info
 };
 
 extern struct ipl_info ipl_info;
-extern void setup_ipl_info(void);
+extern void setup_ipl(void);
 
 /*
  * DIAG 308 support
Signature · 4 lines
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.
#12 lore raw

Re: [patch 6/6] kernel: Shutdown Actions Interface

arch/s390/kernel/ipl.c static struct subsys_attribute reipl_typ · line 688

Quoted 6 lines · Martin Schwidefsky

From: Michael Holzheu <[email protected]>

arch/s390/kernel/ipl.c +0 -4
-static struct subsys_attribute dump_type_attr =
-               __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
-
-static decl_subsys(dump, NULL, NULL);

I guess this will conflict with:
http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=blob;f=driver/kobject-convert-s390-ipl.c-to-kobj_attr-interface.patch;hb=HEAD

which in in -mm.

Thanks,
Kay

#13 lore raw

Re: [patch 6/6] kernel: Shutdown Actions Interface

Quoted 11 lines · Kay Sievers

Review

Quoted 6 lines · Martin Schwidefsky

From: Michael Holzheu <[email protected]>

(quoted diff) +0 -4
-static struct subsys_attribute dump_type_attr =
-               __ATTR(dump_type, 0644, dump_type_show, dump_type_store);
-
-static decl_subsys(dump, NULL, NULL);

I guess this will conflict with:
http://git.kernel.org/?p=linux/kernel/git/gregkh/patches.git;a=blob;f=driver/kobject-convert-s390-ipl.c-to-kobj_attr-interface.patch;hb=HEAD

Quoted 2 lines

which in in -mm.

Right. Patch 6/6 together with the following patch will compile with Greg's "subsys" changes in the -mm tree. To merge the two patches we have to:

1. Remove Greg's changes in ipl.c
2. Apply patch 6/6
3. Apply this patch

---

 arch/s390/kernel/ipl.c |  192 ++++++++++++++++++++++++++++---------------------
 1 files changed, 111 insertions(+), 81 deletions(-)
arch/s390/kernel/ipl.c +111 -81
diff -Naurp linux-2.6.23-mm/arch/s390/kernel/ipl.c linux-2.6.23-mm-ipl-fix/arch/s390/kernel/ipl.c
@@ -169,23 +169,24 @@ EXPORT_SYMBOL_GPL(diag308);
 /* SYSFS */
 
 #define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value)		\
-static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset,	\
-		char *page)						\
+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,	\
-		char *page)						\
+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,	\
-		const char *buf, size_t len)				\
+static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj,	\
+		struct kobj_attribute *attr, const char *buf,		\
+		size_t len)						\
 {									\
 	unsigned long long value;					\
 	if (sscanf(buf, _fmt_in, &value) != 1)				\
@@ -193,25 +194,26 @@ static ssize_t sys_##_prefix##_##_name##
 	_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,	\
-		char *page)						\
+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,	\
-		const char *buf, size_t len)				\
+static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj,	\
+		struct kobj_attribute *attr, const char *buf, 		\
+		size_t len)						\
 {									\
 	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);
@@ -250,14 +252,16 @@ static __init enum ipl_type get_ipl_type
 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;
 
@@ -272,7 +276,7 @@ static ssize_t sys_ipl_device_show(struc
 	}
 }
 
-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,
@@ -347,7 +351,8 @@ static struct attribute_group ipl_fcp_at
 
 /* 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] = {};
 
@@ -359,7 +364,7 @@ static ssize_t ipl_ccw_loadparm_show(str
 	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[] = {
@@ -398,29 +403,29 @@ static struct attribute_group ipl_unknow
 	.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_subsys.kobj,
+	rc = sysfs_create_group(&ipl_kset->kobj,
 				&ipl_fcp_attr_group);
 	if (rc)
 		goto out;
-	rc = sysfs_create_bin_file(&ipl_subsys.kobj,
+	rc = sysfs_create_bin_file(&ipl_kset->kobj,
 				   &ipl_parameter_attr);
 	if (rc)
 		goto out_ipl_parm;
-	rc = sysfs_create_bin_file(&ipl_subsys.kobj,
+	rc = sysfs_create_bin_file(&ipl_kset->kobj,
 				   &ipl_scp_data_attr);
 	if (!rc)
 		goto out;
 
-	sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr);
+	sysfs_remove_bin_file(&ipl_kset->kobj, &ipl_parameter_attr);
 
 out_ipl_parm:
-	sysfs_remove_group(&ipl_subsys.kobj, &ipl_fcp_attr_group);
+	sysfs_remove_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
 out:
 	return rc;
 }
@@ -438,12 +443,14 @@ static int ipl_init(void)
 {
 	int rc;
 
-	rc = firmware_register(&ipl_subsys);
-	if (rc)
+	ipl_kset = kset_create_and_register("ipl", NULL, firmware_kobj, NULL);
+	if (!ipl_kset) {
+		rc = -ENOMEM;
 		goto out;
+	}
 	switch (ipl_info.type) {
 	case IPL_TYPE_CCW:
-		rc = sysfs_create_group(&ipl_subsys.kobj,
+		rc = sysfs_create_group(&ipl_kset->kobj,
 					&ipl_ccw_attr_group);
 		break;
 	case IPL_TYPE_FCP:
@@ -451,11 +458,11 @@ static int ipl_init(void)
 		rc = ipl_register_fcp_files();
 		break;
 	case IPL_TYPE_NSS:
-		rc = sysfs_create_group(&ipl_subsys.kobj,
+		rc = sysfs_create_group(&ipl_kset->kobj,
 					&ipl_nss_attr_group);
 		break;
 	default:
-		rc = sysfs_create_group(&ipl_subsys.kobj,
+		rc = sysfs_create_group(&ipl_kset->kobj,
 					&ipl_unknown_attr_group);
 		break;
 	}
@@ -514,7 +521,8 @@ static void reipl_get_ascii_loadparm(cha
 	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];
 
@@ -522,7 +530,8 @@ static ssize_t reipl_ccw_loadparm_show(s
 	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;
@@ -549,7 +558,7 @@ static ssize_t reipl_ccw_loadparm_store(
 	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);
 
@@ -617,12 +626,14 @@ static int reipl_set_type(enum ipl_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,
+static ssize_t reipl_type_store(struct kobject *kobj,
+				struct kobj_attribute *attr, const char *buf,
 				size_t len)
 {
 	int rc = -EINVAL;
@@ -636,10 +647,10 @@ static ssize_t reipl_type_store(struct k
 	return (rc != 0) ? rc : len;
 }
 
-static struct subsys_attribute reipl_type_attr =
+static struct kobj_attribute reipl_type_attr =
 		__ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store);
 
-static decl_subsys(reipl, NULL, NULL);
+static struct kset *reipl_kset;
 
 void reipl_run(struct shutdown_trigger *trigger)
 {
@@ -712,7 +723,7 @@ static int __init reipl_nss_init(void)
 
 	if (!MACHINE_IS_VM)
 		return 0;
-	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_nss_attr_group);
+	rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
 	if (rc)
 		return rc;
 	strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
@@ -727,7 +738,7 @@ static int __init reipl_ccw_init(void)
 	reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!reipl_block_ccw)
 		return -ENOMEM;
-	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_ccw_attr_group);
+	rc = sysfs_create_group(&reipl_kset->kobj, &reipl_ccw_attr_group);
 	if (rc) {
 		free_page((unsigned long)reipl_block_ccw);
 		return rc;
@@ -765,7 +776,7 @@ static int __init reipl_fcp_init(void)
 	reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!reipl_block_fcp)
 		return -ENOMEM;
-	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_fcp_attr_group);
+	rc = sysfs_create_group(&reipl_kset->kobj, &reipl_fcp_attr_group);
 	if (rc) {
 		free_page((unsigned long)reipl_block_fcp);
 		return rc;
@@ -787,12 +798,13 @@ static int reipl_init(void)
 {
 	int rc;
 
-	rc = firmware_register(&reipl_subsys);
-	if (rc)
-		return rc;
-	rc = subsys_create_file(&reipl_subsys, &reipl_type_attr);
+	reipl_kset = kset_create_and_register("reipl", NULL, firmware_kobj,
+					      NULL);
+	if (!reipl_kset)
+		return -ENOMEM;
+	rc = sysfs_create_file(&reipl_kset->kobj, &reipl_type_attr.attr);
 	if (rc) {
-		firmware_unregister(&reipl_subsys);
+		kset_unregister(reipl_kset);
 		return rc;
 	}
 	rc = reipl_ccw_init();
@@ -882,12 +894,14 @@ static int dump_set_type(enum dump_type 
 	return 0;
 }
 
-static ssize_t dump_type_show(struct kset *kset, char *page)
+static ssize_t dump_type_show(struct kobject *kobj,
+			      struct kobj_attribute *attr, char *page)
 {
 	return sprintf(page, "%s\n", dump_type_str(dump_type));
 }
 
-static ssize_t dump_type_store(struct kset *kset, const char *buf,
+static ssize_t dump_type_store(struct kobject *kobj,
+			       struct kobj_attribute *attr, const char *buf,
 			       size_t len)
 {
 	int rc = -EINVAL;
@@ -901,10 +915,10 @@ static ssize_t dump_type_store(struct ks
 	return (rc != 0) ? rc : len;
 }
 
-static struct subsys_attribute dump_type_attr =
+static struct kobj_attribute dump_type_attr =
 		__ATTR(dump_type, 0644, dump_type_show, dump_type_store);
 
-static decl_subsys(dump, NULL, NULL);
+static struct kset *dump_kset;
 
 static void dump_run(struct shutdown_trigger *trigger)
 {
@@ -947,7 +961,7 @@ static int __init dump_ccw_init(void)
 	dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!dump_block_ccw)
 		return -ENOMEM;
-	rc = sysfs_create_group(&dump_subsys.kobj, &dump_ccw_attr_group);
+	rc = sysfs_create_group(&dump_kset->kobj, &dump_ccw_attr_group);
 	if (rc) {
 		free_page((unsigned long)dump_block_ccw);
 		return rc;
@@ -971,7 +985,7 @@ static int __init dump_fcp_init(void)
 	dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!dump_block_fcp)
 		return -ENOMEM;
-	rc = sysfs_create_group(&dump_subsys.kobj, &dump_fcp_attr_group);
+	rc = sysfs_create_group(&dump_kset->kobj, &dump_fcp_attr_group);
 	if (rc) {
 		free_page((unsigned long)dump_block_fcp);
 		return rc;
@@ -989,12 +1003,13 @@ static int dump_init(void)
 {
 	int rc;
 
-	rc = firmware_register(&dump_subsys);
-	if (rc)
-		return rc;
-	rc = subsys_create_file(&dump_subsys, &dump_type_attr);
+	dump_kset = kset_create_and_register("dump", NULL, firmware_kobj,
+					     NULL);
+	if (!dump_kset)
+		return -ENOMEM;
+	rc = sysfs_create_file(&dump_kset->kobj, &dump_type_attr.attr);
 	if (rc) {
-		firmware_unregister(&dump_subsys);
+		kset_unregister(dump_kset);
 		return rc;
 	}
 	rc = dump_ccw_init();
@@ -1036,7 +1051,7 @@ static struct attribute_group vmcmd_attr
 	.attrs = vmcmd_attrs,
 };
 
-static decl_subsys(vmcmd, NULL, NULL);
+static struct kset *vmcmd_kset;
 
 static void vmcmd_run(struct shutdown_trigger *trigger)
 {
@@ -1068,14 +1083,13 @@ static void vmcmd_run(struct shutdown_tr
 
 static int vmcmd_init(void)
 {
-	int rc;
-
 	if (!MACHINE_IS_VM)
 		return -ENOTSUPP;
-	rc = firmware_register(&vmcmd_subsys);
-	if (rc)
-		return rc;
-	return sysfs_create_group(&vmcmd_subsys.kobj, &vmcmd_attr_group);
+	vmcmd_kset = kset_create_and_register("vmcmd", NULL, firmware_kobj,
+					      NULL);
+	if (!vmcmd_kset)
+		return -ENOMEM;
+	return sysfs_create_group(&vmcmd_kset->kobj, &vmcmd_attr_group);
 }
 
 static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
@@ -1104,7 +1118,7 @@ static struct shutdown_action *shutdown_
  * Trigger section
  */
 
-static decl_subsys(shutdown_actions, NULL, NULL);
+static struct kset *shutdown_actions_kset;
 
 static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
 		       size_t len)
@@ -1128,17 +1142,20 @@ static int set_trigger(const char *buf, 
 static struct shutdown_trigger on_reboot_trigger = {ON_REIPL_STR,
 						    &reipl_action};
 
-static ssize_t on_reboot_show(struct kset *kset, char *page)
+static ssize_t on_reboot_show(struct kobject *kobj, struct kobj_attribute *attr,
+			      char *page)
 {
 	return sprintf(page, "%s\n", on_reboot_trigger.action->name);
 }
 
-static ssize_t on_reboot_store(struct kset *kset, const char *buf, size_t len)
+static ssize_t on_reboot_store(struct kobject *kobj,
+			       struct kobj_attribute *attr,
+			       const char *buf, size_t len)
 {
 	return set_trigger(buf, &on_reboot_trigger, len);
 }
 
-static struct subsys_attribute on_reboot_attr =
+static struct kobj_attribute on_reboot_attr =
 		__ATTR(on_reboot, 0644, on_reboot_show, on_reboot_store);
 
 static void do_machine_restart(char *__unused)
@@ -1153,18 +1170,20 @@ void (*_machine_restart)(char *command) 
 
 static struct shutdown_trigger on_panic_trigger = {ON_PANIC_STR, &stop_action};
 
-static ssize_t on_panic_show(struct kset *kset, char *page)
+static ssize_t on_panic_show(struct kobject *kobj, struct kobj_attribute *attr,
+			     char *page)
 {
 	return sprintf(page, "%s\n", on_panic_trigger.action->name);
 }
 
-static ssize_t on_panic_store(struct kset *kset, const char *buf,
+static ssize_t on_panic_store(struct kobject *kobj,
+			      struct kobj_attribute *attr, const char *buf,
 			      size_t len)
 {
 	return set_trigger(buf, &on_panic_trigger, len);
 }
 
-static struct subsys_attribute on_panic_attr =
+static struct kobj_attribute on_panic_attr =
 		__ATTR(on_panic, 0644, on_panic_show, on_panic_store);
 
 static void do_panic(void)
@@ -1177,17 +1196,19 @@ static void do_panic(void)
 
 static struct shutdown_trigger on_halt_trigger = {ON_HALT_STR, &stop_action};
 
-static ssize_t on_halt_show(struct kset *kset, char *page)
+static ssize_t on_halt_show(struct kobject *kobj, struct kobj_attribute *attr,
+			    char *page)
 {
 	return sprintf(page, "%s\n", on_halt_trigger.action->name);
 }
 
-static ssize_t on_halt_store(struct kset *kset, const char *buf, size_t len)
+static ssize_t on_halt_store(struct kobject *kobj, struct kobj_attribute *attr,
+			     const char *buf, size_t len)
 {
 	return set_trigger(buf, &on_halt_trigger, len);
 }
 
-static struct subsys_attribute on_halt_attr =
+static struct kobj_attribute on_halt_attr =
 		__ATTR(on_halt, 0644, on_halt_show, on_halt_store);
 
 
@@ -1203,17 +1224,19 @@ void (*_machine_halt)(void) = do_machine
 
 static struct shutdown_trigger on_poff_trigger = {ON_POFF_STR, &stop_action};
 
-static ssize_t on_poff_show(struct kset *kset, char *page)
+static ssize_t on_poff_show(struct kobject *kobj, struct kobj_attribute *attr,
+			    char *page)
 {
 	return sprintf(page, "%s\n", on_poff_trigger.action->name);
 }
 
-static ssize_t on_poff_store(struct kset *kset, const char *buf, size_t len)
+static ssize_t on_poff_store(struct kobject *kobj, struct kobj_attribute *attr,
+			     const char *buf, size_t len)
 {
 	return set_trigger(buf, &on_poff_trigger, len);
 }
 
-static struct subsys_attribute on_poff_attr =
+static struct kobj_attribute on_poff_attr =
 		__ATTR(on_poff, 0644, on_poff_show, on_poff_store);
 
 
@@ -1227,15 +1250,22 @@ void (*_machine_power_off)(void) = do_ma
 
 static void __init shutdown_triggers_init(void)
 {
-	if (firmware_register(&shutdown_actions_subsys))
+	shutdown_actions_kset = kset_create_and_register("shutdown_actions",
+							 NULL, firmware_kobj,
+							 NULL);
+	if (!shutdown_actions_kset)
 		goto fail;
-	if (subsys_create_file(&shutdown_actions_subsys, &on_reboot_attr))
+	if (sysfs_create_file(&shutdown_actions_kset->kobj,
+			      &on_reboot_attr.attr))
 		goto fail;
-	if (subsys_create_file(&shutdown_actions_subsys, &on_panic_attr))
+	if (sysfs_create_file(&shutdown_actions_kset->kobj,
+			      &on_panic_attr.attr))
 		goto fail;
-	if (subsys_create_file(&shutdown_actions_subsys, &on_halt_attr))
+	if (sysfs_create_file(&shutdown_actions_kset->kobj,
+			      &on_halt_attr.attr))
 		goto fail;
-	if (subsys_create_file(&shutdown_actions_subsys, &on_poff_attr))
+	if (sysfs_create_file(&shutdown_actions_kset->kobj,
+			      &on_poff_attr.attr))
 		goto fail;
 
 	return;