* [Patch Part1 V2 04/29] x86, mpparse: simplify arch/x86/include/asm/mpspec.h
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
@ 2014-05-19 16:22 ` Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 06/29] 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-19 16:22 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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,
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 90f97b4b9347..9121abbc8c8f 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
* [Patch Part1 V2 06/29] x86, acpi, irq: kill static function irq_to_gsi()
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
2014-05-19 16:22 ` [Patch Part1 V2 04/29] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
@ 2014-05-19 16:22 ` Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 07/29] 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-19 16:22 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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, 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
* [Patch Part1 V2 07/29] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
2014-05-19 16:22 ` [Patch Part1 V2 04/29] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 06/29] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
@ 2014-05-19 16:22 ` Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 08/29] 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-19 16:22 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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, 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
* [Patch Part1 V2 08/29] x86, ACPI, irq: enhance error handling in function acpi_register_gsi()
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
` (2 preceding siblings ...)
2014-05-19 16:22 ` [Patch Part1 V2 07/29] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
@ 2014-05-19 16:22 ` Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 09/29] 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-19 16:22 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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, 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
* [Patch Part1 V2 09/29] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
` (3 preceding siblings ...)
2014-05-19 16:22 ` [Patch Part1 V2 08/29] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
@ 2014-05-19 16:22 ` Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 17/29] 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-19 16:22 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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, 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
* [Patch Part1 V2 17/29] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
` (4 preceding siblings ...)
2014-05-19 16:22 ` [Patch Part1 V2 09/29] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
@ 2014-05-19 16:23 ` Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 18/29] 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-19 16:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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, 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 3b6e29d29903..2d776f69f4e8 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -963,11 +963,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!
@@ -975,17 +986,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.
@@ -1000,11 +1000,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
* [Patch Part1 V2 18/29] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
` (5 preceding siblings ...)
2014-05-19 16:23 ` [Patch Part1 V2 17/29] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
@ 2014-05-19 16:23 ` Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 19/29] 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-19 16:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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, 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.
It first adds several fields into struct ioapic to support irqdomain.
Then it implements an algorithm to dynamically allocate IRQ number
on demand.
1) Legacy(ISA) IRQs is not managed by irqdomain because there may be
multiple pins sharing the same IRQ number and current irqdomain
only supports 1:1 mapping between pins and IRQ.
2) Build identity mapping for GSIs between NR_IRQS_LEGACY and
arch_dynirq_lower_bound(0). This is typically used to support legacy
IRQs and simple platforms.
3) Dynamically allocate IRQs for GSIs above arch_dynirq_lower_bound(0).
This may be used to support big system and IOAPIC hotplug.
4) Dynamically allocate IRQs for non-ISA IRQs below NR_IRQS_LEGACY. This
is to support some really weired platforms.
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 | 12 ++++-
arch/x86/kernel/acpi/boot.c | 10 ++--
arch/x86/kernel/apic/io_apic.c | 111 ++++++++++++++++++++++++++++------------
3 files changed, 94 insertions(+), 39 deletions(-)
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index f4fd0be26cec..2e593832ec6f 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -98,6 +98,8 @@ struct IR_IO_APIC_route_entry {
#define IOAPIC_AUTO -1
#define IOAPIC_EDGE 0
#define IOAPIC_LEVEL 1
+#define IOAPIC_MAP_ALLOC 0x1
+#define IOAPIC_MAP_CHECK 0x2
#ifdef CONFIG_X86_IO_APIC
@@ -169,9 +171,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 ioapic, int pin, int idx, unsigned int flags);
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);
@@ -213,7 +217,11 @@ 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 ioapic, int pin, int idx,
+ unsigned int flags)
+{
+ 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..9aa02b30a8bc 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, unsigned int flags)
{
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(ioapic, pin, -1, flags);
}
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, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
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, IOAPIC_MAP_ALLOC);
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 2d776f69f4e8..d0dd904007aa 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];
@@ -135,6 +140,11 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
return ioapic == 0 || (irq >= 0 && irq < 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 */
@@ -963,19 +973,47 @@ static int irq_trigger(int idx)
return trigger;
}
-int mp_map_pin_to_irq(int apic, int pin)
+int mp_map_pin_to_irq(int ioapic, int pin, int idx, unsigned int flags)
{
- struct mp_ioapic_gsi *gsi_cfg = mp_ioapic_gsi_routing(apic);
- u32 gsi = gsi_cfg->gsi_base + pin;
+ int irq = -1;
+ u32 gsi = mp_pin_2_gsi(ioapic, pin);
+ struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
- /*
- * 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;
+ 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);
+ irq = irq_find_mapping(domain, pin);
+ if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC)) {
+ if ((flags & IOAPIC_MAP_CHECK) && idx < 0) {
+ idx = find_irq_entry(ioapic, pin, mp_INT);
+ if (idx < 0)
+ goto out;
+ }
+
+ /*
+ * Dynamically allocate IRQ for GSI above
+ * arch_dynirq_lower_bound(0), and build identity mapping for
+ * statically assigned IRQ, and specially handle non-ISA IRQs
+ * below NR_IRQS_LEGACY.
+ */
+ if (gsi >= arch_dynirq_lower_bound(0) || gsi < NR_IRQS_LEGACY)
+ irq = irq_create_mapping(domain, pin);
+ else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
+ irq = gsi;
+ }
+out:
+ mutex_unlock(&ioapic_mutex);
+
+ return irq > 0 ? irq : -1;
}
-static int pin_2_irq(int idx, int apic, int pin)
+static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
{
int irq;
int bus = mp_irqs[idx].srcbus;
@@ -1009,7 +1047,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(ioapic, pin, idx, flags);
return irq;
}
@@ -1021,7 +1059,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",
@@ -1035,6 +1073,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 ||
@@ -1051,30 +1090,37 @@ 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,
+ IOAPIC_MAP_ALLOC);
+ 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);
@@ -1265,7 +1311,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);
}
/*
@@ -1391,8 +1437,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);
- if (!mp_init_irq_at_boot(ioapic_idx, irq))
+ irq = pin_2_irq(idx, ioapic_idx, pin,
+ ioapic_idx ? 0 : IOAPIC_MAP_ALLOC);
+ if (irq < 0 || !mp_init_irq_at_boot(ioapic_idx, irq))
continue;
/*
@@ -1442,8 +1489,8 @@ void setup_IO_APIC_irq_extra(u32 gsi)
if (idx == -1)
return;
- irq = pin_2_irq(idx, ioapic_idx, pin);
- if (mp_init_irq_at_boot(ioapic_idx, irq))
+ irq = pin_2_irq(idx, ioapic_idx, pin, IOAPIC_MAP_ALLOC);
+ if (irq < 0 || mp_init_irq_at_boot(ioapic_idx, irq))
return;
set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
@@ -3558,8 +3605,8 @@ void __init setup_ioapic_dest(void)
if (irq_entry == -1)
continue;
- irq = pin_2_irq(irq_entry, ioapic, pin);
- if (!mp_init_irq_at_boot(ioapic, irq))
+ irq = pin_2_irq(irq_entry, ioapic, pin, 0);
+ if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
continue;
idata = irq_get_irq_data(irq);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Patch Part1 V2 19/29] x86, irq: enhance mp_register_ioapic() to support irqdomain
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
` (6 preceding siblings ...)
2014-05-19 16:23 ` [Patch Part1 V2 18/29] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
@ 2014-05-19 16:23 ` Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 20/29] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 25/29] 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-19 16:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
Randy Dunlap, Yinghai Lu, x86, Len Brown, Pavel Machek, Jiang Liu,
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, Ingo Molnar, linux-pm, sfi-devel
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 2e593832ec6f..666170437d78 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -132,6 +132,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.
@@ -171,12 +174,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 ioapic, int pin, int idx, unsigned int flags);
-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 9aa02b30a8bc..66c8feea15a7 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 d0dd904007aa..1b9dd0a70dfa 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -164,6 +164,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
*/
@@ -2898,15 +2907,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.
*/
@@ -3411,6 +3433,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;
}
@@ -3786,7 +3811,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;
@@ -3800,6 +3826,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);
@@ -3836,6 +3865,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
* [Patch Part1 V2 20/29] x86, ACPI, irq: provide basic irqdomain support
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
` (7 preceding siblings ...)
2014-05-19 16:23 ` [Patch Part1 V2 19/29] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
@ 2014-05-19 16:23 ` Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 25/29] 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-19 16:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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, 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 66c8feea15a7..4e8566b071c1 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
* [Patch Part1 V2 25/29] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
` (8 preceding siblings ...)
2014-05-19 16:23 ` [Patch Part1 V2 20/29] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
@ 2014-05-19 16:23 ` Jiang Liu
9 siblings, 0 replies; 10+ messages in thread
From: Jiang Liu @ 2014-05-19 16:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
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, 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 4e8566b071c1..68baa34b8346 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, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
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, IOAPIC_MAP_ALLOC);
- 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, IOAPIC_MAP_ALLOC);
+ 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
end of thread, other threads:[~2014-05-19 16:23 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1400516594-11544-1-git-send-email-jiang.liu@linux.intel.com>
2014-05-19 16:22 ` [Patch Part1 V2 04/29] x86, mpparse: simplify arch/x86/include/asm/mpspec.h Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 06/29] x86, acpi, irq: kill static function irq_to_gsi() Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 07/29] x86, ACPI, trivial: minor improvements to arch/x86/kernel/acpi/boot.c Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 08/29] x86, ACPI, irq: enhance error handling in function acpi_register_gsi() Jiang Liu
2014-05-19 16:22 ` [Patch Part1 V2 09/29] x86, ACPI, irq: fix possible eror in GSI to IRQ mapping for legacy IRQ Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 17/29] x86, ACPI, irq: consolidate algorithm of mapping (ioapic, pin) to IRQ number Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 18/29] x86, irq: introduce mechanisms to support dynamically allocate IRQ for IOAPIC Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 19/29] x86, irq: enhance mp_register_ioapic() to support irqdomain Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 20/29] x86, ACPI, irq: provide basic irqdomain support Jiang Liu
2014-05-19 16:23 ` [Patch Part1 V2 25/29] x86, irq, ACPI: use common irqdomain map interface to program IOAPIC pins Jiang Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).