x86, irq: support ioapic device hotplug for x86
cover x86, irq: support ioapic device hotplug for x86
Hi, Thomas
Current x86 code does not support iapic hotplug yet.
This patcheset will try to pre-reserve irq block in allocated_irqs bitmap. for hot add ioapic controller. also record irq_base in gsi_config, so later could use it to convert gsi to irq for pci device using that ioapic controller.
need to update x86/irq to support realloc_irq after those bit are pre-reserved.
It is tested with pci remove/rescan method plus some test stubs.
Please review them.
could get them from:
git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-x86-irq
Thanks
Yinghai
94738bb: PCI: Disable mem in the ioapic removing path 6a53ea9: PCI: Make sure hotplug ioapic driver get loaded early 77f4e2b: x86, acpi, irq: Enable pci device type ioapic hotplug
b495bde: x86, irq: Make ioapics loop code skip blank slot 56cb7ba: x86, irq: Add mp_unregister_ioapic could handle hotremove ioapic
bd48b79: x86, irq: Make mp_register_ioapic could handle hotadd ioapic 3b23367: x86, irq: more strict check for register ioapic 996f15b: genirq: bail out early in free_desc()
f83ad47: x86, irq: add ioapic_gsi_to_irq
e864fc4: x86, irq: pre-reserve irq range that are used by ioapic 16b8b29: x86, irq: Add realloc_irq_and_cfg_at()
660c577: genirq: Split __irq_reserve_irqs from irq_alloc_descs 1060703: x86, irq: Convert irq_2_pin list to generic list
arch/x86/include/asm/hw_irq.h | 2 +- arch/x86/include/asm/io_apic.h | 2 + arch/x86/include/asm/mpspec.h | 2 + arch/x86/kernel/acpi/boot.c | 28 +--- arch/x86/kernel/apic/io_apic.c | 348 +++++++++++++++++++++++++++++++--------- drivers/pci/Kconfig | 2 +- drivers/pci/Makefile | 5 +- drivers/pci/ioapic.c | 19 ++- include/linux/irq.h | 6 + kernel/irq/irqdesc.c | 84 +++++++---- 10 files changed, 366 insertions(+), 132 deletions(-)
PATCH 1/13 x86, irq: Convert irq_2_pin list to generic list
So we can use generic list helper function.
Also make free_irq_cfg() free irq_2_pin list.
--- arch/x86/include/asm/hw_irq.h | 2 +- arch/x86/kernel/apic/io_apic.c | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-)
arch/x86/include/asm/hw_irq.h +1 -1
@@ -114,7 +114,7 @@ struct irq_2_iommu {* Most irqs are mapped 1:1 with pins. */ struct irq_cfg { -struct irq_pin_list *irq_2_pin; +struct list_head irq_2_pin;cpumask_var_t domain;cpumask_var_t old_domain;u8 vector;
arch/x86/kernel/apic/io_apic.c +12 -10
@@ -65,7 +65,7 @@#define __apicdebuginit (type) static type __init#define for_each_irq_pin (entry, head) \ - for (entry = head; entry; entry = entry->next) + list_for_each_entry(entry, &head, list)/* * Is the SiS APIC rmw bug present ?
@@ -175,8 +175,8 @@ void mp_save_irq(struct mpc_intsrc *m) }struct irq_pin_list { +struct list_head list;int apic, pin; -struct irq_pin_list *next; };static struct irq_pin_list *alloc_irq_pin_list (int node)
@@ -212,6 +212,7 @@ int __init arch_early_irq_init(void)irq_reserve_irqs (0 , legacy_pic->nr_legacy_irqs);for (i =0 ; i < count; i++) { +INIT_LIST_HEAD (&cfg[i].irq_2_pin);irq_set_chip_data (i, &cfg[i]);zalloc_cpumask_var_node (&cfg[i].domain,GFP_KERNEL , node);zalloc_cpumask_var_node (&cfg[i].old_domain,GFP_KERNEL , node);
@@ -244,6 +245,7 @@ static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node) goto out_cfg;if (!zalloc_cpumask_var_node (&cfg->old_domain,GFP_KERNEL , node)) goto out_domain; +INIT_LIST_HEAD (&cfg->irq_2_pin);return cfg; out_domain:free_cpumask_var (cfg->domain);
@@ -254,11 +256,15 @@ out_cfg:static void free_irq_cfg (unsigned int at,struct irq_cfg *cfg) { +struct irq_pin_list *entry, *tmp; +if (!cfg)return ;irq_set_chip_data (at,NULL );free_cpumask_var (cfg->domain);free_cpumask_var (cfg->old_domain); +list_for_each_entry_safe (entry, tmp, &cfg->irq_2_pin, list) +kfree (entry);kfree (cfg); }
@@ -438,15 +444,12 @@ static void ioapic_mask_entry(int apic, int pin)static int __add_pin_to_irq_node (struct irq_cfg *cfg,int node,int apic,int pin) { -struct irq_pin_list **last, *entry; +struct irq_pin_list *entry;/* don't allow duplicates */ - last = &cfg->irq_2_pin; -for_each_irq_pin (entry, cfg->irq_2_pin) { +for_each_irq_pin (entry, cfg->irq_2_pin)if (entry->apic == apic && entry->pin == pin)return 0 ; - last = &entry->next; - } entry =alloc_irq_pin_list (node);if (!entry) {
@@ -457,7 +460,7 @@ __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin) entry->apic = apic; entry->pin = pin; - *last = entry; +list_add_tail (&entry->list, &cfg->irq_2_pin);return 0 ; }
@@ -1722,8 +1725,7 @@ __apicdebuginit(void) print_IO_APICs(void) cfg =irq_get_chip_data (irq);if (!cfg)continue ; - entry = cfg->irq_2_pin; -if (!entry) +if (list_empty (&cfg->irq_2_pin))continue ;printk (KERN_DEBUG "IRQ%d " , irq);for_each_irq_pin (entry, cfg->irq_2_pin)
Signature · 1 line
1.7.7
PATCH 2/13 genirq: Split __irq_reserve_irqs from irq_alloc_descs
In reply to Yinghai Lualso make irq_reserve_irqs to reuse __irq_reserve_irqs.
--- include/linux/irq.h | 1 + kernel/irq/irqdesc.c | 55 ++++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 28 deletions(-)
include/linux/irq.h +1 -0
@@ -582,6 +582,7 @@ int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,void irq_free_descs (unsigned int irq,unsigned int cnt);int irq_reserve_irqs (unsigned int from,unsigned int cnt); +int __irq_reserve_irqs (int irq,unsigned int from,unsigned int cnt);static inline void irq_free_desc (unsigned int irq) {
kernel/irq/irqdesc.c +27 -28
85 lines not on this page · raw message
Signature · 1 line
1.7.7
PATCH 3/13 x86, irq: Add realloc_irq_and_cfg_at()
In reply to Yinghai LuWill use it to allocate irq that are pre-reserved.
--- arch/x86/kernel/apic/io_apic.c | 33 ++++++++++++++++++++++++++++++++- include/linux/irq.h | 5 +++++ kernel/irq/irqdesc.c | 26 ++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletions(-)
arch/x86/kernel/apic/io_apic.c +32 -1
@@ -300,6 +300,37 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)irq_free_desc (at); } +static struct irq_cfg *realloc_irq_and_cfg_at (unsigned int at,int node) +{ +struct irq_desc *desc =irq_to_desc (at); +struct irq_cfg *cfg; +int res; + +if (desc) { +if (irq_desc_get_irq_data (desc)->node == node) +return alloc_irq_and_cfg_at (at, node); + + cfg =irq_desc_get_chip_data (desc); +if (cfg) { +/* shared irq */ +if (!list_empty (&cfg->irq_2_pin)) +return cfg; +free_irq_cfg (at, cfg); + } + } + + res =irq_realloc_desc_at (at, node); +if (res >=0 ) { + cfg =alloc_irq_cfg (at, node); +if (cfg) { +irq_set_chip_data (at, cfg); +return cfg; + } + } + +return alloc_irq_and_cfg_at (at, node); +} +struct io_apic {unsigned int index;unsigned int unused[3 ];
@@ -3563,7 +3594,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)static int io_apic_setup_irq_pin (unsigned int irq,int node,struct io_apic_irq_attr *attr) { -struct irq_cfg *cfg =alloc_irq_and_cfg_at (irq, node); +struct irq_cfg *cfg =realloc_irq_and_cfg_at (irq, node);int ret;if (!cfg)
include/linux/irq.h +5 -0
@@ -584,6 +584,11 @@ void irq_free_descs(unsigned int irq, unsigned int cnt);int irq_reserve_irqs (unsigned int from,unsigned int cnt);int __irq_reserve_irqs (int irq,unsigned int from,unsigned int cnt); +int __irq_realloc_desc (int at,int node,struct module *owner); +/* use macros to avoid needing export.h for THIS_MODULE */ +#define irq_realloc_desc_at (at, node) \ + __irq_realloc_desc(at, node, THIS_MODULE) +static inline void irq_free_desc (unsigned int irq) {irq_free_descs (irq,1 );
kernel/irq/irqdesc.c +26 -0
@@ -99,6 +99,11 @@ EXPORT_SYMBOL_GPL(nr_irqs);static DEFINE_MUTEX (sparse_irq_lock); static DECLARE_BITMAP(allocated_irqs, IRQ_BITMAP_BITS); +static bool __irq_is_reserved (int irq) +{ +return !!test_bit (irq, allocated_irqs); +} +#ifdef CONFIG_SPARSE_IRQ static RADIX_TREE(irq_desc_tree, GFP_KERNEL);
@@ -400,6 +405,27 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,EXPORT_SYMBOL_GPL (__irq_alloc_descs);/** +* irq_realloc_desc - allocate irq descriptor for irq that is already reserved +* @irq: Allocate for specific irq number if irq >= 0 +* @node: Preferred node on which the irq descriptor should be allocated +* @owner: Owning module (can be NULL) +* +* Returns the irq number or error code +*/ +int __ref +__irq_realloc_desc (int irq,int node,struct module *owner) +{ +if (!__irq_is_reserved (irq)) +return -EINVAL ; + +if (irq_to_desc (irq)) +free_desc (irq); + +return alloc_descs (irq,1 , node, owner); +} +EXPORT_SYMBOL_GPL (__irq_realloc_desc); + +/** * irq_reserve_irqs - mark irqs allocated * @from: mark from irq number * @cnt: number of irqs to mark
Signature · 1 line
1.7.7
PATCH 4/13 x86, irq: pre-reserve irq range that are used by ioapic
In reply to Yinghai Lurealloc_irq_and_cfg_at already can handle pre-reserved case.
those for non-hot add ioapic, but make them to share same code path that will be used by hot add ioapic.
--- arch/x86/include/asm/io_apic.h | 1 + arch/x86/kernel/apic/io_apic.c | 133 ++++++++++++++++++++++++++-------------- 2 files changed, 88 insertions(+), 46 deletions(-)
arch/x86/include/asm/io_apic.h +1 -0
@@ -164,6 +164,7 @@ extern void setup_ioapic_ids_from_mpc_nocheck(void);struct mp_ioapic_gsi {u32 gsi_base;u32 gsi_end; +u32 irq_base; };extern struct mp_ioapic_gsi mp_gsi_routing[];extern u32 gsi_top;
arch/x86/kernel/apic/io_apic.c +87 -46
151 lines not on this page · raw message
Signature · 1 line
1.7.7
PATCH 5/13 x86, irq: add ioapic_gsi_to_irq
In reply to Yinghai Luit will handle hot add ioapic that irq_base is not equal to gsi_base.
Also remove irq_to_gsi that is causing confusing.
--- arch/x86/include/asm/io_apic.h | 1 + arch/x86/kernel/acpi/boot.c | 22 +++++----------------- arch/x86/kernel/apic/io_apic.c | 29 ++++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 18 deletions(-)
arch/x86/include/asm/io_apic.h +1 -0
@@ -168,6 +168,7 @@ struct mp_ioapic_gsi{ };extern struct mp_ioapic_gsi mp_gsi_routing[];extern u32 gsi_top; +int ioapic_gsi_to_irq (u32 gsi);int mp_find_ioapic (u32 gsi);int mp_find_ioapic_pin (int ioapic,u32 gsi);void __init mp_register_ioapic (int id,u32 address,u32 gsi_base);
arch/x86/kernel/acpi/boot.c +5 -17
@@ -112,6 +112,10 @@ static unsigned int gsi_to_irq(unsigned int gsi) } } +#ifdef CONFIG_X86_IO_APIC +if (acpi_irq_model ==ACPI_IRQ_MODEL_IOAPIC ) +return ioapic_gsi_to_irq (gsi); +#endif /* Provide an identity mapping of gsi == irq * except on truly weird platforms that have * non isa irqs in the first 16 gsis.
@@ -124,22 +128,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; -} -/* * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, * to map the target physical address. The problem is that set_fixmap()
@@ -527,7 +515,7 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) {if (isa_irq >=16 )return -1 ; - *gsi =irq_to_gsi (isa_irq); + *gsi = isa_irq_to_gsi[isa_irq];return 0 ; }
arch/x86/kernel/apic/io_apic.c +28 -1
@@ -1081,13 +1081,16 @@ 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 { + }else if (gsi_cfg->gsi_base == gsi_cfg->irq_base) {u32 gsi = gsi_cfg->gsi_base + pin;if (gsi >=NR_IRQS_LEGACY ) irq = gsi;else irq = gsi_top + gsi; + }else { +/* hotadd ioapic */ + irq = gsi_cfg->irq_base + pin; }#ifdef CONFIG_X86_32
@@ -1581,6 +1584,30 @@ static void __init setup_IO_APIC_irqs(void)__io_apic_setup_irqs (ioapic_idx); } +int ioapic_gsi_to_irq (u32 gsi) +{ +int ioapic_idx =0 , irq = gsi; +struct mp_ioapic_gsi *gsi_cfg; + + ioapic_idx =mp_find_ioapic (gsi); +if (ioapic_idx <0 ) +return -1 ; + + gsi_cfg =mp_ioapic_gsi_routing (ioapic_idx); +if (gsi_cfg->gsi_base == gsi_cfg->irq_base) { +if (gsi <NR_IRQS_LEGACY ) + irq = gsi_top + gsi; + }else { +int pin =mp_find_ioapic_pin (ioapic_idx, gsi); + +if (pin <0 ) +return -1 ; +/* hotadd ioapic */ + irq = gsi_cfg->irq_base + pin; + } + +return irq; +}/* * for the gsit that is not in first ioapic * but could not use acpi_register_gsi()
Signature · 1 line
1.7.7
PATCH 6/13 genirq: bail out early in free_desc()
In reply to Yinghai LuSo we can use irq_free_descs to clear allocated_irqs bits for preserved irqs.
--- kernel/irq/irqdesc.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
kernel/irq/irqdesc.c +3 -0
@@ -169,6 +169,9 @@ static void free_desc(unsigned int irq) {struct irq_desc *desc =irq_to_desc (irq); +if (!desc) +return ; +unregister_irq_proc (irq, desc);mutex_lock (&sparse_irq_lock);
Signature · 1 line
1.7.7
PATCH 7/13 x86, irq: more strict check for register ioapic
In reply to Yinghai Lu1. check overlaping gsi range
for hotplug ioapic case, BIOS may have some entries in MADT and also in pci bus with _GSB.
2. make bad_ioapics take idx instead of nr_ioapics. for hotadd ioapic could find spare slot in the middle later.
3. check if entries in right range.
--- arch/x86/kernel/apic/io_apic.c | 19 ++++++++++++++----- 1 files changed, 14 insertions(+), 5 deletions(-)
arch/x86/kernel/apic/io_apic.c +14 -5
@@ -4065,11 +4065,11 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)return gsi - gsi_cfg->gsi_base; } -static __init int bad_ioapic (unsigned long address) +static __init int bad_ioapic (int idx,unsigned long address) { -if (nr_ioapics >=MAX_IO_APICS ) { +if (idx >=MAX_IO_APICS ) {printk (KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded " -"(found %d), skipping\n" ,MAX_IO_APICS , nr_ioapics); +"(found %d), skipping\n" ,MAX_IO_APICS , idx);return 1 ; }if (!address) {
@@ -4082,14 +4082,17 @@ static __init int bad_ioapic(unsigned long address)void __init mp_register_ioapic (int id,u32 address,u32 gsi_base) { -int idx =0 ; +int idx;int entries;struct mp_ioapic_gsi *gsi_cfg; -if (bad_ioapic (address)) + idx =mp_find_ioapic (gsi_base); +if (idx >=0 )return ; idx = nr_ioapics; +if (bad_ioapic (idx, address)) +return ; ioapics[idx].mp_config.type =MP_IOAPIC ; ioapics[idx].mp_config.flags =MPC_APIC_USABLE ;
@@ -4104,6 +4107,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)* and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ entries =io_apic_get_redir_entries (idx); + +if (!entries || entries >MP_MAX_IOAPIC_PIN ) { +clear_fixmap (FIX_IO_APIC_BASE_0 + idx); +return ; + } + gsi_cfg =mp_ioapic_gsi_routing (idx); gsi_cfg->gsi_base = gsi_base; gsi_cfg->gsi_end = gsi_base + entries -1 ;
Signature · 1 line
1.7.7
PATCH 8/13 x86, irq: Make mp_register_ioapic could handle hotadd ioapic
In reply to Yinghai Luit will reserve irq block in allocated_irqs bit maps and irq_base will be used to get right irq for ioapic/pin or gsi.
--- arch/x86/include/asm/mpspec.h | 1 + arch/x86/kernel/apic/io_apic.c | 53 ++++++++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 10 deletions(-)
arch/x86/include/asm/mpspec.h +1 -0
@@ -96,6 +96,7 @@ static inline void early_reserve_e820_mpc_new(void) { }void __cpuinit generic_processor_info (int apicid,int version);#ifdef CONFIG_ACPI +int __mp_register_ioapic (int id,u32 address,u32 gsi_base,bool hot);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);
arch/x86/kernel/apic/io_apic.c +43 -10
86 lines not on this page · raw message
Signature · 1 line
1.7.7
PATCH 9/13 x86, irq: Add mp_unregister_ioapic could handle hotremove ioapic
In reply to Yinghai Luit will free ioapic related irq_desc and also clear allocated_irqs bits.
--- arch/x86/include/asm/mpspec.h | 1 + arch/x86/kernel/apic/io_apic.c | 42 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 0 deletions(-)
arch/x86/include/asm/mpspec.h +1 -0
@@ -97,6 +97,7 @@ static inline void early_reserve_e820_mpc_new(void) { }void __cpuinit generic_processor_info (int apicid,int version);#ifdef CONFIG_ACPI int __mp_register_ioapic (int id,u32 address,u32 gsi_base,bool hot); +int mp_unregister_ioapic (u32 gsi_base);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);
arch/x86/kernel/apic/io_apic.c +42 -0
66 lines not on this page · raw message
Signature · 1 line
1.7.7
PATCH 10/13 x86, irq: Make ioapics loop code skip blank slot
In reply to Yinghai LuWhen multiple ioapics get added and removed, we could have blank slot in ioapics array.
Add skip code in this case by check nr_registers.
--- arch/x86/kernel/apic/io_apic.c | 29 +++++++++++++++++++++++------ 1 files changed, 23 insertions(+), 6 deletions(-)
arch/x86/kernel/apic/io_apic.c +23 -6
@@ -819,7 +819,8 @@ int save_ioapic_entries(void)int err =0 ;for (apic =0 ; apic < nr_ioapics; apic++) { -if (!ioapics[apic].saved_registers) { +if (!ioapics[apic].saved_registers && + ioapics[apic].nr_registers) { err = -ENOMEM ;continue ; }
@@ -925,9 +926,12 @@ static int __init find_isa_irq_apic(int irq, int type)if (i < mp_irq_entries) {int ioapic_idx; -for (ioapic_idx =0 ; ioapic_idx < nr_ioapics; ioapic_idx++) +for (ioapic_idx =0 ; ioapic_idx < nr_ioapics; ioapic_idx++) { +if (!ioapics[ioapic_idx].nr_registers) +continue ;if (mpc_ioapic_id (ioapic_idx) == mp_irqs[i].dstapic)return ioapic_idx; + } }return -1 ;
@@ -1158,10 +1162,13 @@ 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; -for (ioapic_idx =0 ; ioapic_idx < nr_ioapics; ioapic_idx++) +for (ioapic_idx =0 ; ioapic_idx < nr_ioapics; ioapic_idx++) { +if (!ioapics[ioapic_idx].nr_registers) +continue ;if (mpc_ioapic_id (ioapic_idx) == mp_irqs[i].dstapic || mp_irqs[i].dstapic ==MP_APIC_ALL )break ; + } if (!test_bit(lbus, mp_bus_not_pci) && !mp_irqs[i].irqtype &&
@@ -2188,6 +2195,9 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)* Set the IOAPIC ID to the value stored in the MPC table. */ for (ioapic_idx =0 ; ioapic_idx < nr_ioapics; ioapic_idx++) { +if (!ioapics[ioapic_idx].nr_registers) +continue ; +/* Read the register 0 value */ raw_spin_lock_irqsave (&ioapic_lock, flags); reg_00.raw =io_apic_read (ioapic_idx,0 );
@@ -3153,8 +3163,12 @@ static void ioapic_resume(void) {int ioapic_idx; -for (ioapic_idx = nr_ioapics -1 ; ioapic_idx >=0 ; ioapic_idx--) +for (ioapic_idx = nr_ioapics -1 ; ioapic_idx >=0 ; ioapic_idx--) { +if (!ioapics[ioapic_idx].nr_registers) +continue ; +resume_ioapic_id (ioapic_idx); + }restore_ioapic_entries (); }
@@ -4065,8 +4079,11 @@ int mp_find_ioapic(u32 gsi)/* Find the IOAPIC that manages this GSI. */ for (i =0 ; i < nr_ioapics; i++) {struct mp_ioapic_gsi *gsi_cfg =mp_ioapic_gsi_routing (i); -if ((gsi >= gsi_cfg->gsi_base) - && (gsi <= gsi_cfg->gsi_end)) + +if (!ioapics[i].nr_registers) +continue ; + +if ((gsi >= gsi_cfg->gsi_base) && (gsi <= gsi_cfg->gsi_end))return i; }
Signature · 1 line
1.7.7
PATCH 11/13 x86, acpi, irq: Enable pci device type ioapic hotplug
In reply to Yinghai LuFill the blank stub of acpi_register_ioapic/acpi_unregister_ioapic.
--- arch/x86/kernel/acpi/boot.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
arch/x86/kernel/acpi/boot.c +2 -4
@@ -688,16 +688,14 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);int acpi_register_ioapic (acpi_handle handle,u64 phys_addr,u32 gsi_base) { -/* TBD */ -return -EINVAL ; +return __mp_register_ioapic (0 , phys_addr, gsi_base, true); }EXPORT_SYMBOL (acpi_register_ioapic);int acpi_unregister_ioapic (acpi_handle handle,u32 gsi_base) { -/* TBD */ -return -EINVAL ; +return mp_unregister_ioapic (gsi_base); }EXPORT_SYMBOL (acpi_unregister_ioapic);
Signature · 1 line
1.7.7
PATCH 12/13 PCI: Make sure hotplug ioapic driver get loaded early
In reply to Yinghai Luat least before port service.
Some system MADT will only have no hotplug entries even those devices are there before os is booting.
So we need to enable those ioapic early before real device driver need to setup ioapic irq.
--- drivers/pci/Kconfig | 2 +- drivers/pci/Makefile | 5 +++-- drivers/pci/ioapic.c | 6 ------ 3 files changed, 4 insertions(+), 9 deletions(-)
drivers/pci/Kconfig +1 -1
@@ -98,7 +98,7 @@ config PCI_PASID If unsure, say N. config PCI_IOAPIC - tristate "PCI IO-APIC hotplug support" if X86 + bool "PCI IO-APIC hotplug support" if X86 depends on PCI depends on ACPI depends on HOTPLUG
drivers/pci/Makefile +3 -2
@@ -10,11 +10,12 @@ obj-$(CONFIG_SYSFS) += slot.o obj-$(CONFIG_PCI_QUIRKS) += quirks.o +# pre-installed hotplug ioapic need to be enabled at first +obj-$(CONFIG_PCI_IOAPIC) += ioapic.o + # Build PCI Express stuff if needed obj-$(CONFIG_PCIEPORTBUS) += pcie/ -obj-$(CONFIG_PCI_IOAPIC) += ioapic.o - obj-$(CONFIG_HOTPLUG) += hotplug.o # Build the PCI Hotplug drivers if we were asked to
drivers/pci/ioapic.c +0 -6
@@ -118,10 +118,4 @@ static int __init ioapic_init(void)return pci_register_driver (&ioapic_driver); } -static void __exit ioapic_exit(void) -{ -pci_unregister_driver (&ioapic_driver); -} -module_init (ioapic_init); -module_exit (ioapic_exit);
Signature · 1 line
1.7.7
PATCH 13/13 PCI: Disable mem in the ioapic removing path
In reply to Yinghai LuFor physical hot plug should be ok, but for remove/rescan path will need us to disable that.
otherwise rescan mmio resource for pci ioapic device will not be sized and allocated, aka skiped.
For ioapic_probe:pci_enable_device will not enable the device correctly, and will bail out early.
So we can just disable mmio for all removing case. that will hurt real hotplug path.
--- drivers/pci/ioapic.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
drivers/pci/ioapic.c +13 -0
@@ -88,6 +88,17 @@ exit_free:return -ENODEV ; } +static void pci_disable_device_mem (struct pci_dev *dev) +{ +u16 pci_command; + +pci_read_config_word (dev,PCI_COMMAND , &pci_command); +if (pci_command &PCI_COMMAND_MEMORY ) { + pci_command &= ~PCI_COMMAND_MEMORY ; +pci_write_config_word (dev,PCI_COMMAND , pci_command); + } +} + static void __devexit ioapic_remove(struct pci_dev *dev) {struct ioapic *ioapic =pci_get_drvdata (dev);
@@ -95,6 +106,8 @@ static void __devexit ioapic_remove(struct pci_dev *dev)acpi_unregister_ioapic (ioapic->handle, ioapic->gsi_base);pci_release_region (dev,0 );pci_disable_device (dev); +/* need to disable it, otherwise remove/rescan will not work */ +pci_disable_device_mem (dev);kfree (ioapic); }
Signature · 1 line
1.7.7
Quoted 8 lines · On Thu, 23 Feb 2012 19:48:46 -0800 Yinghai Lu <[email protected]> wrote:
Hi, Thomas
Current x86 code does not support iapic hotplug yet.
This patcheset will try to pre-reserve irq block in
allocated_irqsbitmap. for hot add ioapic controller. also recordirq_baseingsi_config, so later could use it to convert gsi to irq for pci device using that ioapic controller.
Quoted 5 lines
need to update x86/irq to support
realloc_irqafter those bit are pre-reserved.It is tested with pci remove/rescan method plus some test stubs.
Please review them.
Suresh or Matthew may be interested in this patchset as well, and it should go via -tip.
Thanks,
Signature · 1 line
Jesse Barnes, Intel Open Source Technology Center