* [RFC Patch Part1 V1 03/30] x86, mpparse: simplify arch/x86/include/asm/mpspec.h
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 05/30] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
` (8 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, x86, Len Brown, Pavel Machek, David Rientjes,
Seiji Aguchi, Jiang Liu, HATAYAMA Daisuke, Paul Gortmaker,
Richard Weinberger, Andi Kleen
Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
Greg Kroah-Hartman, linux-kernel, linux-pci, linux-acpi,
sfi-devel, Ingo Molnar, H. Peter Anvin, linux-pm
Simplify arch/x86/include/asm/mpspec.h by
1) Change max_physical_apicid to static as it's only used in apic.c.
2) Kill declaration of mpc_default_type, it's never defined.
3) Delete default_acpi_madt_oem_check(), it has already been declared
in apic.h.
4) Change mp_override_legacy_irq(), mp_config_acpi_legacy_irqs() and
mp_register_gsi() as static because they are only used in acpi/boot.c.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/include/asm/apic.h | 4 ++--
arch/x86/include/asm/io_apic.h | 3 ---
arch/x86/include/asm/mpspec.h | 13 -------------
arch/x86/kernel/acpi/boot.c | 12 +++++++++---
arch/x86/kernel/apic/apic.c | 2 +-
5 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 19b0ebafcd3e..69ed79aa9085 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -502,8 +502,6 @@ static inline unsigned default_get_apic_id(unsigned long x)
#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469
#ifdef CONFIG_X86_64
-extern int default_acpi_madt_oem_check(char *, char *);
-
extern void apic_send_IPI_self(int vector);
DECLARE_PER_CPU(int, x2apic_extra_bits);
@@ -552,6 +550,8 @@ static inline int default_apic_id_valid(int apicid)
return (apicid < 255);
}
+extern int default_acpi_madt_oem_check(char *, char *);
+
extern void default_setup_apic_routing(void);
extern struct apic apic_noop;
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 459e50a424d1..677e599c275e 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -118,9 +118,6 @@ extern int mp_irq_entries;
/* MP IRQ source entries */
extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
-/* non-0 if default (table-less) MP configuration */
-extern int mpc_default_type;
-
/* Older SiS APIC requires we rewrite the index register */
extern int sis_apic_bug;
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index f5a617956735..7bef40a01a1d 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -40,8 +40,6 @@ extern int mp_bus_id_to_type[MAX_MP_BUSSES];
extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
extern unsigned int boot_cpu_physical_apicid;
-extern unsigned int max_physical_apicid;
-extern int mpc_default_type;
extern unsigned long mp_lapic_addr;
#ifdef CONFIG_X86_LOCAL_APIC
@@ -88,15 +86,6 @@ static inline void early_reserve_e820_mpc_new(void) { }
#endif
int generic_processor_info(int apicid, int version);
-#ifdef CONFIG_ACPI
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
-extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
- u32 gsi);
-extern void mp_config_acpi_legacy_irqs(void);
-struct device;
-extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
- int active_high_low);
-#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_LOCAL_APIC)
@@ -163,6 +152,4 @@ extern physid_mask_t phys_cpu_present_map;
extern int generic_mps_oem_check(struct mpc_table *, char *, char *);
-extern int default_acpi_madt_oem_check(char *, char *);
-
#endif /* _ASM_X86_MPSPEC_H */
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 86281ffb96d6..b41b47021f53 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -345,6 +345,10 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
#endif /*CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
+static void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi);
+static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity);
static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
@@ -903,7 +907,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
#ifdef CONFIG_X86_IO_APIC
#define MP_ISA_BUS 0
-void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
+static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
+ u32 gsi)
{
int ioapic;
int pin;
@@ -938,7 +943,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
isa_irq_to_gsi[bus_irq] = gsi;
}
-void __init mp_config_acpi_legacy_irqs(void)
+static void __init mp_config_acpi_legacy_irqs(void)
{
int i;
struct mpc_intsrc mp_irq;
@@ -1040,7 +1045,8 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
return 0;
}
-int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
+static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
+ int polarity)
{
int ioapic;
int ioapic_pin;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index ad28db7e6bde..ca1bd75e3de2 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);
/*
* The highest APIC ID seen during enumeration.
*/
-unsigned int max_physical_apicid;
+static unsigned int max_physical_apicid;
/*
* Bitmask of physically existing CPUs:
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 05/30] x86, acpi, irq: kill static function irq_to_gsi()
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
2014-05-16 8:05 ` [RFC Patch Part1 V1 03/30] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 06/30] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
` (7 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, Len Brown, Pavel Machek, x86
Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
linux-pci, linux-acpi, sfi-devel, linux-pm
Static function irq_to_gsi() is only called by acpi_isa_irq_to_gsi(),
so kill function irq_to_gsi() and simplify acpi_isa_irq_to_gsi().
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/kernel/acpi/boot.c | 26 ++++++--------------------
1 file changed, 6 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b41b47021f53..8390db1f7a93 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -120,22 +120,6 @@ static unsigned int gsi_to_irq(unsigned int gsi)
return irq;
}
-static u32 irq_to_gsi(int irq)
-{
- unsigned int gsi;
-
- if (irq < NR_IRQS_LEGACY)
- gsi = isa_irq_to_gsi[irq];
- else if (irq < gsi_top)
- gsi = irq;
- else if (irq < (gsi_top + NR_IRQS_LEGACY))
- gsi = irq - gsi_top;
- else
- gsi = 0xffffffff;
-
- return gsi;
-}
-
/*
* This is just a simple wrapper around early_ioremap(),
* with sanity checks for phys == 0 and size == 0.
@@ -527,10 +511,12 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq >= 16)
- return -1;
- *gsi = irq_to_gsi(isa_irq);
- return 0;
+ if (isa_irq < NR_IRQS_LEGACY) {
+ *gsi = isa_irq_to_gsi[isa_irq];
+ return 0;
+ }
+
+ return -1;
}
static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 06/30] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
2014-05-16 8:05 ` [RFC Patch Part1 V1 03/30] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 05/30] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 07/30] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
` (6 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, Len Brown, Pavel Machek, x86, Jiri Kosina
Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
linux-pci, linux-acpi, sfi-devel, linux-pm
1) Remove out-of-date comment
2) Kill unused function acpi_set_irq_model_pic()
3) Use NR_IRQS_LEGACY instead of hard-coded 16
4) Trivial syntax improvements
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/kernel/acpi/boot.c | 50 ++++++++++++++-----------------------------
1 file changed, 16 insertions(+), 34 deletions(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 8390db1f7a93..6d65850f49e9 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -370,11 +370,6 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
- /*
- * mp_config_acpi_legacy_irqs() already setup IRQs < 16
- * If GSI is < 16, this will update its flags,
- * else it will create a new mp_irqs[] entry.
- */
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
/*
@@ -573,14 +568,7 @@ void acpi_unregister_gsi(u32 gsi)
}
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
-void __init acpi_set_irq_model_pic(void)
-{
- acpi_irq_model = ACPI_IRQ_MODEL_PIC;
- __acpi_register_gsi = acpi_register_gsi_pic;
- acpi_ioapic = 0;
-}
-
-void __init acpi_set_irq_model_ioapic(void)
+static void __init acpi_set_irq_model_ioapic(void)
{
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
__acpi_register_gsi = acpi_register_gsi_ioapic;
@@ -819,9 +807,8 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
- acpi_parse_lapic_addr_ovr, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
@@ -846,9 +833,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
- acpi_parse_lapic_addr_ovr, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+ acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
@@ -876,11 +862,10 @@ static int __init acpi_parse_madt_lapic_entries(void)
return count;
}
- x2count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
- acpi_parse_x2apic_nmi, 0);
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
+ x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
+ acpi_parse_x2apic_nmi, 0);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI,
+ acpi_parse_lapic_nmi, 0);
if (count < 0 || x2count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
@@ -947,7 +932,7 @@ static void __init mp_config_acpi_legacy_irqs(void)
* Use the default configuration for the IRQs 0-15. Unless
* overridden by (MADT) interrupt source override entries.
*/
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < NR_IRQS_LEGACY; i++) {
int ioapic, pin;
unsigned int dstapic;
int idx;
@@ -1103,9 +1088,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return -ENODEV;
}
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
- MAX_IO_APICS);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
+ MAX_IO_APICS);
if (!count) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV;
@@ -1114,9 +1098,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return count;
}
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
- nr_irqs);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
+ acpi_parse_int_src_ovr, nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing interrupt source overrides entry\n");
@@ -1135,9 +1118,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
/* Fill in identity legacy mappings where no override */
mp_config_acpi_legacy_irqs();
- count =
- acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
- nr_irqs);
+ count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE,
+ acpi_parse_nmi_src, nr_irqs);
if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 07/30] x86, ACPI, irq: enhance error handling in function acpi_register_gsi()
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
` (2 preceding siblings ...)
2014-05-16 8:05 ` [RFC Patch Part1 V1 06/30] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 08/30] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
` (5 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, Len Brown, Pavel Machek, x86
Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
linux-pci, linux-acpi, sfi-devel, linux-pm
Function mp_register_gsi() may return invalid GSI if error happens,
so enhance acpi_register_gsi() to handle possible error cases.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/kernel/acpi/boot.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 6d65850f49e9..8b8ff786af12 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -97,6 +97,8 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
+#define ACPI_INVALID_GSI INT_MIN
+
static unsigned int gsi_to_irq(unsigned int gsi)
{
unsigned int irq = gsi + NR_IRQS_LEGACY;
@@ -553,13 +555,13 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int irq;
unsigned int plat_gsi = gsi;
plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
- irq = gsi_to_irq(plat_gsi);
+ if (plat_gsi != ACPI_INVALID_GSI)
+ return gsi_to_irq(plat_gsi);
- return irq;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_register_gsi);
@@ -1054,7 +1056,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
if (ret < 0)
- gsi = INT_MIN;
+ gsi = ACPI_INVALID_GSI;
return gsi;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 08/30] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
` (3 preceding siblings ...)
2014-05-16 8:05 ` [RFC Patch Part1 V1 07/30] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 18/30] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
` (4 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, Len Brown, Pavel Machek, x86
Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
linux-pci, linux-acpi, sfi-devel, linux-pm
A default identity mapping between GSI and IRQ is built for legacy IRQs.
So when overriding the default identity mapping for legacy IRQs,
we should also invalidate isa_irq_to_gsi[gsi] when setting
isa_irq_to_gsi[irq] = gsi. Otherwise there may be two entries with the
same GSI in the isa_irq_to_gsi array, and acpi_isa_irq_to_gsi() may give
wrong result.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/kernel/acpi/boot.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 8b8ff786af12..dccf9e88db30 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -508,7 +508,8 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
{
- if (isa_irq < NR_IRQS_LEGACY) {
+ if (isa_irq < NR_IRQS_LEGACY &&
+ isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
*gsi = isa_irq_to_gsi[isa_irq];
return 0;
}
@@ -913,6 +914,13 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
mp_save_irq(&mp_irq);
+ /*
+ * Reset default identity mapping if gsi is also an legacy IRQ,
+ * otherwise there will be more than one entry with the same GSI
+ * and acpi_isa_irq_to_gsi() may give wrong result.
+ */
+ if (gsi < NR_IRQS_LEGACY && isa_irq_to_gsi[gsi] == gsi)
+ isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
isa_irq_to_gsi[bus_irq] = gsi;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 18/30] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
` (4 preceding siblings ...)
2014-05-16 8:05 ` [RFC Patch Part1 V1 08/30] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 19/30] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
` (3 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, x86, Len Brown, Pavel Machek, Jiang Liu
Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
linux-acpi, sfi-devel, Ingo Molnar, linux-pm
Currently ACPI and ioapic both implement algorithms to map (ioapic, pin)
to IRQ number. So consolidate the common part into one place, which is
also preparing for irqdomain support.
It introduces mp_map_pin_to_irq(), which will be used to allocate IRQ
number IOAPIC pins when irqdomain is enabled.
Also rename gsi_to_irq() to map_gsi_to_irq(), later we will introduce
unmap_gsi_to_irq() when enabling IOAPIC hotplug.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/include/asm/io_apic.h | 2 ++
arch/x86/kernel/acpi/boot.c | 52 +++++++++++++++++++++-------------------
arch/x86/kernel/apic/io_apic.c | 30 +++++++++++++----------
3 files changed, 48 insertions(+), 36 deletions(-)
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index de3d8b04cf64..f4fd0be26cec 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -171,6 +171,7 @@ extern u32 gsi_top;
extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
+extern int mp_map_pin_to_irq(int ioapic, int pin);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);
@@ -212,6 +213,7 @@ extern void io_apic_eoi(unsigned int apic, unsigned int vector);
static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
+static inline int mp_map_pin_to_irq(int ioapic, int pin) { return -1; }
struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index dccf9e88db30..6eae9a7231c4 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -99,27 +99,22 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
#define ACPI_INVALID_GSI INT_MIN
-static unsigned int gsi_to_irq(unsigned int gsi)
+static int map_gsi_to_irq(unsigned int gsi)
{
- unsigned int irq = gsi + NR_IRQS_LEGACY;
- unsigned int i;
+ int i, ioapic, pin;
- for (i = 0; i < NR_IRQS_LEGACY; i++) {
- if (isa_irq_to_gsi[i] == gsi) {
+ for (i = 0; i < NR_IRQS_LEGACY; i++)
+ if (isa_irq_to_gsi[i] == gsi)
return i;
- }
- }
- /* Provide an identity mapping of gsi == irq
- * except on truly weird platforms that have
- * non isa irqs in the first 16 gsis.
- */
- if (gsi >= NR_IRQS_LEGACY)
- irq = gsi;
- else
- irq = gsi_top + gsi;
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic >= 0) {
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ return mp_map_pin_to_irq(ioapic, pin);
+ }
- return irq;
+ pr_err("Failed to map GSI%d to IRQ number.\n", gsi);
+ return -1;
}
/*
@@ -493,16 +488,20 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
outb(new >> 8, 0x4d1);
}
-int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- *irq = gsi_to_irq(gsi);
+ int irq = map_gsi_to_irq(gsi);
+ if (irq >= 0) {
#ifdef CONFIG_X86_IO_APIC
- if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
- setup_IO_APIC_irq_extra(gsi);
+ if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+ setup_IO_APIC_irq_extra(gsi);
#endif
+ *irqp = irq;
+ return 0;
+ }
- return 0;
+ return -1;
}
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
@@ -556,11 +555,11 @@ int (*acpi_suspend_lowlevel)(void);
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
{
- unsigned int plat_gsi = gsi;
+ unsigned int plat_gsi;
plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
if (plat_gsi != ACPI_INVALID_GSI)
- return gsi_to_irq(plat_gsi);
+ return map_gsi_to_irq(plat_gsi);
return -1;
}
@@ -1029,6 +1028,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
+ int irq;
int ioapic;
int ioapic_pin;
struct io_apic_irq_attr irq_attr;
@@ -1041,6 +1041,10 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;
+ irq = map_gsi_to_irq(gsi);
+ if (irq < 0)
+ return ACPI_INVALID_GSI;
+
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
@@ -1062,7 +1066,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
+ ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
if (ret < 0)
gsi = ACPI_INVALID_GSI;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index faed9b62977d..f55357bd0e07 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -980,11 +980,22 @@ static int irq_trigger(int idx)
return trigger;
}
+int mp_map_pin_to_irq(int apic, int pin)
+{
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
+ u32 gsi = gsi_cfg->gsi_base + pin;
+
+ /*
+ * Provide an identity mapping of gsi == irq except on truly weird
+ * platforms that have non isa irqs in the first 16 gsis.
+ */
+ return gsi >= NR_IRQS_LEGACY ? gsi : gsi_top + gsi;
+}
+
static int pin_2_irq(int idx, int apic, int pin)
{
int irq;
int bus = mp_irqs[idx].srcbus;
- struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
/*
* Debugging check, we are in big trouble if this message pops up!
@@ -992,17 +1003,6 @@ static int pin_2_irq(int idx, int apic, int pin)
if (mp_irqs[idx].dstirq != pin)
pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");
- if (test_bit(bus, mp_bus_not_pci)) {
- irq = mp_irqs[idx].srcbusirq;
- } else {
- u32 gsi = gsi_cfg->gsi_base + pin;
-
- if (gsi >= NR_IRQS_LEGACY)
- irq = gsi;
- else
- irq = gsi_top + gsi;
- }
-
#ifdef CONFIG_X86_32
/*
* PCI IRQ command line redirection. Yes, limits are hardcoded.
@@ -1017,11 +1017,17 @@ static int pin_2_irq(int idx, int apic, int pin)
apic_printk(APIC_VERBOSE, KERN_DEBUG
"using PIRQ%d -> IRQ %d\n",
pin-16, irq);
+ return irq;
}
}
}
#endif
+ if (test_bit(bus, mp_bus_not_pci))
+ irq = mp_irqs[idx].srcbusirq;
+ else
+ irq = mp_map_pin_to_irq(apic, pin);
+
return irq;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 19/30] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
` (5 preceding siblings ...)
2014-05-16 8:05 ` [RFC Patch Part1 V1 18/30] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 20/30] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
` (2 subsequent siblings)
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, x86, Len Brown, Pavel Machek, Jiang Liu
Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
linux-acpi, sfi-devel, Ingo Molnar, linux-pm
Currently x86 support identity mapping between GSI(IOAPIC pin) and IRQ
number, so continous IRQs at low end are statically allocated to IOAPICs
at boot time. This design causes trouble to support IOAPIC hotplug.
This patch implements basic mechanism to dynamically allocate IRQ on
demand for IOAPIC pins by using irqdomain framework.
This patch enhances ioapic.c to provide basic mechanisms to support
dynamically allocate IRQ number for IOAPIC by using irqdomain.
It first adds several fields into struct ioapic to support irqdomain.
Then it implements an algorithm to dynamically allocate IRQ number
on demand.
1) Build identity mapping for GSIs below arch_dynirq_lower_bound(0).
This is typically used to support legacy IRQs and simple platforms.
There's an exception for overridden ISA IRQs, whose GSI number
may be different from assigned IRQ number.
2) Dynamically allocate IRQs for GSIs above arch_dynirq_lower_bound(0).
This may be used to support big system and IOAPIC hotplug.
Function arch_dynirq_lower_bound(0) will be enhanced in coming patch
to enable dynamic IRQ allocation for IOAPIC. To ease our life,
arch_dynirq_lower_bound(0) must be greater than or equal to
NR_IRQS_LEGACY, otherwise it may break backward compatibilities.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/include/asm/io_apic.h | 9 ++-
arch/x86/kernel/acpi/boot.c | 10 ++--
arch/x86/kernel/apic/io_apic.c | 125 +++++++++++++++++++++++++++++++---------
3 files changed, 110 insertions(+), 34 deletions(-)
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index f4fd0be26cec..13209bdf318d 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -169,9 +169,11 @@ struct mp_ioapic_gsi{
};
extern u32 gsi_top;
+typedef struct irq_domain *(*ioapic_create_domain_fn)(int idx, void *arg);
+
extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
-extern int mp_map_pin_to_irq(int ioapic, int pin);
+extern int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);
@@ -213,7 +215,10 @@ extern void io_apic_eoi(unsigned int apic, unsigned int vector);
static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; }
-static inline int mp_map_pin_to_irq(int ioapic, int pin) { return -1; }
+static inline int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc)
+{
+ return -1;
+}
struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 6eae9a7231c4..cdf6908e9f75 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -99,7 +99,7 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
#define ACPI_INVALID_GSI INT_MIN
-static int map_gsi_to_irq(unsigned int gsi)
+static int map_gsi_to_irq(unsigned int gsi, int alloc)
{
int i, ioapic, pin;
@@ -110,7 +110,7 @@ static int map_gsi_to_irq(unsigned int gsi)
ioapic = mp_find_ioapic(gsi);
if (ioapic >= 0) {
pin = mp_find_ioapic_pin(ioapic, gsi);
- return mp_map_pin_to_irq(ioapic, pin);
+ return mp_map_pin_to_irq(-1, ioapic, pin, alloc);
}
pr_err("Failed to map GSI%d to IRQ number.\n", gsi);
@@ -490,7 +490,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
{
- int irq = map_gsi_to_irq(gsi);
+ int irq = map_gsi_to_irq(gsi, 1);
if (irq >= 0) {
#ifdef CONFIG_X86_IO_APIC
@@ -559,7 +559,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
if (plat_gsi != ACPI_INVALID_GSI)
- return map_gsi_to_irq(plat_gsi);
+ return map_gsi_to_irq(plat_gsi, 0);
return -1;
}
@@ -1041,7 +1041,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;
- irq = map_gsi_to_irq(gsi);
+ irq = map_gsi_to_irq(gsi, 1);
if (irq < 0)
return ACPI_INVALID_GSI;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index f55357bd0e07..fb87bdbb4307 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -31,6 +31,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
#include <linux/msi.h>
#include <linux/htirq.h>
#include <linux/freezer.h>
@@ -83,6 +84,7 @@ int sis_apic_bug = -1;
static DEFINE_RAW_SPINLOCK(ioapic_lock);
static DEFINE_RAW_SPINLOCK(vector_lock);
+static DEFINE_MUTEX(ioapic_mutex);
static struct ioapic {
/*
@@ -97,6 +99,9 @@ static struct ioapic {
struct mpc_ioapic mp_config;
/* IO APIC gsi routing info */
struct mp_ioapic_gsi gsi_config;
+ struct irq_domain *irqdomain;
+ ioapic_create_domain_fn irqdomain_cb;
+ void *irqdomain_arg;
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} ioapics[MAX_IO_APICS];
@@ -137,6 +142,11 @@ static inline int mp_init_pin_at_boot(int ioapic, int pin)
return ioapic == 0 || gsi < NR_IRQS_LEGACY;
}
+static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic)
+{
+ return ioapics[ioapic].irqdomain;
+}
+
int nr_ioapics;
/* The one past the highest gsi number used */
@@ -980,19 +990,68 @@ static int irq_trigger(int idx)
return trigger;
}
-int mp_map_pin_to_irq(int apic, int pin)
+/*
+ * Dynamically allocate IRQ for GSI above arch_dynirq_lower_bound(0),
+ * and build identity mapping for statically assigned IRQ, but need
+ * special handling for ISA IRQ overriden.
+ */
+static int alloc_irq_from_domain(struct irq_domain *domain,
+ int idx, int apic, int pin, u32 gsi)
{
- struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
- u32 gsi = gsi_cfg->gsi_base + pin;
+ int irq;
+
+ if (gsi >= arch_dynirq_lower_bound(0))
+ return irq_create_mapping(domain, pin);
+
+ irq = irq_find_mapping(domain, pin);
+ if (irq > 0)
+ return irq;
+
+ if (idx < 0)
+ idx = find_irq_entry(apic, pin, mp_INT);
+
+ /* Handle ISA IRQ overridden */
+ if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci))
+ irq = mp_irqs[idx].srcbusirq;
+ else
+ irq = gsi;
/*
- * Provide an identity mapping of gsi == irq except on truly weird
- * platforms that have non isa irqs in the first 16 gsis.
+ * The first NR_IRQS_LEGACY irq descs are allocated in early_irq_init()
+ * and need just a mapping. The remaining irqs need both.
*/
- return gsi >= NR_IRQS_LEGACY ? gsi : gsi_top + gsi;
+ if (irq < NR_IRQS_LEGACY)
+ return irq_domain_associate(domain, irq, pin);
+
+ return irq_create_strict_mappings(domain, irq, pin, 1) ? -1 : irq;
}
-static int pin_2_irq(int idx, int apic, int pin)
+int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc)
+{
+ int irq;
+ u32 gsi = mp_pin_2_gsi(ioapic, pin);
+ struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
+
+ if (!domain) {
+ /*
+ * Provide an identity mapping of gsi == irq except on truly
+ * weird platforms that have non isa irqs in the first 16 gsis.
+ */
+ return gsi >= NR_IRQS_LEGACY ? gsi : gsi_top + gsi;
+ }
+
+ mutex_lock(&ioapic_mutex);
+ if (alloc) {
+ irq = alloc_irq_from_domain(domain, idx, ioapic, pin, gsi);
+ } else {
+ irq = irq_find_mapping(domain, pin);
+ }
+ mutex_unlock(&ioapic_mutex);
+
+ return irq > 0 ? irq : -1;
+}
+
+static int pin_2_irq(int idx, int apic, int pin, int alloc)
{
int irq;
int bus = mp_irqs[idx].srcbus;
@@ -1026,7 +1085,7 @@ static int pin_2_irq(int idx, int apic, int pin)
if (test_bit(bus, mp_bus_not_pci))
irq = mp_irqs[idx].srcbusirq;
else
- irq = mp_map_pin_to_irq(apic, pin);
+ irq = mp_map_pin_to_irq(idx, apic, pin, alloc);
return irq;
}
@@ -1038,7 +1097,7 @@ static int pin_2_irq(int idx, int apic, int pin)
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
struct io_apic_irq_attr *irq_attr)
{
- int irq, i, best_guess = -1;
+ int irq, i, best_ioapic = -1, best_idx = -1;
apic_printk(APIC_DEBUG,
"querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -1052,6 +1111,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].srcbus;
int ioapic_idx, found = 0;
+ int gsi;
if (test_bit(lbus, mp_bus_not_pci) || (bus != lbus) ||
mp_irqs[i].irqtype != mp_INT ||
@@ -1068,30 +1128,36 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
continue;
/* Skip ISA IRQs */
- irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq);
- if (ioapic_idx == 0 && !IO_APIC_IRQ(irq))
+ gsi = mp_pin_2_gsi(ioapic_idx, mp_irqs[i].dstirq);
+ if (gsi < arch_dynirq_lower_bound(0) && !IO_APIC_IRQ(gsi))
continue;
if (pin == (mp_irqs[i].srcbusirq & 3)) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- return irq;
+ best_idx = i;
+ best_ioapic = ioapic_idx;
+ goto out;
}
+
/*
* Use the first all-but-pin matching entry as a
* best-guess fuzzy result for broken mptables.
*/
- if (best_guess < 0) {
- set_io_apic_irq_attr(irq_attr, ioapic_idx,
- mp_irqs[i].dstirq,
- irq_trigger(i),
- irq_polarity(i));
- best_guess = irq;
+ if (best_idx < 0) {
+ best_idx = i;
+ best_ioapic = ioapic_idx;
}
}
- return best_guess;
+ if (best_idx < 0)
+ return -1;
+
+out:
+ irq = pin_2_irq(best_idx, best_ioapic, mp_irqs[best_idx].dstirq, 1);
+ if (irq > 0)
+ set_io_apic_irq_attr(irq_attr, best_ioapic,
+ mp_irqs[best_idx].dstirq,
+ irq_trigger(best_idx),
+ irq_polarity(best_idx));
+ return irq;
}
EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
@@ -1282,7 +1348,7 @@ static inline int IO_APIC_irq_trigger(int irq)
for_each_ioapic_pin(apic, pin) {
idx = find_irq_entry(apic, pin, mp_INT);
- if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
+ if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin, 0)))
return irq_trigger(idx);
}
/*
@@ -1411,7 +1477,9 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
continue;
- irq = pin_2_irq(idx, ioapic_idx, pin);
+ irq = pin_2_irq(idx, ioapic_idx, pin, 1);
+ if (irq < 0)
+ continue;
/*
* Skip the timer IRQ if there's a quirk handler
@@ -1463,7 +1531,7 @@ void setup_IO_APIC_irq_extra(u32 gsi)
if (idx == -1)
return;
- irq = pin_2_irq(idx, ioapic_idx, pin);
+ irq = pin_2_irq(idx, ioapic_idx, pin, 1);
set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
irq_polarity(idx));
@@ -3637,7 +3705,10 @@ void __init setup_ioapic_dest(void)
if (irq_entry == -1)
continue;
- irq = pin_2_irq(irq_entry, ioapic, pin);
+ irq = pin_2_irq(irq_entry, ioapic, pin, 0);
+ if (irq < 0)
+ continue;
+
idata = irq_get_irq_data(irq);
/*
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 20/30] x86, irq: enhance mp_register_ioapic() to support irqdomain
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
` (6 preceding siblings ...)
2014-05-16 8:05 ` [RFC Patch Part1 V1 19/30] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 21/30] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 26/30] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, x86, Len Brown, Pavel Machek, Jiang Liu, Grant Likely,
Rob Herring, Michal Simek, Tony Lindgren
Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
linux-acpi, sfi-devel, Ingo Molnar, linux-pm
Add extra arguments to function mp_register_ioapic() to support
irqdomain. When registering IOAPIC, caller may provide a callback
and corresponding argument to create irqdomain for this IOAPIC.
The callback will be called later when initializing IOAPIC subsystem.
We also provide a common implementation mp_create_irqdomain()
to create irqdomain for IOAPICs, which may be used by platform drivers.
Global variable ioapic_dynirq_base is provided for platform drivers
to override return value of arch_dynirq_lower_bound(), thus enable
or disable dynamic IRQ allocation for IOAPIC.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/include/asm/io_apic.h | 9 +++++++-
arch/x86/kernel/acpi/boot.c | 3 ++-
arch/x86/kernel/apic/io_apic.c | 48 ++++++++++++++++++++++++++++++++++++++--
arch/x86/kernel/devicetree.c | 2 +-
arch/x86/kernel/mpparse.c | 2 +-
arch/x86/platform/sfi/sfi.c | 2 +-
6 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 13209bdf318d..f3afa86e5bb6 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -130,6 +130,9 @@ extern int noioapicquirk;
/* -1 if "noapic" boot option passed */
extern int noioapicreroute;
+/* Build identity mapping for GSIs below it */
+extern int ioapic_dynirq_base;
+
/*
* If we use the IO-APIC for IRQ routing, disable automatic
* assignment of PCI IRQ's.
@@ -169,12 +172,16 @@ struct mp_ioapic_gsi{
};
extern u32 gsi_top;
+struct irq_domain_ops;
typedef struct irq_domain *(*ioapic_create_domain_fn)(int idx, void *arg);
extern int mp_find_ioapic(u32 gsi);
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
extern int mp_map_pin_to_irq(int idx, int ioapic, int pin, int alloc);
-extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+ ioapic_create_domain_fn cb, void *arg);
+extern struct irq_domain *mp_irqdomain_create(int ioapic,
+ struct device_node *np, const struct irq_domain_ops *ops);
extern void __init pre_init_apic_IRQ0(void);
extern void mp_save_irq(struct mpc_intsrc *m);
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index cdf6908e9f75..f70f4f318316 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -344,7 +344,8 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
acpi_table_print_madt_entry(header);
mp_register_ioapic(ioapic->id,
- ioapic->address, ioapic->global_irq_base);
+ ioapic->address, ioapic->global_irq_base,
+ NULL, NULL);
return 0;
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index fb87bdbb4307..0bdf50988d75 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -166,6 +166,15 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
int skip_ioapic_setup;
+/*
+ * If not zero:
+ * . build identity mapping for GSIs below it.
+ * . must be bigger than or equal to max(NR_IRQS_LEGACY, pins_on_ioapic0).
+ * If zero:
+ * . build identity mapping for all GSIs
+ */
+int ioapic_dynirq_base;
+
/**
* disable_ioapic_support() - disables ioapic support at runtime
*/
@@ -2938,15 +2947,28 @@ out:
*/
#define PIC_IRQS (1UL << PIC_CASCADE_IR)
-void __init setup_IO_APIC(void)
+static void ioapic_create_irqdomains(void)
{
+ int i;
+ struct ioapic *ip;
+ for_each_ioapic(i) {
+ ip = &ioapics[i];
+ if (ip->irqdomain_cb)
+ ip->irqdomain = ip->irqdomain_cb(i, ip->irqdomain_arg);
+ }
+}
+
+void __init setup_IO_APIC(void)
+{
/*
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
*/
io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
+ ioapic_create_irqdomains();
+
/*
* Set up IO-APIC IRQ routing.
*/
@@ -3508,6 +3530,9 @@ unsigned int arch_dynirq_lower_bound(unsigned int from)
{
unsigned int min = gsi_top + NR_IRQS_LEGACY;
+ if (ioapic_dynirq_base)
+ return ioapic_dynirq_base;
+
return from < min ? min : from;
}
@@ -3886,7 +3911,8 @@ static __init int bad_ioapic_register(int idx)
return 0;
}
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
+void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
+ ioapic_create_domain_fn cb, void *arg)
{
int idx = 0;
int entries;
@@ -3900,6 +3926,9 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
ioapics[idx].mp_config.type = MP_IOAPIC;
ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
ioapics[idx].mp_config.apicaddr = address;
+ ioapics[idx].irqdomain_cb = cb;
+ ioapics[idx].irqdomain_arg = arg;
+ ioapics[idx].irqdomain = NULL;
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
@@ -3936,6 +3965,21 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
nr_ioapics++;
}
+struct irq_domain *mp_irqdomain_create(int ioapic, struct device_node *np,
+ const struct irq_domain_ops *ops)
+{
+ struct irq_domain *domain;
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+ int hwirqs = mp_ioapic_pin_count(ioapic);
+
+ domain = irq_domain_add_linear(np, hwirqs, ops, (void *)(long)ioapic);
+ BUG_ON(!domain);
+ if (gsi_cfg->gsi_base == 0)
+ irq_set_default_host(domain);
+
+ return domain;
+}
+
/* Enable IOAPIC early just for system timer */
void __init pre_init_apic_IRQ0(void)
{
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index d35078ea1446..1ab002c045c9 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -176,7 +176,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
dn->full_name);
return;
}
- mp_register_ioapic(++ioapic_id, r.start, gsi_top);
+ mp_register_ioapic(++ioapic_id, r.start, gsi_top, NULL, NULL);
}
static void __init dtb_ioapic_setup(void)
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 24da837389b7..6cb9a43ecde1 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -115,7 +115,7 @@ static void __init MP_bus_info(struct mpc_bus *m)
static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
if (m->flags & MPC_APIC_USABLE)
- mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
+ mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, NULL, NULL);
}
static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c
index bcd1a703e3e6..3bd7cf642680 100644
--- a/arch/x86/platform/sfi/sfi.c
+++ b/arch/x86/platform/sfi/sfi.c
@@ -82,7 +82,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table)
pentry = (struct sfi_apic_table_entry *)sb->pentry;
for (i = 0; i < num; i++) {
- mp_register_ioapic(i, pentry->phys_addr, gsi_top);
+ mp_register_ioapic(i, pentry->phys_addr, gsi_top, NULL, NULL);
pentry++;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 21/30] x86, ACPI, irq: provide basic irqdomain support
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
` (7 preceding siblings ...)
2014-05-16 8:05 ` [RFC Patch Part1 V1 20/30] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
2014-05-16 8:05 ` [RFC Patch Part1 V1 26/30] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, Len Brown, Pavel Machek, x86
Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
linux-pci, linux-acpi, sfi-devel, linux-pm
Enhance ACPI driver to provide basic irqdomain support for IOAPIC.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/kernel/acpi/boot.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index f70f4f318316..1ee639e74d50 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/slab.h>
#include <linux/bootmem.h>
#include <linux/ioport.h>
@@ -331,6 +332,23 @@ static void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity);
+static struct irq_domain_ops acpi_irqdomain_ops;
+
+static struct irq_domain *acpi_create_irqdomain(int idx, void *arg)
+{
+ struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(idx);
+
+ /*
+ * Statically allocate IRQ number for legacy IRQs and all pins on the
+ * first IOAPIC.
+ */
+ if (gsi_cfg->gsi_base < NR_IRQS_LEGACY &&
+ ioapic_dynirq_base < gsi_cfg->gsi_end)
+ ioapic_dynirq_base = gsi_cfg->gsi_end + 1;
+
+ return mp_irqdomain_create(idx, NULL, &acpi_irqdomain_ops);
+}
+
static int __init
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
{
@@ -345,7 +363,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
mp_register_ioapic(ioapic->id,
ioapic->address, ioapic->global_irq_base,
- NULL, NULL);
+ acpi_create_irqdomain, NULL);
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC Patch Part1 V1 26/30] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins
[not found] <1400227550-5935-1-git-send-email-jiang.liu@linux.intel.com>
` (8 preceding siblings ...)
2014-05-16 8:05 ` [RFC Patch Part1 V1 21/30] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
@ 2014-05-16 8:05 ` Jiang Liu
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-16 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Ingo Molnar,
H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas, Randy Dunlap,
Yinghai Lu, Len Brown, Pavel Machek, x86
Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
linux-pci, linux-acpi, sfi-devel, linux-pm
Refine ACPI to use common irqdomain map interface to program IOAPIC pins,
so we can unify the callsite to progam IOAPIC pins.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
arch/x86/kernel/acpi/boot.c | 48 ++++++++++++++++---------------------------
1 file changed, 18 insertions(+), 30 deletions(-)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 1ee639e74d50..50f06c9d1e2a 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -332,7 +332,9 @@ static void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity);
-static struct irq_domain_ops acpi_irqdomain_ops;
+static struct irq_domain_ops acpi_irqdomain_ops = {
+ .map = mp_irqdomain_map,
+};
static struct irq_domain *acpi_create_irqdomain(int idx, void *arg)
{
@@ -512,10 +514,6 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
int irq = map_gsi_to_irq(gsi, 1);
if (irq >= 0) {
-#ifdef CONFIG_X86_IO_APIC
- if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
- setup_IO_APIC_irq_extra(gsi);
-#endif
*irqp = irq;
return 0;
}
@@ -1047,11 +1045,7 @@ static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
{
- int irq;
- int ioapic;
- int ioapic_pin;
- struct io_apic_irq_attr irq_attr;
- int ret;
+ int irq, ioapic, pin, node;
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return gsi;
@@ -1060,35 +1054,29 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;
- irq = map_gsi_to_irq(gsi, 1);
- if (irq < 0)
- return ACPI_INVALID_GSI;
-
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
- return gsi;
+ pr_warn("No IOAPIC for GSI %u\n", gsi);
+ return ACPI_INVALID_GSI;
}
- ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-
- if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mpc_ioapic_id(ioapic),
- ioapic_pin);
- return gsi;
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
+ if (mp_set_pin_attr(ioapic, pin,
+ trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
+ polarity == ACPI_ACTIVE_HIGH ? 0 : 1,
+ node)) {
+ pr_warn("Failed to set pin attr for GSI%d\n", gsi);
+ return ACPI_INVALID_GSI;
}
+ irq = map_gsi_to_irq(gsi, 1);
+ if (irq < 0)
+ return ACPI_INVALID_GSI;
+
if (enable_update_mptable)
mp_config_acpi_gsi(dev, gsi, trigger, polarity);
- set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
- trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
- polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- ret = io_apic_set_pci_routing(dev, irq, &irq_attr);
- if (ret < 0)
- gsi = ACPI_INVALID_GSI;
-
return gsi;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread