diff options
Diffstat (limited to 'arch/s390/kernel')
| -rw-r--r-- | arch/s390/kernel/compat_wrapper.S | 6 | ||||
| -rw-r--r-- | arch/s390/kernel/debug.c | 11 | ||||
| -rw-r--r-- | arch/s390/kernel/irq.c | 124 | ||||
| -rw-r--r-- | arch/s390/kernel/nmi.c | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/perf_cpum_cf.c | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/runtime_instr.c | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/setup.c | 3 | ||||
| -rw-r--r-- | arch/s390/kernel/smp.c | 12 | ||||
| -rw-r--r-- | arch/s390/kernel/syscalls.S | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/time.c | 6 | ||||
| -rw-r--r-- | arch/s390/kernel/topology.c | 2 | 
11 files changed, 106 insertions, 65 deletions
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 827e094a2f4..9b9a805656b 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1659,3 +1659,9 @@ ENTRY(sys_kcmp_wrapper)  	llgfr	%r5,%r5			# unsigned long  	llgfr	%r6,%r6			# unsigned long  	jg	sys_kcmp + +ENTRY(sys_finit_module_wrapper) +	lgfr	%r2,%r2			# int +	llgtr	%r3,%r3			# const char __user * +	lgfr	%r4,%r4			# int +	jg	sys_finit_module diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index ba500d8dc39..4e8215e0d4b 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -1127,13 +1127,14 @@ debug_register_view(debug_info_t * id, struct debug_view *view)  	if (i == DEBUG_MAX_VIEWS) {  		pr_err("Registering view %s/%s would exceed the maximum "  		       "number of views %i\n", id->name, view->name, i); -		debugfs_remove(pde);  		rc = -1;  	} else {  		id->views[i] = view;  		id->debugfs_entries[i] = pde;  	}  	spin_unlock_irqrestore(&id->lock, flags); +	if (rc) +		debugfs_remove(pde);  out:  	return rc;  } @@ -1146,9 +1147,9 @@ EXPORT_SYMBOL(debug_register_view);  int  debug_unregister_view(debug_info_t * id, struct debug_view *view)  { -	int rc = 0; -	int i; +	struct dentry *dentry = NULL;  	unsigned long flags; +	int i, rc = 0;  	if (!id)  		goto out; @@ -1160,10 +1161,12 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view)  	if (i == DEBUG_MAX_VIEWS)  		rc = -1;  	else { -		debugfs_remove(id->debugfs_entries[i]); +		dentry = id->debugfs_entries[i];  		id->views[i] = NULL; +		id->debugfs_entries[i] = NULL;  	}  	spin_unlock_irqrestore(&id->lock, flags); +	debugfs_remove(dentry);  out:  	return rc;  } diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index bf24293970c..9df824ea166 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -24,43 +24,65 @@  #include <asm/irq.h>  #include "entry.h" +DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); +EXPORT_PER_CPU_SYMBOL_GPL(irq_stat); +  struct irq_class {  	char *name;  	char *desc;  }; -static const struct irq_class intrclass_names[] = { +/* + * The list of "main" irq classes on s390. This is the list of interrrupts + * that appear both in /proc/stat ("intr" line) and /proc/interrupts. + * Historically only external and I/O interrupts have been part of /proc/stat. + * We can't add the split external and I/O sub classes since the first field + * in the "intr" line in /proc/stat is supposed to be the sum of all other + * fields. + * Since the external and I/O interrupt fields are already sums we would end + * up with having a sum which accounts each interrupt twice. + */ +static const struct irq_class irqclass_main_desc[NR_IRQS] = {  	[EXTERNAL_INTERRUPT] = {.name = "EXT"}, -	[IO_INTERRUPT]	     = {.name = "I/O"}, -	[EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, -	[EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, -	[EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, -	[EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, -	[EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, -	[EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, -	[EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, -	[EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, -	[EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, -	[EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, -	[EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, -	[EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, -	[EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, -	[IOINT_CIO]  = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, -	[IOINT_QAI]  = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, -	[IOINT_DAS]  = {.name = "DAS", .desc = "[I/O] DASD"}, -	[IOINT_C15]  = {.name = "C15", .desc = "[I/O] 3215"}, -	[IOINT_C70]  = {.name = "C70", .desc = "[I/O] 3270"}, -	[IOINT_TAP]  = {.name = "TAP", .desc = "[I/O] Tape"}, -	[IOINT_VMR]  = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, -	[IOINT_LCS]  = {.name = "LCS", .desc = "[I/O] LCS"}, -	[IOINT_CLW]  = {.name = "CLW", .desc = "[I/O] CLAW"}, -	[IOINT_CTC]  = {.name = "CTC", .desc = "[I/O] CTC"}, -	[IOINT_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"}, -	[IOINT_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, -	[IOINT_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, -	[IOINT_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, -	[IOINT_MSI] =  {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, +	[IO_INTERRUPT]	     = {.name = "I/O"} +}; + +/* + * The list of split external and I/O interrupts that appear only in + * /proc/interrupts. + * In addition this list contains non external / I/O events like NMIs. + */ +static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = { +	[IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, +	[IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, +	[IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, +	[IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, +	[IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, +	[IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, +	[IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, +	[IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, +	[IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, +	[IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, +	[IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, +	[IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, +	[IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, +	[IRQIO_CIO]  = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, +	[IRQIO_QAI]  = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, +	[IRQIO_DAS]  = {.name = "DAS", .desc = "[I/O] DASD"}, +	[IRQIO_C15]  = {.name = "C15", .desc = "[I/O] 3215"}, +	[IRQIO_C70]  = {.name = "C70", .desc = "[I/O] 3270"}, +	[IRQIO_TAP]  = {.name = "TAP", .desc = "[I/O] Tape"}, +	[IRQIO_VMR]  = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, +	[IRQIO_LCS]  = {.name = "LCS", .desc = "[I/O] LCS"}, +	[IRQIO_CLW]  = {.name = "CLW", .desc = "[I/O] CLAW"}, +	[IRQIO_CTC]  = {.name = "CTC", .desc = "[I/O] CTC"}, +	[IRQIO_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"}, +	[IRQIO_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, +	[IRQIO_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, +	[IRQIO_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, +	[IRQIO_MSI]  = {.name = "MSI", .desc = "[I/O] MSI Interrupt" },  	[NMI_NMI]    = {.name = "NMI", .desc = "[NMI] Machine Check"}, +	[CPU_RST]    = {.name = "RST", .desc = "[CPU] CPU Restart"},  };  /* @@ -68,30 +90,34 @@ static const struct irq_class intrclass_names[] = {   */  int show_interrupts(struct seq_file *p, void *v)  { -	int i = *(loff_t *) v, j; +	int irq = *(loff_t *) v; +	int cpu;  	get_online_cpus(); -	if (i == 0) { +	if (irq == 0) {  		seq_puts(p, "           "); -		for_each_online_cpu(j) -			seq_printf(p, "CPU%d       ",j); +		for_each_online_cpu(cpu) +			seq_printf(p, "CPU%d       ", cpu);  		seq_putc(p, '\n');  	} - -	if (i < NR_IRQS) { -		seq_printf(p, "%s: ", intrclass_names[i].name); -#ifndef CONFIG_SMP -		seq_printf(p, "%10u ", kstat_irqs(i)); -#else -		for_each_online_cpu(j) -			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); -#endif -		if (intrclass_names[i].desc) -			seq_printf(p, "  %s", intrclass_names[i].desc); -                seq_putc(p, '\n'); -        } +	if (irq < NR_IRQS) { +		seq_printf(p, "%s: ", irqclass_main_desc[irq].name); +		for_each_online_cpu(cpu) +			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]); +		seq_putc(p, '\n'); +		goto skip_arch_irqs; +	} +	for (irq = 0; irq < NR_ARCH_IRQS; irq++) { +		seq_printf(p, "%s: ", irqclass_sub_desc[irq].name); +		for_each_online_cpu(cpu) +			seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]); +		if (irqclass_sub_desc[irq].desc) +			seq_printf(p, "  %s", irqclass_sub_desc[irq].desc); +		seq_putc(p, '\n'); +	} +skip_arch_irqs:  	put_online_cpus(); -        return 0; +	return 0;  }  /* @@ -222,7 +248,7 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code,  		/* Serve timer interrupts first. */  		clock_comparator_work();  	} -	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; +	kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL);  	if (ext_code.code != 0x1004)  		__get_cpu_var(s390_idle).nohz_delay = 1; diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index a6daa5c5cdb..7918fbea36b 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -254,7 +254,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)  	int umode;  	nmi_enter(); -	kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++; +	inc_irq_stat(NMI_NMI);  	mci = (struct mci *) &S390_lowcore.mcck_interruption_code;  	mcck = &__get_cpu_var(cpu_mcck);  	umode = user_mode(regs); diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index c4e7269d4a0..86ec7447e1f 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -229,7 +229,7 @@ static void cpumf_measurement_alert(struct ext_code ext_code,  	if (!(alert & CPU_MF_INT_CF_MASK))  		return; -	kstat_cpu(smp_processor_id()).irqs[EXTINT_CMC]++; +	inc_irq_stat(IRQEXT_CMC);  	cpuhw = &__get_cpu_var(cpu_hw_events);  	/* Measurement alerts are shared and might happen when the PMU diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c index 61066f6f71a..077a99389b0 100644 --- a/arch/s390/kernel/runtime_instr.c +++ b/arch/s390/kernel/runtime_instr.c @@ -71,7 +71,7 @@ static void runtime_instr_int_handler(struct ext_code ext_code,  	if (!(param32 & CPU_MF_INT_RI_MASK))  		return; -	kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++; +	inc_irq_stat(IRQEXT_CMR);  	if (!current->thread.ri_cb)  		return; diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 2568590973a..a5360de85ec 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -16,7 +16,7 @@  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt  #include <linux/errno.h> -#include <linux/module.h> +#include <linux/export.h>  #include <linux/sched.h>  #include <linux/kernel.h>  #include <linux/memblock.h> @@ -289,6 +289,7 @@ void machine_power_off(void)   * Dummy power off function.   */  void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL_GPL(pm_power_off);  static int __init early_parse_mem(char *p)  { diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 0b45baa5543..7433a2f9e5c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -433,9 +433,9 @@ static void do_ext_call_interrupt(struct ext_code ext_code,  	cpu = smp_processor_id();  	if (ext_code.code == 0x1202) -		kstat_cpu(cpu).irqs[EXTINT_EXC]++; +		inc_irq_stat(IRQEXT_EXC);  	else -		kstat_cpu(cpu).irqs[EXTINT_EMS]++; +		inc_irq_stat(IRQEXT_EMS);  	/*  	 * handle bit signal external calls  	 */ @@ -623,9 +623,10 @@ static struct sclp_cpu_info *smp_get_cpu_info(void)  	return info;  } -static int smp_add_present_cpu(int cpu); +static int __cpuinit smp_add_present_cpu(int cpu); -static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add) +static int __cpuinit __smp_rescan_cpus(struct sclp_cpu_info *info, +				       int sysfs_add)  {  	struct pcpu *pcpu;  	cpumask_t avail; @@ -708,6 +709,7 @@ static void __cpuinit smp_start_secondary(void *cpuvoid)  	pfault_init();  	notify_cpu_starting(smp_processor_id());  	set_cpu_online(smp_processor_id(), true); +	inc_irq_stat(CPU_RST);  	local_irq_enable();  	/* cpu_idle will call schedule for us */  	cpu_idle(); @@ -985,7 +987,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,  	return notifier_from_errno(err);  } -static int smp_add_present_cpu(int cpu) +static int __cpuinit smp_add_present_cpu(int cpu)  {  	struct cpu *c = &pcpu_devices[cpu].cpu;  	struct device *s = &c->dev; diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 48174850f3b..6a6c61f94dd 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S @@ -352,3 +352,4 @@ SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wr  SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)  SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)  SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) +SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 7fcd690d42c..a5f4f5a1d24 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators);   */  unsigned long long notrace __kprobes sched_clock(void)  { -	return (get_clock_monotonic() * 125) >> 9; +	return tod_to_ns(get_clock_monotonic());  }  /* @@ -168,7 +168,7 @@ static void clock_comparator_interrupt(struct ext_code ext_code,  				       unsigned int param32,  				       unsigned long param64)  { -	kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++; +	inc_irq_stat(IRQEXT_CLK);  	if (S390_lowcore.clock_comparator == -1ULL)  		set_clock_comparator(S390_lowcore.clock_comparator);  } @@ -179,7 +179,7 @@ static void stp_timing_alert(struct stp_irq_parm *);  static void timing_alert_interrupt(struct ext_code ext_code,  				   unsigned int param32, unsigned long param64)  { -	kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++; +	inc_irq_stat(IRQEXT_TLA);  	if (param32 & 0x00c40000)  		etr_timing_alert((struct etr_irq_parm *) ¶m32);  	if (param32 & 0x00038000) diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index f1aba87cceb..4b2e3e31700 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -10,6 +10,7 @@  #include <linux/bootmem.h>  #include <linux/cpuset.h>  #include <linux/device.h> +#include <linux/export.h>  #include <linux/kernel.h>  #include <linux/sched.h>  #include <linux/init.h> @@ -42,6 +43,7 @@ static struct mask_info socket_info;  static struct mask_info book_info;  struct cpu_topology_s390 cpu_topology[NR_CPUS]; +EXPORT_SYMBOL_GPL(cpu_topology);  static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)  {  |