Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f44a225 authored by Martin Schwidefsky's avatar Martin Schwidefsky
Browse files

s390: convert interrupt handling to use generic hardirq



With the introduction of PCI it became apparent that s390 should
convert to generic hardirqs as too many drivers do not have the
correct dependency for GENERIC_HARDIRQS. On the architecture
level s390 does not have irq lines. It has external interrupts,
I/O interrupts and adapter interrupts. This patch hard-codes all
external interrupts as irq #1, all I/O interrupts as irq #2 and
all adapter interrupts as irq #3. The additional information from
the lowcore associated with the interrupt is stored in the
pt_regs of the interrupt frame, where the interrupt handler can
pick it up. For PCI/MSI interrupts the adapter interrupt handler
scans the relevant bit fields and calls generic_handle_irq with
the virtual irq number for the MSI interrupt.

Reviewed-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 5d0d8f43
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ config S390
	select HAVE_FUNCTION_GRAPH_TRACER
	select HAVE_FUNCTION_TRACER
	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
	select HAVE_GENERIC_HARDIRQS
	select HAVE_KERNEL_BZIP2
	select HAVE_KERNEL_GZIP
	select HAVE_KERNEL_LZ4
@@ -445,6 +446,16 @@ config PCI_NR_FUNCTIONS
	  This allows you to specify the maximum number of PCI functions which
	  this kernel will support.

config PCI_NR_MSI
	int "Maximum number of MSI interrupts (64-32768)"
	range 64 32768
	default "256"
	help
	  This defines the number of virtual interrupts the kernel will
	  provide for MSI interrupts. If you configure your system to have
	  too few drivers will fail to allocate MSI interrupts for all
	  PCI devices.

source "drivers/pci/Kconfig"
source "drivers/pci/pcie/Kconfig"
source "drivers/pci/hotplug/Kconfig"
+5 −0
Original line number Diff line number Diff line
@@ -20,4 +20,9 @@

#define HARDIRQ_BITS	8

static inline void ack_bad_irq(unsigned int irq)
{
	printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
}

#endif /* __ASM_HARDIRQ_H */
+3 −14
Original line number Diff line number Diff line
@@ -4,19 +4,8 @@
#include <linux/msi.h>
#include <linux/pci.h>

static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
{
	return __irq_get_msi_desc(irq);
}

/* Must be called with msi map lock held */
static inline int irq_set_msi_desc(unsigned int irq, struct msi_desc *msi)
{
	if (!msi)
		return -EINVAL;

	msi->irq = irq;
	return 0;
}
void __init init_airq_interrupts(void);
void __init init_cio_interrupts(void);
void __init init_ext_interrupts(void);

#endif
+20 −15
Original line number Diff line number Diff line
#ifndef _ASM_IRQ_H
#define _ASM_IRQ_H

#define EXT_INTERRUPT	1
#define IO_INTERRUPT	2
#define THIN_INTERRUPT	3

#define NR_IRQS_BASE	4

#ifdef CONFIG_PCI_NR_MSI
# define NR_IRQS	(NR_IRQS_BASE + CONFIG_PCI_NR_MSI)
#else
# define NR_IRQS	NR_IRQS_BASE
#endif

/* This number is used when no interrupt has been assigned */
#define NO_IRQ		0

#ifndef __ASSEMBLY__

#include <linux/hardirq.h>
#include <linux/percpu.h>
#include <linux/cache.h>
#include <linux/types.h>

enum interruption_main_class {
	EXTERNAL_INTERRUPT,
	IO_INTERRUPT,
	NR_IRQS
};

enum interruption_class {
	IRQEXT_CLK,
	IRQEXT_EXC,
@@ -72,14 +83,8 @@ void service_subclass_irq_unregister(void);
void measurement_alert_subclass_register(void);
void measurement_alert_subclass_unregister(void);

#ifdef CONFIG_LOCKDEP
#  define disable_irq_nosync_lockdep(irq)	disable_irq_nosync(irq)
#  define disable_irq_nosync_lockdep_irqsave(irq, flags) \
						disable_irq_nosync(irq)
#  define disable_irq_lockdep(irq)		disable_irq(irq)
#  define enable_irq_lockdep(irq)		enable_irq(irq)
#  define enable_irq_lockdep_irqrestore(irq, flags) \
						enable_irq(irq)
#endif
#define irq_canonicalize(irq)  (irq)

#endif /* __ASSEMBLY__ */

#endif /* _ASM_IRQ_H */
+0 −16
Original line number Diff line number Diff line
@@ -53,12 +53,6 @@ struct zpci_fmb {
	atomic64_t unmapped_pages;
} __packed __aligned(16);

struct msi_map {
	unsigned long irq;
	struct msi_desc *msi;
	struct hlist_node msi_chain;
};

#define ZPCI_MSI_VEC_BITS	11
#define ZPCI_MSI_VEC_MAX	(1 << ZPCI_MSI_VEC_BITS)
#define ZPCI_MSI_VEC_MASK	(ZPCI_MSI_VEC_MAX - 1)
@@ -92,8 +86,6 @@ struct zpci_dev {

	/* IRQ stuff */
	u64		msi_addr;	/* MSI address */
	struct zdev_irq_map *irq_map;
	struct msi_map *msi_map;
	struct airq_iv *aibv;		/* adapter interrupt bit vector */
	unsigned int	aisb;		/* number of the summary bit */

@@ -153,14 +145,6 @@ int clp_add_pci_device(u32, u32, int);
int clp_enable_fh(struct zpci_dev *, u8);
int clp_disable_fh(struct zpci_dev *);

/* MSI */
struct msi_desc *__irq_get_msi_desc(unsigned int);
int zpci_msi_set_mask_bits(struct msi_desc *, u32, u32);
int zpci_setup_msi_irq(struct zpci_dev *, struct msi_desc *, unsigned int, int);
void zpci_teardown_msi_irq(struct zpci_dev *, struct msi_desc *);
int zpci_msihash_init(void);
void zpci_msihash_exit(void);

#ifdef CONFIG_PCI
/* Error handling and recovery */
void zpci_event_error(void *);
Loading