All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms
@ 2014-06-17  5:29 Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 01/16] x86, irq: Split out alloc_ioapic_save_registers() Jiang Liu
                   ` (15 more replies)
  0 siblings, 16 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

This patch set enhances IOAPIC core and ACPI drivers to support IOAPIC
hotplug on x86 platforms. It's based on another patch set "use irqdomain
to dynamically allocate IRQ for IOAPIC" at
https://lkml.org/lkml/2014/6/9/44

You may pull it from 
https://github.com/jiangliu/linux.git ioapic/hotplug_v2

We have pick up several patches from Yinghai's original IOAPIC hotplug
patch set and reimplemented IOAPIC driver as an ACPI driver instead of
a PCI driver.

It has been tested on a 4-socket Intel SDV with socket hot-addition
capability. Any suggestions are welcomed!

Jiang Liu (10):
  x86, irq, ACPI: protect acpi_pci_irq_enable() from reentrance
  PCI: kill wrong warning message in pcieport driver
  x86, irq: remove __init marker for functions will be used by IOAPIC
    hotplug
  x86, irq: refine mp_register_ioapic() to prepare for IOAPIC hotplug
  x86, irq, ACPI: introduce a rwsem to protect IOAPIC operations from
    hotplug
  x86, irq, ACPI: implement interface to support ACPI based IOAPIC
    hot-addition
  x86, irq, ACPI: implement interface to support ACPI based IOAPIC
    hot-removal
  x86, irq: introduce helper to check whether an IOAPIC has been
    registered
  pci, ioapic: kill ioapic PCI driver
  x86, irq, ACPI: implement ACPI driver to support IOAPIC hotplug

Yinghai Lu (6):
  x86, irq: Split out alloc_ioapic_save_registers()
  x86, ioapic: Find usable ioapic id for 64bit.
  ACPI, x86/PCI: Move resource_to_addr() to acpi generic
  ACPI: Make map_mat_entry handle x2apic entry
  ACPI: Move acpi_get_cpuid() to separated file
  ACPI, ioapic: Add acpi_get_ioapic_id()

 arch/x86/include/asm/io_apic.h |    6 +-
 arch/x86/kernel/acpi/boot.c    |   74 +++++++++-
 arch/x86/kernel/apic/io_apic.c |  235 +++++++++++++++++++++++++-------
 arch/x86/pci/acpi.c            |   50 +------
 drivers/acpi/Kconfig           |    6 +
 drivers/acpi/Makefile          |    2 +
 drivers/acpi/apic_id.c         |  295 ++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/internal.h        |    7 +
 drivers/acpi/ioapic.c          |  231 +++++++++++++++++++++++++++++++
 drivers/acpi/pci_irq.c         |    7 +-
 drivers/acpi/pci_root.c        |    3 +
 drivers/acpi/processor_core.c  |  191 --------------------------
 drivers/acpi/resource.c        |   46 +++++++
 drivers/pci/Kconfig            |    7 -
 drivers/pci/Makefile           |    2 -
 drivers/pci/ioapic.c           |  121 ----------------
 drivers/pci/pcie/portdrv_pci.c |    4 -
 include/acpi/processor.h       |    3 -
 include/linux/acpi.h           |   11 ++
 19 files changed, 868 insertions(+), 433 deletions(-)
 create mode 100644 drivers/acpi/apic_id.c
 create mode 100644 drivers/acpi/ioapic.c
 delete mode 100644 drivers/pci/ioapic.c

-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [RFC Patch V2 01/16] x86, irq: Split out alloc_ioapic_save_registers()
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 02/16] x86, ioapic: Find usable ioapic id for 64bit Jiang Liu
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Sebastian Andrzej Siewior, Ingo Molnar

From: Yinghai Lu <yinghai@kernel.org>

Split alloc_ioapic_save_registers() from early_irq_init(),
so it will be used per ioapic.

Will call that later for hot-added ioapic controller.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
---
 arch/x86/kernel/apic/io_apic.c |   22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 26490336ef6f..e97ec28f5269 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -237,6 +237,19 @@ static struct irq_pin_list *alloc_irq_pin_list(int node)
 	return kzalloc_node(sizeof(struct irq_pin_list), GFP_KERNEL, node);
 }
 
+static void alloc_ioapic_saved_registers(int idx)
+{
+	size_t size;
+
+	if (ioapics[idx].saved_registers)
+		return;
+
+	size = sizeof(struct IO_APIC_route_entry) * ioapics[idx].nr_registers;
+	ioapics[idx].saved_registers = kzalloc(size, GFP_KERNEL);
+	if (!ioapics[idx].saved_registers)
+		pr_err("IOAPIC %d: suspend/resume impossible!\n", idx);
+}
+
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
@@ -245,13 +258,8 @@ int __init arch_early_irq_init(void)
 	if (!nr_legacy_irqs())
 		io_apic_irqs = ~0UL;
 
-	for_each_ioapic(i) {
-		ioapics[i].saved_registers =
-			kzalloc(sizeof(struct IO_APIC_route_entry) *
-				ioapics[i].nr_registers, GFP_KERNEL);
-		if (!ioapics[i].saved_registers)
-			pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
-	}
+	for_each_ioapic(i)
+		alloc_ioapic_saved_registers(i);
 
 	/*
 	 * For legacy IRQ's, start with assigning irq0 to irq15 to
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 02/16] x86, ioapic: Find usable ioapic id for 64bit.
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 01/16] x86, irq: Split out alloc_ioapic_save_registers() Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 03/16] ACPI, x86/PCI: Move resource_to_addr() to acpi generic Jiang Liu
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Sebastian Andrzej Siewior, Ingo Molnar

From: Yinghai Lu <yinghai@kernel.org>

Checking the id in register, if that is duplicated, will pick one and
update id register.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/apic/io_apic.c |   38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e97ec28f5269..e56bb94cd32a 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3566,26 +3566,54 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 	return apic_id;
 }
 
-static u8 __init io_apic_unique_id(u8 id)
+static u8 io_apic_unique_id(int idx, u8 id)
 {
 	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
 	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return io_apic_get_unique_id(nr_ioapics, id);
+		return io_apic_get_unique_id(idx, id);
 	else
 		return id;
 }
 #else
-static u8 __init io_apic_unique_id(u8 id)
+static u8 io_apic_unique_id(int idx, u8 id)
 {
 	int i;
+	u8 new_id;
+	unsigned long flags;
 	DECLARE_BITMAP(used, 256);
+	union IO_APIC_reg_00 reg_00;
 
 	bitmap_zero(used, 256);
 	for_each_ioapic(i)
 		__set_bit(mpc_ioapic_id(i), used);
 	if (!test_bit(id, used))
 		return id;
-	return find_first_zero_bit(used, 256);
+
+	/* check register at first */
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(idx, 0);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+	new_id = reg_00.bits.ID;
+	if (!test_bit(new_id, used)) {
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Using reg apic_id %d instead of %d\n",
+			 idx, new_id, id);
+		return new_id;
+	}
+
+	new_id = find_first_zero_bit(used, 256);
+	reg_00.bits.ID = new_id;
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	io_apic_write(idx, 0, reg_00.raw);
+	reg_00.raw = io_apic_read(idx, 0);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	/* Sanity check */
+	if (reg_00.bits.ID != new_id)
+		pr_warn("IOAPIC[%d]: Unable to change apic_id to %d!\n",
+			idx, new_id);
+
+	return new_id;
 }
 #endif
 
@@ -3851,7 +3879,7 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
 		return;
 	}
 
-	ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
+	ioapics[idx].mp_config.apicid = io_apic_unique_id(idx, id);
 	ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
 
 	/*
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 03/16] ACPI, x86/PCI: Move resource_to_addr() to acpi generic
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 01/16] x86, irq: Split out alloc_ioapic_save_registers() Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 02/16] x86, ioapic: Find usable ioapic id for 64bit Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17 16:05   ` Bjorn Helgaas
  2014-06-17  5:29 ` [RFC Patch V2 04/16] ACPI: Make map_mat_entry handle x2apic entry Jiang Liu
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-acpi, Jiang Liu

From: Yinghai Lu <yinghai@kernel.org>

Rui Wang reported ioapic hot-add does not work on his machine
that _CRS have MEMORY_FIXED.
He also proposed to expose resource_to_addr() and use it for ioapic.

We should move it to acpi generic, as ioapi.c current is in
drivers/pci/.

Or should move it to acpica?

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/pci/acpi.c     |   50 ++---------------------------------------------
 drivers/acpi/resource.c |   46 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/acpi.h    |    3 +++
 3 files changed, 51 insertions(+), 48 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 91bef49df228..e766cc7d3abe 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -218,59 +218,13 @@ static void teardown_mcfg_map(struct pci_root_info *info)
 }
 #endif
 
-static acpi_status resource_to_addr(struct acpi_resource *resource,
-				    struct acpi_resource_address64 *addr)
-{
-	acpi_status status;
-	struct acpi_resource_memory24 *memory24;
-	struct acpi_resource_memory32 *memory32;
-	struct acpi_resource_fixed_memory32 *fixed_memory32;
-
-	memset(addr, 0, sizeof(*addr));
-	switch (resource->type) {
-	case ACPI_RESOURCE_TYPE_MEMORY24:
-		memory24 = &resource->data.memory24;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = memory24->minimum;
-		addr->address_length = memory24->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_MEMORY32:
-		memory32 = &resource->data.memory32;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = memory32->minimum;
-		addr->address_length = memory32->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		fixed_memory32 = &resource->data.fixed_memory32;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = fixed_memory32->address;
-		addr->address_length = fixed_memory32->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_ADDRESS16:
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		status = acpi_resource_to_address64(resource, addr);
-		if (ACPI_SUCCESS(status) &&
-		    (addr->resource_type == ACPI_MEMORY_RANGE ||
-		    addr->resource_type == ACPI_IO_RANGE) &&
-		    addr->address_length > 0) {
-			return AE_OK;
-		}
-		break;
-	}
-	return AE_ERROR;
-}
-
 static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
 	struct acpi_resource_address64 addr;
 	acpi_status status;
 
-	status = resource_to_addr(acpi_res, &addr);
+	status = acpi_mem_addr_resource_to_address64(acpi_res, &addr);
 	if (ACPI_SUCCESS(status))
 		info->res_num++;
 	return AE_OK;
@@ -285,7 +239,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 	unsigned long flags;
 	u64 start, orig_end, end;
 
-	status = resource_to_addr(acpi_res, &addr);
+	status = acpi_mem_addr_resource_to_address64(acpi_res, &addr);
 	if (!ACPI_SUCCESS(status))
 		return AE_OK;
 
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 0bdacc5e26a3..e91deebf0930 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -424,6 +424,52 @@ void acpi_dev_free_resource_list(struct list_head *list)
 }
 EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
 
+acpi_status acpi_mem_addr_resource_to_address64(struct acpi_resource *resource,
+			struct acpi_resource_address64 *addr)
+{
+	acpi_status status;
+	struct acpi_resource_memory24 *memory24;
+	struct acpi_resource_memory32 *memory32;
+	struct acpi_resource_fixed_memory32 *fixed_memory32;
+
+	memset(addr, 0, sizeof(*addr));
+	switch (resource->type) {
+	case ACPI_RESOURCE_TYPE_MEMORY24:
+		memory24 = &resource->data.memory24;
+		addr->resource_type = ACPI_MEMORY_RANGE;
+		addr->minimum = memory24->minimum;
+		addr->address_length = memory24->address_length;
+		addr->maximum = addr->minimum + addr->address_length - 1;
+		return AE_OK;
+	case ACPI_RESOURCE_TYPE_MEMORY32:
+		memory32 = &resource->data.memory32;
+		addr->resource_type = ACPI_MEMORY_RANGE;
+		addr->minimum = memory32->minimum;
+		addr->address_length = memory32->address_length;
+		addr->maximum = addr->minimum + addr->address_length - 1;
+		return AE_OK;
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+		fixed_memory32 = &resource->data.fixed_memory32;
+		addr->resource_type = ACPI_MEMORY_RANGE;
+		addr->minimum = fixed_memory32->address;
+		addr->address_length = fixed_memory32->address_length;
+		addr->maximum = addr->minimum + addr->address_length - 1;
+		return AE_OK;
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+		status = acpi_resource_to_address64(resource, addr);
+		if (ACPI_SUCCESS(status) &&
+		    (addr->resource_type == ACPI_MEMORY_RANGE ||
+		    addr->resource_type == ACPI_IO_RANGE) &&
+		    addr->address_length > 0) {
+			return AE_OK;
+		}
+		break;
+	}
+	return AE_ERROR;
+}
+
 struct res_proc_context {
 	struct list_head *list;
 	int (*preproc)(struct acpi_resource *, void *);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 7a8f2cd66c8b..b479e10f6621 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -286,6 +286,9 @@ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
 bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
 				 struct resource *res);
 
+acpi_status acpi_mem_addr_resource_to_address64(struct acpi_resource *resource,
+			struct acpi_resource_address64 *addr);
+
 struct resource_list_entry {
 	struct list_head node;
 	struct resource res;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 04/16] ACPI: Make map_mat_entry handle x2apic entry
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (2 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 03/16] ACPI, x86/PCI: Move resource_to_addr() to acpi generic Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 05/16] ACPI: Move acpi_get_cpuid() to separated file Jiang Liu
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, x86, linux-kernel, linux-pci,
	linux-acpi, Jiang Liu

From: Yinghai Lu <yinghai@kernel.org>

Now we have map_madt_entry/MADT to handle x2apic, but does not do
that with map_mat_entry _MAT.

For hotplug on system with x2apic only support, we need to add
support for x2apic map in _MAT.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/acpi/processor_core.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 71e2065639a6..c8a991e9d257 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -133,6 +133,8 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 	header = (struct acpi_subtable_header *)obj->buffer.pointer;
 	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
 		map_lapic_id(header, acpi_id, &apic_id);
+	} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+		map_x2apic_id(header, type, acpi_id, &apic_id);
 	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
 		map_lsapic_id(header, type, acpi_id, &apic_id);
 	}
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 05/16] ACPI: Move acpi_get_cpuid() to separated file
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (3 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 04/16] ACPI: Make map_mat_entry handle x2apic entry Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 06/16] ACPI, ioapic: Add acpi_get_ioapic_id() Jiang Liu
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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, Robert Moore, Lv Zheng
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, x86, linux-kernel, linux-pci,
	linux-acpi, Jiang Liu, devel

From: Yinghai Lu <yinghai@kernel.org>

Will need to reuse searching MADT for ioapic, but should add
related function like acpi_get_ioapic_id to processor_core.c
to pollute the file.

Move related cpu apic id search to separated file.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/acpi/Makefile         |    1 +
 drivers/acpi/apic_id.c        |  202 +++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/processor_core.c |  193 ---------------------------------------
 include/acpi/processor.h      |    3 -
 include/linux/acpi.h          |    4 +
 5 files changed, 207 insertions(+), 196 deletions(-)
 create mode 100644 drivers/acpi/apic_id.c

diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 0331f91d56e6..d922febd9164 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -34,6 +34,7 @@ acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o
 acpi-y				+= bus.o glue.o
 acpi-y				+= scan.o
 acpi-y				+= resource.o
+acpi-y				+= apic_id.o
 acpi-y				+= acpi_processor.o
 acpi-y				+= processor_core.o
 acpi-y				+= ec.o
diff --git a/drivers/acpi/apic_id.c b/drivers/acpi/apic_id.c
new file mode 100644
index 000000000000..ac3b10a9f92d
--- /dev/null
+++ b/drivers/acpi/apic_id.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2005 Intel Corporation
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *	All routines dealing with CPU APIC ID are moved from processor_core.c
+ */
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+
+#include "internal.h"
+
+static int map_lapic_id(struct acpi_subtable_header *entry,
+		 u32 acpi_id, int *apic_id)
+{
+	struct acpi_madt_local_apic *lapic =
+		(struct acpi_madt_local_apic *)entry;
+
+	if (!(lapic->lapic_flags & ACPI_MADT_ENABLED))
+		return -ENODEV;
+
+	if (lapic->processor_id != acpi_id)
+		return -EINVAL;
+
+	*apic_id = lapic->id;
+	return 0;
+}
+
+static int map_x2apic_id(struct acpi_subtable_header *entry,
+			 int device_declaration, u32 acpi_id, int *apic_id)
+{
+	struct acpi_madt_local_x2apic *apic =
+		(struct acpi_madt_local_x2apic *)entry;
+
+	if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
+		return -ENODEV;
+
+	if (device_declaration && (apic->uid == acpi_id)) {
+		*apic_id = apic->local_apic_id;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int map_lsapic_id(struct acpi_subtable_header *entry,
+		int device_declaration, u32 acpi_id, int *apic_id)
+{
+	struct acpi_madt_local_sapic *lsapic =
+		(struct acpi_madt_local_sapic *)entry;
+
+	if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
+		return -ENODEV;
+
+	if (device_declaration) {
+		if ((entry->length < 16) || (lsapic->uid != acpi_id))
+			return -EINVAL;
+	} else if (lsapic->processor_id != acpi_id)
+		return -EINVAL;
+
+	*apic_id = (lsapic->id << 8) | lsapic->eid;
+	return 0;
+}
+
+static int map_madt_entry(int type, u32 acpi_id)
+{
+	unsigned long madt_end, entry;
+	static struct acpi_table_madt *madt;
+	static int read_madt;
+	int apic_id = -1;
+
+	if (!read_madt) {
+		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
+					(struct acpi_table_header **)&madt)))
+			madt = NULL;
+		read_madt++;
+	}
+
+	if (!madt)
+		return apic_id;
+
+	entry = (unsigned long)madt;
+	madt_end = entry + madt->header.length;
+
+	/* Parse all entries looking for a match. */
+
+	entry += sizeof(struct acpi_table_madt);
+	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
+		struct acpi_subtable_header *header =
+			(struct acpi_subtable_header *)entry;
+		if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
+			if (!map_lapic_id(header, acpi_id, &apic_id))
+				break;
+		} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
+			if (!map_x2apic_id(header, type, acpi_id, &apic_id))
+				break;
+		} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
+			if (!map_lsapic_id(header, type, acpi_id, &apic_id))
+				break;
+		}
+		entry += header->length;
+	}
+	return apic_id;
+}
+
+static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	struct acpi_subtable_header *header;
+	int apic_id = -1;
+
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+		goto exit;
+
+	if (!buffer.length || !buffer.pointer)
+		goto exit;
+
+	obj = buffer.pointer;
+	if (obj->type != ACPI_TYPE_BUFFER ||
+	    obj->buffer.length < sizeof(struct acpi_subtable_header)) {
+		goto exit;
+	}
+
+	header = (struct acpi_subtable_header *)obj->buffer.pointer;
+	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC)
+		map_lapic_id(header, acpi_id, &apic_id);
+	else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC)
+		map_x2apic_id(header, type, acpi_id, &apic_id);
+	else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC)
+		map_lsapic_id(header, type, acpi_id, &apic_id);
+
+exit:
+	kfree(buffer.pointer);
+	return apic_id;
+}
+
+int acpi_get_apicid(acpi_handle handle, int type, u32 acpi_id)
+{
+	int apic_id;
+
+	apic_id = map_mat_entry(handle, type, acpi_id);
+	if (apic_id == -1)
+		apic_id = map_madt_entry(type, acpi_id);
+
+	return apic_id;
+}
+
+int acpi_map_cpuid(int apic_id, u32 acpi_id)
+{
+#ifdef CONFIG_SMP
+	int i;
+#endif
+
+	if (apic_id == -1) {
+		/*
+		 * On UP processor, there is no _MAT or MADT table.
+		 * So above apic_id is always set to -1.
+		 *
+		 * BIOS may define multiple CPU handles even for UP processor.
+		 * For example,
+		 *
+		 * Scope (_PR)
+		 * {
+		 *     Processor (CPU0, 0x00, 0x00000410, 0x06) {}
+		 *     Processor (CPU1, 0x01, 0x00000410, 0x06) {}
+		 *     Processor (CPU2, 0x02, 0x00000410, 0x06) {}
+		 *     Processor (CPU3, 0x03, 0x00000410, 0x06) {}
+		 * }
+		 *
+		 * Ignores apic_id and always returns 0 for the processor
+		 * handle with acpi id 0 if nr_cpu_ids is 1.
+		 * This should be the case if SMP tables are not found.
+		 * Return -1 for other CPU's handle.
+		 */
+		if (nr_cpu_ids <= 1 && acpi_id == 0)
+			return acpi_id;
+		else
+			return apic_id;
+	}
+
+#ifdef CONFIG_SMP
+	for_each_possible_cpu(i) {
+		if (cpu_physical_id(i) == apic_id)
+			return i;
+	}
+#else
+	/* In UP kernel, only processor 0 is valid */
+	if (apic_id == 0)
+		return apic_id;
+#endif
+	return -1;
+}
+
+int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
+{
+	int apic_id;
+
+	apic_id = acpi_get_apicid(handle, type, acpi_id);
+
+	return acpi_map_cpuid(apic_id, acpi_id);
+}
+EXPORT_SYMBOL_GPL(acpi_get_cpuid);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index c8a991e9d257..e2ef53721755 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -18,199 +18,6 @@
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
-static int map_lapic_id(struct acpi_subtable_header *entry,
-		 u32 acpi_id, int *apic_id)
-{
-	struct acpi_madt_local_apic *lapic =
-		(struct acpi_madt_local_apic *)entry;
-
-	if (!(lapic->lapic_flags & ACPI_MADT_ENABLED))
-		return -ENODEV;
-
-	if (lapic->processor_id != acpi_id)
-		return -EINVAL;
-
-	*apic_id = lapic->id;
-	return 0;
-}
-
-static int map_x2apic_id(struct acpi_subtable_header *entry,
-			 int device_declaration, u32 acpi_id, int *apic_id)
-{
-	struct acpi_madt_local_x2apic *apic =
-		(struct acpi_madt_local_x2apic *)entry;
-
-	if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
-		return -ENODEV;
-
-	if (device_declaration && (apic->uid == acpi_id)) {
-		*apic_id = apic->local_apic_id;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int map_lsapic_id(struct acpi_subtable_header *entry,
-		int device_declaration, u32 acpi_id, int *apic_id)
-{
-	struct acpi_madt_local_sapic *lsapic =
-		(struct acpi_madt_local_sapic *)entry;
-
-	if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
-		return -ENODEV;
-
-	if (device_declaration) {
-		if ((entry->length < 16) || (lsapic->uid != acpi_id))
-			return -EINVAL;
-	} else if (lsapic->processor_id != acpi_id)
-		return -EINVAL;
-
-	*apic_id = (lsapic->id << 8) | lsapic->eid;
-	return 0;
-}
-
-static int map_madt_entry(int type, u32 acpi_id)
-{
-	unsigned long madt_end, entry;
-	static struct acpi_table_madt *madt;
-	static int read_madt;
-	int apic_id = -1;
-
-	if (!read_madt) {
-		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
-					(struct acpi_table_header **)&madt)))
-			madt = NULL;
-		read_madt++;
-	}
-
-	if (!madt)
-		return apic_id;
-
-	entry = (unsigned long)madt;
-	madt_end = entry + madt->header.length;
-
-	/* Parse all entries looking for a match. */
-
-	entry += sizeof(struct acpi_table_madt);
-	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
-		struct acpi_subtable_header *header =
-			(struct acpi_subtable_header *)entry;
-		if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
-			if (!map_lapic_id(header, acpi_id, &apic_id))
-				break;
-		} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
-			if (!map_x2apic_id(header, type, acpi_id, &apic_id))
-				break;
-		} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
-			if (!map_lsapic_id(header, type, acpi_id, &apic_id))
-				break;
-		}
-		entry += header->length;
-	}
-	return apic_id;
-}
-
-static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
-{
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-	union acpi_object *obj;
-	struct acpi_subtable_header *header;
-	int apic_id = -1;
-
-	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
-		goto exit;
-
-	if (!buffer.length || !buffer.pointer)
-		goto exit;
-
-	obj = buffer.pointer;
-	if (obj->type != ACPI_TYPE_BUFFER ||
-	    obj->buffer.length < sizeof(struct acpi_subtable_header)) {
-		goto exit;
-	}
-
-	header = (struct acpi_subtable_header *)obj->buffer.pointer;
-	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
-		map_lapic_id(header, acpi_id, &apic_id);
-	} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
-		map_x2apic_id(header, type, acpi_id, &apic_id);
-	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
-		map_lsapic_id(header, type, acpi_id, &apic_id);
-	}
-
-exit:
-	kfree(buffer.pointer);
-	return apic_id;
-}
-
-int acpi_get_apicid(acpi_handle handle, int type, u32 acpi_id)
-{
-	int apic_id;
-
-	apic_id = map_mat_entry(handle, type, acpi_id);
-	if (apic_id == -1)
-		apic_id = map_madt_entry(type, acpi_id);
-
-	return apic_id;
-}
-
-int acpi_map_cpuid(int apic_id, u32 acpi_id)
-{
-#ifdef CONFIG_SMP
-	int i;
-#endif
-
-	if (apic_id == -1) {
-		/*
-		 * On UP processor, there is no _MAT or MADT table.
-		 * So above apic_id is always set to -1.
-		 *
-		 * BIOS may define multiple CPU handles even for UP processor.
-		 * For example,
-		 *
-		 * Scope (_PR)
-                 * {
-		 *     Processor (CPU0, 0x00, 0x00000410, 0x06) {}
-		 *     Processor (CPU1, 0x01, 0x00000410, 0x06) {}
-		 *     Processor (CPU2, 0x02, 0x00000410, 0x06) {}
-		 *     Processor (CPU3, 0x03, 0x00000410, 0x06) {}
-		 * }
-		 *
-		 * Ignores apic_id and always returns 0 for the processor
-		 * handle with acpi id 0 if nr_cpu_ids is 1.
-		 * This should be the case if SMP tables are not found.
-		 * Return -1 for other CPU's handle.
-		 */
-		if (nr_cpu_ids <= 1 && acpi_id == 0)
-			return acpi_id;
-		else
-			return apic_id;
-	}
-
-#ifdef CONFIG_SMP
-	for_each_possible_cpu(i) {
-		if (cpu_physical_id(i) == apic_id)
-			return i;
-	}
-#else
-	/* In UP kernel, only processor 0 is valid */
-	if (apic_id == 0)
-		return apic_id;
-#endif
-	return -1;
-}
-
-int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
-{
-	int apic_id;
-
-	apic_id = acpi_get_apicid(handle, type, acpi_id);
-
-	return acpi_map_cpuid(apic_id, acpi_id);
-}
-EXPORT_SYMBOL_GPL(acpi_get_cpuid);
-
 static bool __init processor_physically_present(acpi_handle handle)
 {
 	int cpuid, type;
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 6eb1d3cb5104..337e731ec2ba 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -314,9 +314,6 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 
 /* in processor_core.c */
 void acpi_processor_set_pdc(acpi_handle handle);
-int acpi_get_apicid(acpi_handle, int type, u32 acpi_id);
-int acpi_map_cpuid(int apic_id, u32 acpi_id);
-int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
 
 /* in processor_throttling.c */
 int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index b479e10f6621..5c432e842921 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -145,6 +145,10 @@ int acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu);
 int acpi_unmap_lsapic(int cpu);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
+int acpi_get_apicid(acpi_handle, int type, u32 acpi_id);
+int acpi_map_cpuid(int apic_id, u32 acpi_id);
+int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
+
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
 void acpi_irq_stats_init(void);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 06/16] ACPI, ioapic: Add acpi_get_ioapic_id()
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (4 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 05/16] ACPI: Move acpi_get_cpuid() to separated file Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 07/16] x86, irq, ACPI: protect acpi_pci_irq_enable() from reentrance Jiang Liu
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, x86, linux-kernel, linux-pci,
	linux-acpi, Jiang Liu

From: Yinghai Lu <yinghai@kernel.org>

For ioapic hotplug, we need to parse apic id for ioapic registration.

We could check _MAT and MADT to get io apic id, just like cpu hotplug
path to get apic id.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/acpi/apic_id.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/acpi.h   |    3 ++
 2 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/apic_id.c b/drivers/acpi/apic_id.c
index ac3b10a9f92d..a74a3fcd8362 100644
--- a/drivers/acpi/apic_id.c
+++ b/drivers/acpi/apic_id.c
@@ -2,6 +2,10 @@
  * Copyright (C) 2005 Intel Corporation
  * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  *	All routines dealing with CPU APIC ID are moved from processor_core.c
+ *
+ * I/O APIC hotplug support
+ *	Yinghai Lu <yinghai@kernel.org>
+ *	Jiang Liu <jiang.liu@intel.com>
  */
 #include <linux/export.h>
 #include <linux/slab.h>
@@ -9,6 +13,9 @@
 
 #include "internal.h"
 
+static struct acpi_table_madt *madt;
+static int read_madt;
+
 static int map_lapic_id(struct acpi_subtable_header *entry,
 		 u32 acpi_id, int *apic_id)
 {
@@ -64,8 +71,6 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
 static int map_madt_entry(int type, u32 acpi_id)
 {
 	unsigned long madt_end, entry;
-	static struct acpi_table_madt *madt;
-	static int read_madt;
 	int apic_id = -1;
 
 	if (!read_madt) {
@@ -200,3 +205,91 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 	return acpi_map_cpuid(apic_id, acpi_id);
 }
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+static int map_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base,
+			 u64 *phys_addr, int *ioapic_id)
+{
+	struct acpi_madt_io_apic *ioapic = (struct acpi_madt_io_apic *)entry;
+
+	if (ioapic->global_irq_base != gsi_base)
+		return 0;
+
+	*phys_addr = ioapic->address;
+	*ioapic_id = ioapic->id;
+	return 1;
+}
+
+static int map_madt_ioapic_entry(u32 gsi_base, u64 *phys_addr)
+{
+	struct acpi_subtable_header *hdr;
+	unsigned long madt_end, entry;
+	int apic_id = -1;
+
+	if (!read_madt) {
+		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
+					(struct acpi_table_header **)&madt)))
+			madt = NULL;
+		read_madt++;
+	}
+
+	if (!madt)
+		return apic_id;
+
+	entry = (unsigned long)madt;
+	madt_end = entry + madt->header.length;
+
+	/* Parse all entries looking for a match. */
+	entry += sizeof(struct acpi_table_madt);
+	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
+		hdr = (struct acpi_subtable_header *)entry;
+		if (hdr->type == ACPI_MADT_TYPE_IO_APIC &&
+		    map_ioapic_id(hdr, gsi_base, phys_addr, &apic_id))
+			break;
+		else
+			entry += hdr->length;
+	}
+
+	return apic_id;
+}
+
+static int map_mat_ioapic_entry(acpi_handle handle, u32 gsi_base,
+				u64 *phys_addr)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	struct acpi_subtable_header *header;
+	int apic_id = -1;
+
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+		goto exit;
+
+	if (!buffer.length || !buffer.pointer)
+		goto exit;
+
+	obj = buffer.pointer;
+	if (obj->type != ACPI_TYPE_BUFFER ||
+	    obj->buffer.length < sizeof(struct acpi_subtable_header)) {
+		goto exit;
+	}
+
+	header = (struct acpi_subtable_header *)obj->buffer.pointer;
+	if (header->type == ACPI_MADT_TYPE_IO_APIC)
+		map_ioapic_id(header, gsi_base, phys_addr, &apic_id);
+
+exit:
+	kfree(buffer.pointer);
+	return apic_id;
+}
+
+int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr)
+{
+	int apic_id;
+
+	apic_id = map_mat_ioapic_entry(handle, gsi_base, phys_addr);
+	if (apic_id == -1)
+		apic_id = map_madt_ioapic_entry(gsi_base, phys_addr);
+
+	return apic_id;
+}
+#endif /* CONFIG_ACPI_HOTPLUG_IOAPIC */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 5c432e842921..f478af87f575 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -148,6 +148,9 @@ int acpi_unmap_lsapic(int cpu);
 int acpi_get_apicid(acpi_handle, int type, u32 acpi_id);
 int acpi_map_cpuid(int apic_id, u32 acpi_id);
 int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
+#endif
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 07/16] x86, irq, ACPI: protect acpi_pci_irq_enable() from reentrance
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (5 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 06/16] ACPI, ioapic: Add acpi_get_ioapic_id() Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 08/16] PCI: kill wrong warning message in pcieport driver Jiang Liu
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

Function acpi_pci_irq_enable() may be called twice for each PCI device
present at boot time as below:
1) pci_acpi_init()
	--> acpi_pci_irq_enable()
2) pci_enable_device()
	--> pcibios_enable_device()
		--> acpi_pci_irq_enable()

So protect acpi_pci_irq_enable() from reentrance to correctly manage
IOAPIC pin reference count.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/acpi/pci_irq.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 6ba463ceccc6..9d2ebd5fd9aa 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -413,6 +413,9 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return 0;
 	}
 
+	if (dev->irq > 0)
+		return 0;
+
 	entry = acpi_pci_irq_lookup(dev, pin);
 	if (!entry) {
 		/*
@@ -498,6 +501,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
 	 */
 
 	dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
-	if (gsi >= 0 && dev->irq > 0)
+	if (gsi >= 0 && dev->irq > 0) {
 		acpi_unregister_gsi(gsi);
+		dev->irq = 0;
+	}
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 08/16] PCI: kill wrong warning message in pcieport driver
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (6 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 07/16] x86, irq, ACPI: protect acpi_pci_irq_enable() from reentrance Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17 16:11   ` Bjorn Helgaas
  2014-06-17  5:29 ` [RFC Patch V2 09/16] x86, irq: remove __init marker for functions will be used by IOAPIC hotplug Jiang Liu
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu, Jiang Liu
  Cc: Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck, Joerg Roedel,
	Paul Gortmaker, Greg Kroah-Hartman, x86, linux-kernel, linux-pci,
	linux-acpi

For hot-added PCIe ports, it always generates a warning message on x86
platforms when binding to pcieport driver as:
	"device [8086:0e0b] has invalid IRQ; check vendor BIOS".

It's due to that we check pci_dev->irq before actually allocating IRQ
number for the PCI device:
	if (!dev->irq && dev->pin) {
		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
			 "check vendor BIOS\n", dev->vendor, dev->device);
	}
 	status = pcie_port_device_register(dev);
		-->pci_enable_device(dev);
			-->pci_enable_device_flags()
				-->do_pci_enable_device()
					-->pcibios_enable_device()
						-->pcibios_enable_irq()

This warning message isn't generated for PCIe ports present at boot time
because x86 arch code has called acpi_pci_irq_enable() in pci_acpi_init()
for each PCI device for safety.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/pci/pcie/portdrv_pci.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 0d8fdc48e642..0e35f9670066 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -203,10 +203,6 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
 	     (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
 		return -ENODEV;
 
-	if (!dev->irq && dev->pin) {
-		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
-			 "check vendor BIOS\n", dev->vendor, dev->device);
-	}
 	status = pcie_port_device_register(dev);
 	if (status)
 		return status;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 09/16] x86, irq: remove __init marker for functions will be used by IOAPIC hotplug
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (7 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 08/16] PCI: kill wrong warning message in pcieport driver Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 10/16] x86, irq: refine mp_register_ioapic() to prepare for " Jiang Liu
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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, 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

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/io_apic.h |    4 ++--
 arch/x86/kernel/apic/io_apic.c |   14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 0aeed5ca356e..0b31aebd9405 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -188,8 +188,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-				      struct ioapic_domain_cfg *cfg);
+extern void mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			       struct ioapic_domain_cfg *cfg);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e56bb94cd32a..15a7d36d4a9c 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3445,7 +3445,7 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
 	return ret;
 }
 
-static int __init io_apic_get_redir_entries(int ioapic)
+static int io_apic_get_redir_entries(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3491,7 +3491,7 @@ int __init arch_probe_nr_irqs(void)
 }
 
 #ifdef CONFIG_X86_32
-static int __init io_apic_get_unique_id(int ioapic, int apic_id)
+static int io_apic_get_unique_id(int ioapic, int apic_id)
 {
 	union IO_APIC_reg_00 reg_00;
 	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
@@ -3617,7 +3617,7 @@ static u8 io_apic_unique_id(int idx, u8 id)
 }
 #endif
 
-static int __init io_apic_get_version(int ioapic)
+static int io_apic_get_version(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3821,7 +3821,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
 	return gsi - gsi_cfg->gsi_base;
 }
 
-static __init int bad_ioapic(unsigned long address)
+static int bad_ioapic(unsigned long address)
 {
 	if (nr_ioapics >= MAX_IO_APICS) {
 		pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
@@ -3835,7 +3835,7 @@ static __init int bad_ioapic(unsigned long address)
 	return 0;
 }
 
-static __init int bad_ioapic_register(int idx)
+static int bad_ioapic_register(int idx)
 {
 	union IO_APIC_reg_00 reg_00;
 	union IO_APIC_reg_01 reg_01;
@@ -3854,8 +3854,8 @@ static __init int bad_ioapic_register(int idx)
 	return 0;
 }
 
-void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			       struct ioapic_domain_cfg *cfg)
+void mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			struct ioapic_domain_cfg *cfg)
 {
 	int idx = 0;
 	int entries;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 10/16] x86, irq: refine mp_register_ioapic() to prepare for IOAPIC hotplug
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (8 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 09/16] x86, irq: remove __init marker for functions will be used by IOAPIC hotplug Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 11/16] x86, irq, ACPI: introduce a rwsem to protect IOAPIC operations from hotplug Jiang Liu
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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, 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

Refine mp_register_ioapic() to prepare for IOAPIC hotplug by:
1) change return value from void to int.
2) check for gsi range conflicts
3) check for IOAPIC physical address conflicts
4) enhance the way to allocate IOAPIC index

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/io_apic.h |    4 +-
 arch/x86/kernel/apic/io_apic.c |   80 ++++++++++++++++++++++++----------------
 2 files changed, 51 insertions(+), 33 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 0b31aebd9405..94d05bd6586f 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -188,8 +188,8 @@ extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
 extern u32 mp_pin_to_gsi(int ioapic, int pin);
 extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
-extern void mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			       struct ioapic_domain_cfg *cfg);
+extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
+			      struct ioapic_domain_cfg *cfg);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 15a7d36d4a9c..e1cce02e9f55 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3821,20 +3821,6 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
 	return gsi - gsi_cfg->gsi_base;
 }
 
-static int bad_ioapic(unsigned long address)
-{
-	if (nr_ioapics >= MAX_IO_APICS) {
-		pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
-			MAX_IO_APICS, nr_ioapics);
-		return 1;
-	}
-	if (!address) {
-		pr_warn("WARNING: Bogus (zero) I/O APIC address found in table, skipping!\n");
-		return 1;
-	}
-	return 0;
-}
-
 static int bad_ioapic_register(int idx)
 {
 	union IO_APIC_reg_00 reg_00;
@@ -3854,29 +3840,44 @@ static int bad_ioapic_register(int idx)
 	return 0;
 }
 
-void mp_register_ioapic(int id, u32 address, u32 gsi_base,
-			struct ioapic_domain_cfg *cfg)
+static int find_free_ioapic_entry(void)
 {
-	int idx = 0;
-	int entries;
+	return nr_ioapics;
+}
+
+int mp_register_ioapic(int id, u32 address, u32 gsi_base,
+		       struct ioapic_domain_cfg *cfg)
+{
+	u32 gsi_end;
+	int idx, ioapic, entries;
 	struct mp_ioapic_gsi *gsi_cfg;
 
-	if (bad_ioapic(address))
-		return;
+	if (!address) {
+		pr_warn("Bogus (zero) I/O APIC address found, skipping!\n");
+		return -EINVAL;
+	}
+	for_each_ioapic(ioapic)
+		if (ioapics[ioapic].mp_config.apicaddr == address) {
+			pr_warn("address 0x%x conflicts with IOAPIC%d\n",
+				address, ioapic);
+			return -EEXIST;
+		}
 
-	idx = nr_ioapics;
+	idx = find_free_ioapic_entry();
+	if (idx >= MAX_IO_APICS) {
+		pr_warn("Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
+			MAX_IO_APICS, idx);
+		return -ENOSPC;
+	}
 
 	ioapics[idx].mp_config.type = MP_IOAPIC;
 	ioapics[idx].mp_config.flags = MPC_APIC_USABLE;
 	ioapics[idx].mp_config.apicaddr = address;
-	ioapics[idx].irqdomain = NULL;
-	ioapics[idx].irqdomain_cfg = *cfg;
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
-
 	if (bad_ioapic_register(idx)) {
 		clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
-		return;
+		return -ENODEV;
 	}
 
 	ioapics[idx].mp_config.apicid = io_apic_unique_id(idx, id);
@@ -3887,24 +3888,41 @@ void 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);
+	gsi_end = gsi_base + entries - 1;
+	for_each_ioapic(ioapic) {
+		gsi_cfg = mp_ioapic_gsi_routing(ioapic);
+		if ((gsi_base >= gsi_cfg->gsi_base &&
+		     gsi_base <= gsi_cfg->gsi_end) ||
+		    (gsi_end >= gsi_cfg->gsi_base &&
+		     gsi_end <= gsi_cfg->gsi_end)) {
+			pr_warn("GSI range [%u-%u] for new IOAPIC conflicts with GSI[%u-%u]\n",
+				gsi_base, gsi_end,
+				gsi_cfg->gsi_base, gsi_cfg->gsi_end);
+			clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
+			return -ENOSPC;
+		}
+	}
 	gsi_cfg = mp_ioapic_gsi_routing(idx);
 	gsi_cfg->gsi_base = gsi_base;
-	gsi_cfg->gsi_end = gsi_base + entries - 1;
+	gsi_cfg->gsi_end = gsi_end;
 
-	/*
-	 * The number of IO-APIC IRQ registers (== #pins):
-	 */
-	ioapics[idx].nr_registers = entries;
+	ioapics[idx].irqdomain = NULL;
+	ioapics[idx].irqdomain_cfg = *cfg;
 
 	if (gsi_cfg->gsi_end >= gsi_top)
 		gsi_top = gsi_cfg->gsi_end + 1;
+	if (nr_ioapics <= idx)
+		nr_ioapics = idx + 1;
+
+	/* Set nr_registers to mark entry present */
+	ioapics[idx].nr_registers = entries;
 
 	pr_info("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, GSI %d-%d\n",
 		idx, mpc_ioapic_id(idx),
 		mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
 		gsi_cfg->gsi_base, gsi_cfg->gsi_end);
 
-	nr_ioapics++;
+	return 0;
 }
 
 int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 11/16] x86, irq, ACPI: introduce a rwsem to protect IOAPIC operations from hotplug
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (9 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 10/16] x86, irq: refine mp_register_ioapic() to prepare for " Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 12/16] x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-addition Jiang Liu
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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

We are going to support ACPI based IOAPIC hotplug, so introduce a rwsem
to protect IOAPIC data structures from IOAPIC hotplug. We choose to
serialize in ACPI instead of in the IOAPIC core because:
1) currently we are only plan to support ACPI based IOAPIC hotplug
2) it's much more clean and easy
3) It does't affect IOAPIC discovered by devicetree, SFI and mppparse.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/acpi/boot.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 8c28023924bf..120b573f1e96 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -76,6 +76,8 @@ int acpi_fix_pin2_polarity __initdata;
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
 
+static DECLARE_RWSEM(acpi_ioapic_rwsem);
+
 #ifndef __HAVE_ARCH_CMPXCHG
 #warning ACPI uses CMPXCHG, i486 and later hardware
 #endif
@@ -608,8 +610,11 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 {
-	int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+	int irq;
 
+	down_read(&acpi_ioapic_rwsem);
+	irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+	up_read(&acpi_ioapic_rwsem);
 	if (irq >= 0) {
 		*irqp = irq;
 		return 0;
@@ -650,7 +655,9 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
 	int irq = gsi;
 
 #ifdef CONFIG_X86_IO_APIC
+	down_read(&acpi_ioapic_rwsem);
 	irq = mp_register_gsi(dev, gsi, trigger, polarity);
+	up_read(&acpi_ioapic_rwsem);
 #endif
 
 	return irq;
@@ -659,7 +666,9 @@ static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
 static void acpi_unregister_gsi_ioapic(u32 gsi)
 {
 #ifdef CONFIG_X86_IO_APIC
+	down_read(&acpi_ioapic_rwsem);
 	mp_unregister_gsi(gsi);
+	up_read(&acpi_ioapic_rwsem);
 #endif
 }
 
@@ -1185,7 +1194,9 @@ static void __init acpi_process_madt(void)
 			/*
 			 * Parse MADT IO-APIC entries
 			 */
+			down_write(&acpi_ioapic_rwsem);
 			error = acpi_parse_madt_ioapic_entries();
+			up_write(&acpi_ioapic_rwsem);
 			if (!error) {
 				acpi_set_irq_model_ioapic();
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 12/16] x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-addition
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (10 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 11/16] x86, irq, ACPI: introduce a rwsem to protect IOAPIC operations from hotplug Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 13/16] x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-removal Jiang Liu
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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,
	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

Implement acpi_register_ioapic() and enhance mp_register_ioapic()
to support ACPI based IOAPIC hot-addition.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/kernel/acpi/boot.c    |   37 +++++++++++++++++++++++++++++++++++--
 arch/x86/kernel/apic/io_apic.c |   27 ++++++++++++++++++++++++---
 2 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 120b573f1e96..85caf3221cde 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -768,8 +768,41 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
+	int ret = -ENOSYS;
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	int ioapic_id;
+	u64 addr;
+	struct ioapic_domain_cfg cfg = {
+		.type = IOAPIC_DOMAIN_DYNAMIC,
+		.ops = &acpi_irqdomain_ops,
+	};
+
+	ioapic_id = acpi_get_ioapic_id(handle, gsi_base, &addr);
+	if (ioapic_id >= 0) {
+		if (addr != phys_addr) {
+			acpi_handle_warn(handle,
+				"IOAPIC physical address doesn't match.\n");
+			return -EINVAL;
+		}
+	} else  {
+		unsigned long long uid;
+		acpi_status status;
+
+		status = acpi_evaluate_integer(handle, METHOD_NAME__UID,
+					       NULL, &uid);
+		if (ACPI_FAILURE(status)) {
+			acpi_handle_warn(handle, "failed to get IOAPIC ID.\n");
+			return -EINVAL;
+		}
+		ioapic_id = (int)uid;
+	}
+
+	down_write(&acpi_ioapic_rwsem);
+	ret  = mp_register_ioapic(ioapic_id, phys_addr, gsi_base, &cfg);
+	up_write(&acpi_ioapic_rwsem);
+#endif
+
+	return ret;
 }
 
 EXPORT_SYMBOL(acpi_register_ioapic);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e1cce02e9f55..d26fd3ac1b4b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3842,7 +3842,13 @@ static int bad_ioapic_register(int idx)
 
 static int find_free_ioapic_entry(void)
 {
-	return nr_ioapics;
+	int idx;
+
+	for (idx = 0; idx < MAX_IO_APICS; idx++)
+		if (ioapics[idx].nr_registers == 0)
+			return idx;
+
+	return MAX_IO_APICS;
 }
 
 int mp_register_ioapic(int id, u32 address, u32 gsi_base,
@@ -3858,8 +3864,15 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	}
 	for_each_ioapic(ioapic)
 		if (ioapics[ioapic].mp_config.apicaddr == address) {
-			pr_warn("address 0x%x conflicts with IOAPIC%d\n",
-				address, ioapic);
+			/*
+			 * IOAPIC unit may also be visible in PCI scope.
+			 * When ioapic PCI driver's probe() is called,
+			 * the IOAPIC unit may have already been initialized
+			 * at boot time.
+			 */
+			if (!ioapic_initialized)
+				pr_warn("address 0x%x conflicts with IOAPIC%d\n",
+					address, ioapic);
 			return -EEXIST;
 		}
 
@@ -3909,6 +3922,14 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	ioapics[idx].irqdomain = NULL;
 	ioapics[idx].irqdomain_cfg = *cfg;
 
+	if (ioapic_initialized) {
+		if (mp_irqdomain_create(idx)) {
+			clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
+			return -ENOMEM;
+		}
+		alloc_ioapic_saved_registers(idx);
+	}
+
 	if (gsi_cfg->gsi_end >= gsi_top)
 		gsi_top = gsi_cfg->gsi_end + 1;
 	if (nr_ioapics <= idx)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 13/16] x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-removal
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (11 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 12/16] x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-addition Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 14/16] x86, irq: introduce helper to check whether an IOAPIC has been registered Jiang Liu
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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

Implement acpi_unregister_ioapic() to support ACPI based IOAPIC hot-removal.
An IOAPIC could only be removed when all its pins are unused.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/io_apic.h |    1 +
 arch/x86/kernel/acpi/boot.c    |   13 +++++++---
 arch/x86/kernel/apic/io_apic.c |   55 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 94d05bd6586f..ce63cf34c93c 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -190,6 +190,7 @@ extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
 extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
+extern int mp_unregister_ioapic(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 85caf3221cde..8a1b25d2aa4c 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -804,15 +804,20 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
 
 	return ret;
 }
-
 EXPORT_SYMBOL(acpi_register_ioapic);
 
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 {
-	/* TBD */
-	return -EINVAL;
-}
+	int ret = -ENOSYS;
+
+#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+	down_write(&acpi_ioapic_rwsem);
+	ret  = mp_unregister_ioapic(gsi_base);
+	up_write(&acpi_ioapic_rwsem);
+#endif
 
+	return ret;
+}
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index d26fd3ac1b4b..22bbecb05345 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -112,6 +112,7 @@ static struct ioapic {
 	struct ioapic_domain_cfg irqdomain_cfg;
 	struct irq_domain *irqdomain;
 	struct mp_pin_info *pin_info;
+	struct resource *iomem_res;
 } ioapics[MAX_IO_APICS];
 
 #define mpc_ioapic_ver(ioapic_idx)	ioapics[ioapic_idx].mp_config.apicver
@@ -250,6 +251,12 @@ static void alloc_ioapic_saved_registers(int idx)
 		pr_err("IOAPIC %d: suspend/resume impossible!\n", idx);
 }
 
+static void free_ioapic_saved_registers(int idx)
+{
+	kfree(ioapics[idx].saved_registers);
+	ioapics[idx].saved_registers = NULL;
+}
+
 int __init arch_early_irq_init(void)
 {
 	struct irq_cfg *cfg;
@@ -2967,6 +2974,16 @@ static int mp_irqdomain_create(int ioapic)
 	return 0;
 }
 
+static void ioapic_destroy_irqdomain(int idx)
+{
+	if (ioapics[idx].irqdomain) {
+		irq_domain_remove(ioapics[idx].irqdomain);
+		ioapics[idx].irqdomain = NULL;
+	}
+	kfree(ioapics[idx].pin_info);
+	ioapics[idx].pin_info = NULL;
+}
+
 void __init setup_IO_APIC(void)
 {
 	int ioapic;
@@ -3724,6 +3741,7 @@ static struct resource * __init ioapic_setup_resources(void)
 		snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
 		mem += IOAPIC_RESOURCE_NAME_SIZE;
 		num++;
+		ioapics[i].iomem_res = res;
 	}
 
 	ioapic_resources = res;
@@ -3946,6 +3964,43 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 	return 0;
 }
 
+int mp_unregister_ioapic(u32 gsi_base)
+{
+	int ioapic, pin;
+	int found = 0;
+	struct mp_pin_info *pin_info;
+
+	for_each_ioapic(ioapic)
+		if (ioapics[ioapic].gsi_config.gsi_base == gsi_base) {
+			found = 1;
+			break;
+		}
+	if (!found) {
+		pr_warn("can't find IOAPIC for GSI %d\n", gsi_base);
+		return -ENODEV;
+	}
+
+	for_each_pin(ioapic, pin) {
+		pin_info = mp_pin_info(ioapic, pin);
+		if (pin_info->count) {
+			pr_warn("pin%d on IOAPIC%d is still in use.\n",
+				pin, ioapic);
+			return -EBUSY;
+		}
+	}
+
+	/* Mark entry not present */
+	ioapics[ioapic].nr_registers  = 0;
+	ioapic_destroy_irqdomain(ioapic);
+	free_ioapic_saved_registers(ioapic);
+	if (ioapics[ioapic].iomem_res)
+		release_resource(ioapics[ioapic].iomem_res);
+	clear_fixmap(FIX_IO_APIC_BASE_0 + ioapic);
+	memset(&ioapics[ioapic], 0, sizeof(ioapics[ioapic]));
+
+	return 0;
+}
+
 int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 		     irq_hw_number_t hwirq)
 {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 14/16] x86, irq: introduce helper to check whether an IOAPIC has been registered
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (12 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 13/16] x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-removal Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 15/16] pci, ioapic: kill ioapic PCI driver Jiang Liu
  2014-06-17  5:29 ` [RFC Patch V2 16/16] x86, irq, ACPI: implement ACPI driver to support IOAPIC hotplug Jiang Liu
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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

Introduce acpi_ioapic_registered() to check whether an IOAPIC has already
been registered, it will be used when enabling IOAPIC hotplug.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/x86/include/asm/io_apic.h |    1 +
 arch/x86/kernel/acpi/boot.c    |   11 +++++++++++
 arch/x86/kernel/apic/io_apic.c |   11 +++++++++++
 include/linux/acpi.h           |    1 +
 4 files changed, 24 insertions(+)

diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index ce63cf34c93c..0db2b7037e4b 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -191,6 +191,7 @@ extern void mp_unmap_irq(int irq);
 extern int mp_register_ioapic(int id, u32 address, u32 gsi_base,
 			      struct ioapic_domain_cfg *cfg);
 extern int mp_unregister_ioapic(u32 gsi_base);
+extern int mp_ioapic_registered(u32 gsi_base);
 extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 			    irq_hw_number_t hwirq);
 extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 8a1b25d2aa4c..bab37bd6296a 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -820,6 +820,17 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
 }
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
+int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base)
+{
+	int ret;
+
+	down_write(&acpi_ioapic_rwsem);
+	ret  = mp_ioapic_registered(gsi_base);
+	up_write(&acpi_ioapic_rwsem);
+
+	return ret;
+}
+
 static int __init acpi_parse_sbf(struct acpi_table_header *table)
 {
 	struct acpi_table_boot *sb;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 22bbecb05345..176433c03cf5 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -4001,6 +4001,17 @@ int mp_unregister_ioapic(u32 gsi_base)
 	return 0;
 }
 
+int mp_ioapic_registered(u32 gsi_base)
+{
+	int ioapic;
+
+	for_each_ioapic(ioapic)
+		if (ioapics[ioapic].gsi_config.gsi_base == gsi_base)
+			return 1;
+
+	return 0;
+}
+
 int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
 		     irq_hw_number_t hwirq)
 {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index f478af87f575..7cf20a2e29cc 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -154,6 +154,7 @@ int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr);
 
 int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base);
 int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base);
+int acpi_ioapic_registered(acpi_handle handle, u32 gsi_base);
 void acpi_irq_stats_init(void);
 extern u32 acpi_irq_handled;
 extern u32 acpi_irq_not_handled;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 15/16] pci, ioapic: kill ioapic PCI driver
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (13 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 14/16] x86, irq: introduce helper to check whether an IOAPIC has been registered Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  2014-06-17 16:49   ` Bjorn Helgaas
  2014-06-17  5:29 ` [RFC Patch V2 16/16] x86, irq, ACPI: implement ACPI driver to support IOAPIC hotplug Jiang Liu
  15 siblings, 1 reply; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Bjorn Helgaas,
	Randy Dunlap, Yinghai Lu
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

Originally the ioapic PCI driver is designed to support IOAPIC hotplug,
but it never works because no architecture has implemented required
interface to support it. We plan to reimplement it as an ACPI driver
instead of PCI driver due to:
1) To support IOAPIC hotplug, an IOAPIC unit must have an companion
   ACPI device, but it may or may not be presented in PCI domain.
2) All other PCI devices have dependency on IOAPIC, so we must hot-add
   it before all other PCI devices and hot-remove it after all other
   PCI devices. So we need to explicitly control the order to add/remove
   IOAPIC devices.

So kill the ioapic PCI driver and will reimplement it as an ACPI driver.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/pci/Kconfig  |    7 ---
 drivers/pci/Makefile |    2 -
 drivers/pci/ioapic.c |  121 --------------------------------------------------
 3 files changed, 130 deletions(-)
 delete mode 100644 drivers/pci/ioapic.c

diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 893503fa1782..39866d18004e 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -104,13 +104,6 @@ config PCI_PASID
 
 	  If unsure, say N.
 
-config PCI_IOAPIC
-	bool "PCI IO-APIC hotplug support" if X86
-	depends on PCI
-	depends on ACPI
-	depends on X86_IO_APIC
-	default !X86
-
 config PCI_LABEL
 	def_bool y if (DMI || ACPI)
 	select NLS
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e04fe2d9df3b..73e4af400a5a 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -13,8 +13,6 @@ obj-$(CONFIG_PCI_QUIRKS) += quirks.o
 # Build PCI Express stuff if needed
 obj-$(CONFIG_PCIEPORTBUS) += pcie/
 
-obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
-
 # Build the PCI Hotplug drivers if we were asked to
 obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
 ifdef CONFIG_HOTPLUG_PCI
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
deleted file mode 100644
index 6b2b7dddbbdb..000000000000
--- a/drivers/pci/ioapic.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * IOAPIC/IOxAPIC/IOSAPIC driver
- *
- * Copyright (C) 2009 Fujitsu Limited.
- * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * This driver manages PCI I/O APICs added by hotplug after boot.  We try to
- * claim all I/O APIC PCI devices, but those present at boot were registered
- * when we parsed the ACPI MADT, so we'll fail when we try to re-register
- * them.
- */
-
-#include <linux/pci.h>
-#include <linux/module.h>
-#include <linux/acpi.h>
-#include <linux/slab.h>
-
-struct ioapic {
-	acpi_handle	handle;
-	u32		gsi_base;
-};
-
-static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
-{
-	acpi_handle handle;
-	acpi_status status;
-	unsigned long long gsb;
-	struct ioapic *ioapic;
-	int ret;
-	char *type;
-	struct resource *res;
-
-	handle = ACPI_HANDLE(&dev->dev);
-	if (!handle)
-		return -EINVAL;
-
-	status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
-	if (ACPI_FAILURE(status))
-		return -EINVAL;
-
-	/*
-	 * The previous code in acpiphp evaluated _MAT if _GSB failed, but
-	 * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
-	 */
-
-	ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
-	if (!ioapic)
-		return -ENOMEM;
-
-	ioapic->handle = handle;
-	ioapic->gsi_base = (u32) gsb;
-
-	if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
-		type = "IOAPIC";
-	else
-		type = "IOxAPIC";
-
-	ret = pci_enable_device(dev);
-	if (ret < 0)
-		goto exit_free;
-
-	pci_set_master(dev);
-
-	if (pci_request_region(dev, 0, type))
-		goto exit_disable;
-
-	res = &dev->resource[0];
-	if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
-		goto exit_release;
-
-	pci_set_drvdata(dev, ioapic);
-	dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
-	return 0;
-
-exit_release:
-	pci_release_region(dev, 0);
-exit_disable:
-	pci_disable_device(dev);
-exit_free:
-	kfree(ioapic);
-	return -ENODEV;
-}
-
-static void ioapic_remove(struct pci_dev *dev)
-{
-	struct ioapic *ioapic = pci_get_drvdata(dev);
-
-	acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
-	pci_release_region(dev, 0);
-	pci_disable_device(dev);
-	kfree(ioapic);
-}
-
-
-static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = {
-	{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
-	{ PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, ioapic_devices);
-
-static struct pci_driver ioapic_driver = {
-	.name		= "ioapic",
-	.id_table	= ioapic_devices,
-	.probe		= ioapic_probe,
-	.remove		= ioapic_remove,
-};
-
-static int __init ioapic_init(void)
-{
-	return pci_register_driver(&ioapic_driver);
-}
-module_init(ioapic_init);
-
-MODULE_LICENSE("GPL");
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2 16/16] x86, irq, ACPI: implement ACPI driver to support IOAPIC hotplug
  2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
                   ` (14 preceding siblings ...)
  2014-06-17  5:29 ` [RFC Patch V2 15/16] pci, ioapic: kill ioapic PCI driver Jiang Liu
@ 2014-06-17  5:29 ` Jiang Liu
  15 siblings, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-17  5:29 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
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

Enable support of IOAPIC hotplug by:
1) reintroducing ACPI based IOAPIC driver
2) enhance pci_root driver to hook hotplug events

The ACPI IOAPIC driver is always enabled if system supports all of
ACPI, PCI and IOAPIC.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 drivers/acpi/Kconfig    |    6 ++
 drivers/acpi/Makefile   |    1 +
 drivers/acpi/internal.h |    7 ++
 drivers/acpi/ioapic.c   |  231 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/pci_root.c |    3 +
 5 files changed, 248 insertions(+)
 create mode 100644 drivers/acpi/ioapic.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab686b310100..2d0ed9da6fea 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -292,6 +292,12 @@ config ACPI_HOTPLUG_MEMORY
 	  To compile this driver as a module, choose M here:
 	  the module will be called acpi_memhotplug.
 
+config ACPI_HOTPLUG_IOAPIC
+	bool
+	depends on PCI
+	depends on X86_IO_APIC
+	default y
+
 config ACPI_SBS
 	tristate "Smart Battery System"
 	depends on X86
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index d922febd9164..b85b226a7f49 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_ACPI_PROCESSOR)	+= processor.o
 obj-$(CONFIG_ACPI_CONTAINER)	+= container.o
 obj-$(CONFIG_ACPI_THERMAL)	+= thermal.o
 obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
+obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
 obj-$(CONFIG_ACPI_BATTERY)	+= battery.o
 obj-$(CONFIG_ACPI_SBS)		+= sbshc.o
 obj-$(CONFIG_ACPI_SBS)		+= sbs.o
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 957391306cbf..e8023cd81da3 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -52,6 +52,13 @@ void acpi_memory_hotplug_init(void);
 #else
 static inline void acpi_memory_hotplug_init(void) {}
 #endif
+#ifdef	CONFIG_ACPI_HOTPLUG_IOAPIC
+int acpi_ioapic_add(struct acpi_pci_root *root);
+int acpi_ioapic_remove(struct acpi_pci_root *root);
+#else
+static inline int acpi_ioapic_add(struct acpi_pci_root *root) { return 0; }
+static inline int acpi_ioapic_remove(struct acpi_pci_root *root) { return 0; }
+#endif
 #ifdef CONFIG_X86
 void acpi_cmos_rtc_init(void);
 #else
diff --git a/drivers/acpi/ioapic.c b/drivers/acpi/ioapic.c
new file mode 100644
index 000000000000..3c9442899782
--- /dev/null
+++ b/drivers/acpi/ioapic.c
@@ -0,0 +1,231 @@
+/*
+ * IOAPIC/IOxAPIC/IOSAPIC driver
+ *
+ * Copyright (C) 2009 Fujitsu Limited.
+ * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on original drivers/pci/ioapic.c
+ *	Yinghai Lu <yinghai@kernel.org>
+ *	Jiang Liu <jiang.liu@intel.com>
+ */
+
+/*
+ * This driver manages I/O APICs added by hotplug after boot.
+ * We try to claim all I/O APIC devices, but those present at boot were
+ * registered when we parsed the ACPI MADT, so we'll fail when we try to
+ * re-register them.
+ */
+
+#define pr_fmt(fmt) "ACPI : IOAPIC: " fmt
+
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <acpi/acpi.h>
+
+struct acpi_pci_ioapic {
+	acpi_handle	root_handle;
+	acpi_handle	handle;
+	u32		gsi_base;
+	struct resource	res;
+	struct pci_dev	*pdev;
+	struct list_head list;
+};
+
+static LIST_HEAD(ioapic_list);
+static DEFINE_MUTEX(ioapic_list_lock);
+
+static acpi_status setup_res(struct acpi_resource *acpi_res, void *data)
+{
+	struct resource *res = data;
+	struct acpi_resource_address64 addr;
+	acpi_status status;
+
+	status = acpi_mem_addr_resource_to_address64(acpi_res, &addr);
+	if (!ACPI_SUCCESS(status))
+		return AE_OK;
+
+	if (addr.resource_type != ACPI_MEMORY_RANGE ||
+	    addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+		return AE_OK;
+
+	res->flags = IORESOURCE_MEM;
+	res->start = addr.minimum + addr.translation_offset;
+	res->end = addr.maximum + addr.translation_offset;
+
+	return AE_OK;
+}
+
+static bool acpi_is_ioapic(acpi_handle handle, char **type)
+{
+	acpi_status status;
+	struct acpi_device_info *info;
+	char *hid = NULL;
+	bool match = false;
+
+	if (!acpi_has_method(handle, "_GSB"))
+		return false;
+
+	status = acpi_get_object_info(handle, &info);
+	if (ACPI_SUCCESS(status)) {
+		if (info->valid & ACPI_VALID_HID)
+			hid = info->hardware_id.string;
+		if (hid) {
+			if (strcmp(hid, "ACPI0009") == 0) {
+				*type = "IOxAPIC";
+				match = true;
+			} else if (strcmp(hid, "ACPI000A") == 0) {
+				*type = "IOAPIC";
+				match = true;
+			}
+		}
+		kfree(info);
+	}
+
+	return match;
+}
+
+static acpi_status handle_ioapic_add(acpi_handle handle, u32 lvl,
+				     void *context, void **rv)
+{
+	acpi_status status;
+	unsigned long long gsi_base;
+	struct acpi_pci_ioapic *ioapic;
+	struct pci_dev *dev = NULL;
+	struct resource *res = NULL;
+	char *type = NULL;
+
+	if (!acpi_is_ioapic(handle, &type))
+		return AE_OK;
+
+	mutex_lock(&ioapic_list_lock);
+	list_for_each_entry(ioapic, &ioapic_list, list)
+		if (ioapic->handle == handle) {
+			mutex_unlock(&ioapic_list_lock);
+			return AE_OK;
+		}
+
+	status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsi_base);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_warn(handle, "failed to evaluate _GSB method\n");
+		goto exit;
+	}
+
+	ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
+	if (!ioapic) {
+		pr_err("cannot allocate memory for new IOAPIC\n");
+		goto exit;
+	} else {
+		ioapic->root_handle = (acpi_handle)context;
+		ioapic->handle = handle;
+		ioapic->gsi_base = (u32)gsi_base;
+		ioapic->res.flags = IORESOURCE_UNSET;
+	}
+
+	if (acpi_ioapic_registered(handle, (u32)gsi_base))
+		goto done;
+
+	dev = acpi_get_pci_dev(handle);
+	if (dev && pci_resource_len(dev, 0)) {
+		if (pci_enable_device(dev) < 0)
+			goto exit_put;
+		pci_set_master(dev);
+		if (pci_request_region(dev, 0, type))
+			goto exit_disable;
+		res = &dev->resource[0];
+		ioapic->pdev = dev;
+	} else {
+		pci_dev_put(dev);
+		dev = NULL;
+
+		res = &ioapic->res;
+		acpi_walk_resources(handle, METHOD_NAME__CRS, setup_res, res);
+		if (res->flags == IORESOURCE_UNSET) {
+			acpi_handle_warn(handle, "failed to get resource\n");
+			goto exit_free;
+		} else if (request_resource(&iomem_resource, res)) {
+			acpi_handle_warn(handle, "failed to insert resource\n");
+			goto exit_free;
+		}
+	}
+
+	if (acpi_register_ioapic(handle, res->start, (u32)gsi_base)) {
+		acpi_handle_warn(handle, "failed to register IOAPIC\n");
+		goto exit_release;
+	}
+done:
+	list_add(&ioapic->list, &ioapic_list);
+	mutex_unlock(&ioapic_list_lock);
+
+	if (dev)
+		dev_info(&dev->dev, "%s at %pR, GSI %u\n",
+			 type, res, (u32)gsi_base);
+	else
+		acpi_handle_info(handle, "%s at %pR, GSI %u\n",
+				 type, res, (u32)gsi_base);
+
+	return AE_OK;
+
+exit_release:
+	if (dev)
+		pci_release_region(dev, 0);
+	else
+		release_resource(res);
+exit_disable:
+	if (dev)
+		pci_disable_device(dev);
+exit_put:
+	if (dev)
+		pci_dev_put(dev);
+exit_free:
+	kfree(ioapic);
+exit:
+	mutex_unlock(&ioapic_list_lock);
+	*(acpi_status *)rv = AE_ERROR;
+	return AE_OK;
+}
+
+int acpi_ioapic_add(struct acpi_pci_root *root)
+{
+	acpi_status status, retval = AE_OK;
+
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, root->device->handle,
+				     UINT_MAX, handle_ioapic_add, NULL,
+				     root->device->handle, (void **)&retval);
+
+	return ACPI_SUCCESS(status) && ACPI_SUCCESS(retval) ? 0 : -ENODEV;
+}
+
+int acpi_ioapic_remove(struct acpi_pci_root *root)
+{
+	int retval = 0;
+	struct acpi_pci_ioapic *ioapic, *tmp;
+
+	mutex_lock(&ioapic_list_lock);
+	list_for_each_entry_safe(ioapic, tmp, &ioapic_list, list) {
+		if (root->device->handle != ioapic->root_handle)
+			continue;
+
+		if (acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base))
+			retval = -EBUSY;
+
+		if (ioapic->pdev) {
+			pci_release_region(ioapic->pdev, 0);
+			pci_disable_device(ioapic->pdev);
+			pci_dev_put(ioapic->pdev);
+		} else if (ioapic->res.flags != IORESOURCE_UNSET) {
+			release_resource(&ioapic->res);
+		}
+		list_del(&ioapic->list);
+		kfree(ioapic);
+	}
+	mutex_unlock(&ioapic_list_lock);
+
+	return retval;
+}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index d388f13d48b4..e1223fac65ce 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -600,6 +600,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
 	if (system_state != SYSTEM_BOOTING) {
 		pcibios_resource_survey_bus(root->bus);
 		pci_assign_unassigned_root_bus_resources(root->bus);
+		acpi_ioapic_add(root);
 	}
 
 	pci_lock_rescan_remove();
@@ -620,6 +621,8 @@ static void acpi_pci_root_remove(struct acpi_device *device)
 
 	pci_stop_root_bus(root->bus);
 
+	WARN_ON(acpi_ioapic_remove(root));
+
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [RFC Patch V2 03/16] ACPI, x86/PCI: Move resource_to_addr() to acpi generic
  2014-06-17  5:29 ` [RFC Patch V2 03/16] ACPI, x86/PCI: Move resource_to_addr() to acpi generic Jiang Liu
@ 2014-06-17 16:05   ` Bjorn Helgaas
  2014-06-18 16:30     ` [RFC Patch V2] x86/PCI/ACPI: kill private function resource_to_addr() Jiang Liu
  0 siblings, 1 reply; 26+ messages in thread
From: Bjorn Helgaas @ 2014-06-17 16:05 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Randy Dunlap,
	Yinghai Lu, x86, Len Brown, Konrad Rzeszutek Wilk, Andrew Morton,
	Tony Luck, Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman,
	linux-kernel, linux-pci, linux-acpi

On Mon, Jun 16, 2014 at 11:29 PM, Jiang Liu <jiang.liu@linux.intel.com> wrote:
> From: Yinghai Lu <yinghai@kernel.org>
>
> Rui Wang reported ioapic hot-add does not work on his machine
> that _CRS have MEMORY_FIXED.
> He also proposed to expose resource_to_addr() and use it for ioapic.
>
> We should move it to acpi generic, as ioapi.c current is in

s/ioapi.c/ioapic.c/

> drivers/pci/.
>
> Or should move it to acpica?
>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>

> diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
> index 0bdacc5e26a3..e91deebf0930 100644
> --- a/drivers/acpi/resource.c
> +++ b/drivers/acpi/resource.c
> @@ -424,6 +424,52 @@ void acpi_dev_free_resource_list(struct list_head *list)
>  }
>  EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
>
> +acpi_status acpi_mem_addr_resource_to_address64(struct acpi_resource *resource,
> +                       struct acpi_resource_address64 *addr)
> +{
> +       acpi_status status;
> +       struct acpi_resource_memory24 *memory24;
> +       struct acpi_resource_memory32 *memory32;
> +       struct acpi_resource_fixed_memory32 *fixed_memory32;
> +
> +       memset(addr, 0, sizeof(*addr));
> +       switch (resource->type) {
> +       case ACPI_RESOURCE_TYPE_MEMORY24:
> +               memory24 = &resource->data.memory24;
> +               addr->resource_type = ACPI_MEMORY_RANGE;
> +               addr->minimum = memory24->minimum;
> +               addr->address_length = memory24->address_length;
> +               addr->maximum = addr->minimum + addr->address_length - 1;
> +               return AE_OK;
> +       case ACPI_RESOURCE_TYPE_MEMORY32:
> +               memory32 = &resource->data.memory32;
> +               addr->resource_type = ACPI_MEMORY_RANGE;
> +               addr->minimum = memory32->minimum;
> +               addr->address_length = memory32->address_length;
> +               addr->maximum = addr->minimum + addr->address_length - 1;
> +               return AE_OK;
> +       case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
> +               fixed_memory32 = &resource->data.fixed_memory32;
> +               addr->resource_type = ACPI_MEMORY_RANGE;
> +               addr->minimum = fixed_memory32->address;
> +               addr->address_length = fixed_memory32->address_length;
> +               addr->maximum = addr->minimum + addr->address_length - 1;
> +               return AE_OK;
> +       case ACPI_RESOURCE_TYPE_ADDRESS16:
> +       case ACPI_RESOURCE_TYPE_ADDRESS32:
> +       case ACPI_RESOURCE_TYPE_ADDRESS64:
> +               status = acpi_resource_to_address64(resource, addr);
> +               if (ACPI_SUCCESS(status) &&
> +                   (addr->resource_type == ACPI_MEMORY_RANGE ||
> +                   addr->resource_type == ACPI_IO_RANGE) &&
> +                   addr->address_length > 0) {
> +                       return AE_OK;
> +               }
> +               break;
> +       }
> +       return AE_ERROR;
> +}

There's already very similar-looking code in acpi/resource.c, e.g.,
acpi_dev_resource_address_space() and acpi_dev_resource_memory().  Can
you use that existing code instead of adding new code that's mostly a
duplication?

Bjorn

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RFC Patch V2 08/16] PCI: kill wrong warning message in pcieport driver
  2014-06-17  5:29 ` [RFC Patch V2 08/16] PCI: kill wrong warning message in pcieport driver Jiang Liu
@ 2014-06-17 16:11   ` Bjorn Helgaas
  2014-06-18  5:56     ` [Patch] PCI/portdrv: Remove warning about invalid IRQ Jiang Liu
  0 siblings, 1 reply; 26+ messages in thread
From: Bjorn Helgaas @ 2014-06-17 16:11 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Randy Dunlap,
	Yinghai Lu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

Please pay attention to the existing convention of changelog summaries
(email subject lines), including spacing and capitalization.  "git log
--oneline drivers/pci/pcie" is a good way to see the pattern.  In this
case, you could use something like this:

  PCI/portdrv: Remove warning about invalid IRQ

On Mon, Jun 16, 2014 at 11:29 PM, Jiang Liu <jiang.liu@linux.intel.com> wrote:
> For hot-added PCIe ports, it always generates a warning message on x86
> platforms when binding to pcieport driver as:
>         "device [8086:0e0b] has invalid IRQ; check vendor BIOS".
>
> It's due to that we check pci_dev->irq before actually allocating IRQ
> number for the PCI device:
>         if (!dev->irq && dev->pin) {
>                 dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
>                          "check vendor BIOS\n", dev->vendor, dev->device);
>         }
>         status = pcie_port_device_register(dev);
>                 -->pci_enable_device(dev);
>                         -->pci_enable_device_flags()
>                                 -->do_pci_enable_device()
>                                         -->pcibios_enable_device()
>                                                 -->pcibios_enable_irq()
>
> This warning message isn't generated for PCIe ports present at boot time
> because x86 arch code has called acpi_pci_irq_enable() in pci_acpi_init()
> for each PCI device for safety.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>  drivers/pci/pcie/portdrv_pci.c |    4 ----
>  1 file changed, 4 deletions(-)
>
> diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
> index 0d8fdc48e642..0e35f9670066 100644
> --- a/drivers/pci/pcie/portdrv_pci.c
> +++ b/drivers/pci/pcie/portdrv_pci.c
> @@ -203,10 +203,6 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
>              (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
>                 return -ENODEV;
>
> -       if (!dev->irq && dev->pin) {
> -               dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
> -                        "check vendor BIOS\n", dev->vendor, dev->device);
> -       }

This needs to be rebased to v3.16-rc1.

>         status = pcie_port_device_register(dev);
>         if (status)
>                 return status;
> --
> 1.7.10.4
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RFC Patch V2 15/16] pci, ioapic: kill ioapic PCI driver
  2014-06-17  5:29 ` [RFC Patch V2 15/16] pci, ioapic: kill ioapic PCI driver Jiang Liu
@ 2014-06-17 16:49   ` Bjorn Helgaas
  2014-06-20  8:47     ` Jiang Liu
  2014-06-20  8:58     ` Jiang Liu
  0 siblings, 2 replies; 26+ messages in thread
From: Bjorn Helgaas @ 2014-06-17 16:49 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Randy Dunlap,
	Yinghai Lu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

Your subject lines aren't even consistent in the same patch series.  I suggest:

  PCI: Remove PCI ioapic driver

On Mon, Jun 16, 2014 at 11:29 PM, Jiang Liu <jiang.liu@linux.intel.com> wrote:
> Originally the ioapic PCI driver is designed to support IOAPIC hotplug,
> but it never works because no architecture has implemented required
> interface to support it.

Please be specific about what these "required interfaces" are that no
architecture has implemented.  Otherwise it's hard for me to be
convinced that it's safe to remove this.

> We plan to reimplement it as an ACPI driver
> instead of PCI driver due to:
> 1) To support IOAPIC hotplug, an IOAPIC unit must have an companion
>    ACPI device, but it may or may not be presented in PCI domain.

Please include the reason why there must be a companion ACPI device.

What about hotplugging IOAPICs on non-ACPI systems?  How would that
work?  Will that require totally separate IOAPIC drivers?  I guess
pci/ioapic.c isn't very big and contains mostly ACPI stuff, so maybe
there's nothing worth sharing.

If there must be a companion ACPI device, I guess that implies that we
can't support an IOAPIC on a plug-in card, because there won't be
anything in the ACPI namespace about the card.  Is it possible to have
an IOAPIC on a plug-in card?  I guess I don't know what we could do
with it, since I don't know how we would learn about what is connected
to the IOAPIC input pins.  There's no standard for describing that for
plug-in IOAPICs, is there?

> 2) All other PCI devices have dependency on IOAPIC, so we must hot-add
>    it before all other PCI devices and hot-remove it after all other
>    PCI devices. So we need to explicitly control the order to add/remove
>    IOAPIC devices.
>
> So kill the ioapic PCI driver and will reimplement it as an ACPI driver.
>
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
>  drivers/pci/Kconfig  |    7 ---
>  drivers/pci/Makefile |    2 -
>  drivers/pci/ioapic.c |  121 --------------------------------------------------
>  3 files changed, 130 deletions(-)
>  delete mode 100644 drivers/pci/ioapic.c
>
> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> index 893503fa1782..39866d18004e 100644
> --- a/drivers/pci/Kconfig
> +++ b/drivers/pci/Kconfig
> @@ -104,13 +104,6 @@ config PCI_PASID
>
>           If unsure, say N.
>
> -config PCI_IOAPIC
> -       bool "PCI IO-APIC hotplug support" if X86
> -       depends on PCI
> -       depends on ACPI
> -       depends on X86_IO_APIC
> -       default !X86
> -
>  config PCI_LABEL
>         def_bool y if (DMI || ACPI)
>         select NLS
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index e04fe2d9df3b..73e4af400a5a 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -13,8 +13,6 @@ obj-$(CONFIG_PCI_QUIRKS) += quirks.o
>  # Build PCI Express stuff if needed
>  obj-$(CONFIG_PCIEPORTBUS) += pcie/
>
> -obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
> -
>  # Build the PCI Hotplug drivers if we were asked to
>  obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
>  ifdef CONFIG_HOTPLUG_PCI
> diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
> deleted file mode 100644
> index 6b2b7dddbbdb..000000000000
> --- a/drivers/pci/ioapic.c
> +++ /dev/null
> @@ -1,121 +0,0 @@
> -/*
> - * IOAPIC/IOxAPIC/IOSAPIC driver
> - *
> - * Copyright (C) 2009 Fujitsu Limited.
> - * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License version 2 as
> - * published by the Free Software Foundation.
> - */
> -
> -/*
> - * This driver manages PCI I/O APICs added by hotplug after boot.  We try to
> - * claim all I/O APIC PCI devices, but those present at boot were registered
> - * when we parsed the ACPI MADT, so we'll fail when we try to re-register
> - * them.
> - */
> -
> -#include <linux/pci.h>
> -#include <linux/module.h>
> -#include <linux/acpi.h>
> -#include <linux/slab.h>
> -
> -struct ioapic {
> -       acpi_handle     handle;
> -       u32             gsi_base;
> -};
> -
> -static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
> -{
> -       acpi_handle handle;
> -       acpi_status status;
> -       unsigned long long gsb;
> -       struct ioapic *ioapic;
> -       int ret;
> -       char *type;
> -       struct resource *res;
> -
> -       handle = ACPI_HANDLE(&dev->dev);
> -       if (!handle)
> -               return -EINVAL;
> -
> -       status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
> -       if (ACPI_FAILURE(status))
> -               return -EINVAL;
> -
> -       /*
> -        * The previous code in acpiphp evaluated _MAT if _GSB failed, but
> -        * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
> -        */
> -
> -       ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
> -       if (!ioapic)
> -               return -ENOMEM;
> -
> -       ioapic->handle = handle;
> -       ioapic->gsi_base = (u32) gsb;
> -
> -       if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
> -               type = "IOAPIC";
> -       else
> -               type = "IOxAPIC";
> -
> -       ret = pci_enable_device(dev);
> -       if (ret < 0)
> -               goto exit_free;
> -
> -       pci_set_master(dev);
> -
> -       if (pci_request_region(dev, 0, type))
> -               goto exit_disable;
> -
> -       res = &dev->resource[0];
> -       if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
> -               goto exit_release;
> -
> -       pci_set_drvdata(dev, ioapic);
> -       dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
> -       return 0;
> -
> -exit_release:
> -       pci_release_region(dev, 0);
> -exit_disable:
> -       pci_disable_device(dev);
> -exit_free:
> -       kfree(ioapic);
> -       return -ENODEV;
> -}
> -
> -static void ioapic_remove(struct pci_dev *dev)
> -{
> -       struct ioapic *ioapic = pci_get_drvdata(dev);
> -
> -       acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
> -       pci_release_region(dev, 0);
> -       pci_disable_device(dev);
> -       kfree(ioapic);
> -}
> -
> -
> -static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = {
> -       { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
> -       { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
> -       { }
> -};
> -MODULE_DEVICE_TABLE(pci, ioapic_devices);
> -
> -static struct pci_driver ioapic_driver = {
> -       .name           = "ioapic",
> -       .id_table       = ioapic_devices,
> -       .probe          = ioapic_probe,
> -       .remove         = ioapic_remove,
> -};
> -
> -static int __init ioapic_init(void)
> -{
> -       return pci_register_driver(&ioapic_driver);
> -}
> -module_init(ioapic_init);
> -
> -MODULE_LICENSE("GPL");
> --
> 1.7.10.4
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [Patch] PCI/portdrv: Remove warning about invalid IRQ
  2014-06-17 16:11   ` Bjorn Helgaas
@ 2014-06-18  5:56     ` Jiang Liu
  2014-07-02 21:25       ` Bjorn Helgaas
  0 siblings, 1 reply; 26+ messages in thread
From: Jiang Liu @ 2014-06-18  5:56 UTC (permalink / raw)
  To: Bjorn Helgaas, Ryan Desfosses, Jiang Liu; +Cc: x86, linux-kernel, linux-pci

For hot-added PCIe ports, it always generates a warning message on x86
platforms when binding to portdrv as:
	"device [8086:0e0b] has invalid IRQ; check vendor BIOS".

It's due to that we check pci_dev->irq before actually allocating IRQ
for the PCI device:
	if (!dev->irq && dev->pin) {
		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
			 "check vendor BIOS\n", dev->vendor, dev->device);
	}
 	status = pcie_port_device_register(dev);
		-->pci_enable_device(dev);
			-->pci_enable_device_flags()
				-->do_pci_enable_device()
					-->pcibios_enable_device()
						-->pcibios_enable_irq()

This warning message isn't generated for PCIe ports present at boot time
because x86 arch code has called acpi_pci_irq_enable() in pci_acpi_init()
for each PCI device for safety.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
Hi Bjorn,
	I have rebased it onto v3.16-rc1 and changed the patch title
according to your suggestion.
Thanks!
Gerry
___
 drivers/pci/pcie/portdrv_pci.c |    4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 80887eaa0668..2ccc9b926ea7 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -203,10 +203,6 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
 	     (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
 		return -ENODEV;
 
-	if (!dev->irq && dev->pin) {
-		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; check vendor BIOS\n",
-			 dev->vendor, dev->device);
-	}
 	status = pcie_port_device_register(dev);
 	if (status)
 		return status;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [RFC Patch V2] x86/PCI/ACPI: kill private function resource_to_addr()
  2014-06-17 16:05   ` Bjorn Helgaas
@ 2014-06-18 16:30     ` Jiang Liu
  2014-07-02 22:30       ` Bjorn Helgaas
  0 siblings, 1 reply; 26+ messages in thread
From: Jiang Liu @ 2014-06-18 16:30 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
  Cc: Jiang Liu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi

Replace private function resource_to_addr() to parse ACPI resources for
PCI host bridge with public ACPI resource interfaces.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
Hi Bjorn,
	Thanks for your suggestion. Then how about this version?
Regards!
Gerry
---
 arch/x86/pci/acpi.c |  142 ++++++++++++++++++---------------------------------
 1 file changed, 51 insertions(+), 91 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 91bef49df228..cc0975ef86d1 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -218,114 +218,74 @@ static void teardown_mcfg_map(struct pci_root_info *info)
 }
 #endif
 
-static acpi_status resource_to_addr(struct acpi_resource *resource,
-				    struct acpi_resource_address64 *addr)
-{
-	acpi_status status;
-	struct acpi_resource_memory24 *memory24;
-	struct acpi_resource_memory32 *memory32;
-	struct acpi_resource_fixed_memory32 *fixed_memory32;
-
-	memset(addr, 0, sizeof(*addr));
-	switch (resource->type) {
-	case ACPI_RESOURCE_TYPE_MEMORY24:
-		memory24 = &resource->data.memory24;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = memory24->minimum;
-		addr->address_length = memory24->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_MEMORY32:
-		memory32 = &resource->data.memory32;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = memory32->minimum;
-		addr->address_length = memory32->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-		fixed_memory32 = &resource->data.fixed_memory32;
-		addr->resource_type = ACPI_MEMORY_RANGE;
-		addr->minimum = fixed_memory32->address;
-		addr->address_length = fixed_memory32->address_length;
-		addr->maximum = addr->minimum + addr->address_length - 1;
-		return AE_OK;
-	case ACPI_RESOURCE_TYPE_ADDRESS16:
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		status = acpi_resource_to_address64(resource, addr);
-		if (ACPI_SUCCESS(status) &&
-		    (addr->resource_type == ACPI_MEMORY_RANGE ||
-		    addr->resource_type == ACPI_IO_RANGE) &&
-		    addr->address_length > 0) {
-			return AE_OK;
-		}
-		break;
-	}
-	return AE_ERROR;
-}
-
 static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
+	struct resource r = {
+		.flags = 0
+	};
 
-	status = resource_to_addr(acpi_res, &addr);
-	if (ACPI_SUCCESS(status))
+	if (!acpi_dev_resource_memory(acpi_res, &r) &&
+	    !acpi_dev_resource_address_space(acpi_res, &r))
+		return AE_OK;
+
+	if ((r.flags & (IORESOURCE_IO | IORESOURCE_MEM)) && resource_size(&r))
 		info->res_num++;
+
 	return AE_OK;
 }
 
 static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 {
 	struct pci_root_info *info = data;
-	struct resource *res;
-	struct acpi_resource_address64 addr;
-	acpi_status status;
-	unsigned long flags;
-	u64 start, orig_end, end;
+	struct resource *res = &info->res[info->res_num];
+	u64 translation_offset = 0;
+
+	memset(res, 0, sizeof(*res));
+	if (acpi_dev_resource_memory(acpi_res, res)) {
+		res->flags &= IORESOURCE_MEM | IORESOURCE_IO;
+	} else if (acpi_dev_resource_address_space(acpi_res, res)) {
+		u64 orig_end;
+		struct acpi_resource_address64 addr;
+
+		res->flags &= IORESOURCE_MEM | IORESOURCE_IO;
+		if (res->flags == 0)
+			return AE_OK;
 
-	status = resource_to_addr(acpi_res, &addr);
-	if (!ACPI_SUCCESS(status))
-		return AE_OK;
+		if (ACPI_FAILURE(acpi_resource_to_address64(acpi_res, &addr)))
+			return AE_OK;
 
-	if (addr.resource_type == ACPI_MEMORY_RANGE) {
-		flags = IORESOURCE_MEM;
-		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
-			flags |= IORESOURCE_PREFETCH;
-	} else if (addr.resource_type == ACPI_IO_RANGE) {
-		flags = IORESOURCE_IO;
-	} else
-		return AE_OK;
+		if (addr.resource_type == ACPI_MEMORY_RANGE &&
+		    addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+			res->flags |= IORESOURCE_PREFETCH;
 
-	start = addr.minimum + addr.translation_offset;
-	orig_end = end = addr.maximum + addr.translation_offset;
+		translation_offset = addr.translation_offset;
+		orig_end = res->end;
+		res->start += translation_offset;
+		res->end += translation_offset;
 
-	/* Exclude non-addressable range or non-addressable portion of range */
-	end = min(end, (u64)iomem_resource.end);
-	if (end <= start) {
-		dev_info(&info->bridge->dev,
-			"host bridge window [%#llx-%#llx] "
-			"(ignored, not CPU addressable)\n", start, orig_end);
-		return AE_OK;
-	} else if (orig_end != end) {
-		dev_info(&info->bridge->dev,
-			"host bridge window [%#llx-%#llx] "
-			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
-			start, orig_end, end + 1, orig_end);
+		/* Exclude non-addressable range or non-addressable portion of range */
+		res->end = min(res->end, (u64)iomem_resource.end);
+		if (res->end <= res->start) {
+			dev_info(&info->bridge->dev,
+				"host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
+				 res->start, orig_end);
+			return AE_OK;
+		} else if (orig_end != res->end) {
+			dev_info(&info->bridge->dev,
+				"host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
+				res->start, orig_end, res->end + 1, orig_end);
+		}
 	}
 
-	res = &info->res[info->res_num];
-	res->name = info->name;
-	res->flags = flags;
-	res->start = start;
-	res->end = end;
-	info->res_offset[info->res_num] = addr.translation_offset;
-	info->res_num++;
-
-	if (!pci_use_crs)
-		dev_printk(KERN_DEBUG, &info->bridge->dev,
-			   "host bridge window %pR (ignored)\n", res);
+	if (res->flags && resource_size(res)) {
+		res->name = info->name;
+		info->res_offset[info->res_num] = translation_offset;
+		info->res_num++;
+		if (!pci_use_crs)
+			dev_printk(KERN_DEBUG, &info->bridge->dev,
+				   "host bridge window %pR (ignored)\n", res);
+	}
 
 	return AE_OK;
 }
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [RFC Patch V2 15/16] pci, ioapic: kill ioapic PCI driver
  2014-06-17 16:49   ` Bjorn Helgaas
@ 2014-06-20  8:47     ` Jiang Liu
  2014-06-20  8:58     ` Jiang Liu
  1 sibling, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-20  8:47 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Randy Dunlap,
	Yinghai Lu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi

Hi Bjorn,
	I should pay more attention to commit messages:)
Then how about this description?
----------------------------------------------------------------------
PCI: Remove PCI ioapic driver

To support IOAPIC hotplug on x86 and IA64 platforms, OS needs to figure
out global interrupt source number(GSI) and IOAPIC enumeration ID
through ACPI interfaces. So BIOS must implement an ACPI IOAPIC device
with _GSB/_UID or _MAT method to support IOAPIC hotplug. OS also needs
to figure out base physical address to access IOAPIC registers. OS may
get the base physical address through PCI BARs if IOAPIC device is
visible in PCI domain, otherwise OS may get the address by ACPI _CRS
method if IOAPIC device is hidden from PCI domain by BIOS.

When adding a PCI subtree, we need to add IOAPIC devices before enabling
all other PCI devices because other PCI devices may use the IOAPIC to
allocate PCI interrupts.

So we plan to reimplement IOAPIC driver as an ACPI instead of PCI driver
due to:
1) hot-pluggable IOAPIC devices are always visible in ACPI domain,
   but may or may not be visible in PCI domain.
2) we could explicitly control the order between IOAPIC and other PCI
   devices.

We also have another choice to use a PCI driver to manage IOAPIC device
if it's visible in PCI domain and use an ACPI driver if it's only
visible in ACPI domain. But this solution is a little complex.

It shouldn't cause serious backward compatibility issues because:
1) IOAPIC hotplug is never supported on x86 yet because it hasn't
   implemented the required acpi_register_ioapic() and
   acpi_unregister_ioapic().
2) Currently only ACPI based IOAPIC hotplug is possible on x86 and
   IA64, we don't know other specifications and interfaces to support
   IOAPIC hotplug yet.
3) We will reimplement an ACPI IOAPICtdriver support IOAPIC hotplug.

This change also helps to get rid of the false alarm on all current
Linux distributions:
[    6.952497] ioapic: probe of 0000:00:05.4 failed with error -22
[    6.959542] ioapic: probe of 0000:80:05.4 failed with error -22
---------------------------------------------------------------------------
On 2014/6/18 0:49, Bjorn Helgaas wrote:
> Your subject lines aren't even consistent in the same patch series.  I suggest:
> 
>   PCI: Remove PCI ioapic driver
> 
> On Mon, Jun 16, 2014 at 11:29 PM, Jiang Liu <jiang.liu@linux.intel.com> wrote:
>> Originally the ioapic PCI driver is designed to support IOAPIC hotplug,
>> but it never works because no architecture has implemented required
>> interface to support it.
> 
> Please be specific about what these "required interfaces" are that no
> architecture has implemented.  Otherwise it's hard for me to be
> convinced that it's safe to remove this.
> 
>> We plan to reimplement it as an ACPI driver
>> instead of PCI driver due to:
>> 1) To support IOAPIC hotplug, an IOAPIC unit must have an companion
>>    ACPI device, but it may or may not be presented in PCI domain.
> 
> Please include the reason why there must be a companion ACPI device.
> 
> What about hotplugging IOAPICs on non-ACPI systems?  How would that
> work?  Will that require totally separate IOAPIC drivers?  I guess
> pci/ioapic.c isn't very big and contains mostly ACPI stuff, so maybe
> there's nothing worth sharing.
> 
> If there must be a companion ACPI device, I guess that implies that we
> can't support an IOAPIC on a plug-in card, because there won't be
> anything in the ACPI namespace about the card.  Is it possible to have
> an IOAPIC on a plug-in card?  I guess I don't know what we could do
> with it, since I don't know how we would learn about what is connected
> to the IOAPIC input pins.  There's no standard for describing that for
> plug-in IOAPICs, is there?
> 
>> 2) All other PCI devices have dependency on IOAPIC, so we must hot-add
>>    it before all other PCI devices and hot-remove it after all other
>>    PCI devices. So we need to explicitly control the order to add/remove
>>    IOAPIC devices.
>>
>> So kill the ioapic PCI driver and will reimplement it as an ACPI driver.
>>
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>> ---
>>  drivers/pci/Kconfig  |    7 ---
>>  drivers/pci/Makefile |    2 -
>>  drivers/pci/ioapic.c |  121 --------------------------------------------------
>>  3 files changed, 130 deletions(-)
>>  delete mode 100644 drivers/pci/ioapic.c
>>
>> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
>> index 893503fa1782..39866d18004e 100644
>> --- a/drivers/pci/Kconfig
>> +++ b/drivers/pci/Kconfig
>> @@ -104,13 +104,6 @@ config PCI_PASID
>>
>>           If unsure, say N.
>>
>> -config PCI_IOAPIC
>> -       bool "PCI IO-APIC hotplug support" if X86
>> -       depends on PCI
>> -       depends on ACPI
>> -       depends on X86_IO_APIC
>> -       default !X86
>> -
>>  config PCI_LABEL
>>         def_bool y if (DMI || ACPI)
>>         select NLS
>> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
>> index e04fe2d9df3b..73e4af400a5a 100644
>> --- a/drivers/pci/Makefile
>> +++ b/drivers/pci/Makefile
>> @@ -13,8 +13,6 @@ obj-$(CONFIG_PCI_QUIRKS) += quirks.o
>>  # Build PCI Express stuff if needed
>>  obj-$(CONFIG_PCIEPORTBUS) += pcie/
>>
>> -obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
>> -
>>  # Build the PCI Hotplug drivers if we were asked to
>>  obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
>>  ifdef CONFIG_HOTPLUG_PCI
>> diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
>> deleted file mode 100644
>> index 6b2b7dddbbdb..000000000000
>> --- a/drivers/pci/ioapic.c
>> +++ /dev/null
>> @@ -1,121 +0,0 @@
>> -/*
>> - * IOAPIC/IOxAPIC/IOSAPIC driver
>> - *
>> - * Copyright (C) 2009 Fujitsu Limited.
>> - * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License version 2 as
>> - * published by the Free Software Foundation.
>> - */
>> -
>> -/*
>> - * This driver manages PCI I/O APICs added by hotplug after boot.  We try to
>> - * claim all I/O APIC PCI devices, but those present at boot were registered
>> - * when we parsed the ACPI MADT, so we'll fail when we try to re-register
>> - * them.
>> - */
>> -
>> -#include <linux/pci.h>
>> -#include <linux/module.h>
>> -#include <linux/acpi.h>
>> -#include <linux/slab.h>
>> -
>> -struct ioapic {
>> -       acpi_handle     handle;
>> -       u32             gsi_base;
>> -};
>> -
>> -static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
>> -{
>> -       acpi_handle handle;
>> -       acpi_status status;
>> -       unsigned long long gsb;
>> -       struct ioapic *ioapic;
>> -       int ret;
>> -       char *type;
>> -       struct resource *res;
>> -
>> -       handle = ACPI_HANDLE(&dev->dev);
>> -       if (!handle)
>> -               return -EINVAL;
>> -
>> -       status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
>> -       if (ACPI_FAILURE(status))
>> -               return -EINVAL;
>> -
>> -       /*
>> -        * The previous code in acpiphp evaluated _MAT if _GSB failed, but
>> -        * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
>> -        */
>> -
>> -       ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
>> -       if (!ioapic)
>> -               return -ENOMEM;
>> -
>> -       ioapic->handle = handle;
>> -       ioapic->gsi_base = (u32) gsb;
>> -
>> -       if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
>> -               type = "IOAPIC";
>> -       else
>> -               type = "IOxAPIC";
>> -
>> -       ret = pci_enable_device(dev);
>> -       if (ret < 0)
>> -               goto exit_free;
>> -
>> -       pci_set_master(dev);
>> -
>> -       if (pci_request_region(dev, 0, type))
>> -               goto exit_disable;
>> -
>> -       res = &dev->resource[0];
>> -       if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
>> -               goto exit_release;
>> -
>> -       pci_set_drvdata(dev, ioapic);
>> -       dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
>> -       return 0;
>> -
>> -exit_release:
>> -       pci_release_region(dev, 0);
>> -exit_disable:
>> -       pci_disable_device(dev);
>> -exit_free:
>> -       kfree(ioapic);
>> -       return -ENODEV;
>> -}
>> -
>> -static void ioapic_remove(struct pci_dev *dev)
>> -{
>> -       struct ioapic *ioapic = pci_get_drvdata(dev);
>> -
>> -       acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
>> -       pci_release_region(dev, 0);
>> -       pci_disable_device(dev);
>> -       kfree(ioapic);
>> -}
>> -
>> -
>> -static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = {
>> -       { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
>> -       { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
>> -       { }
>> -};
>> -MODULE_DEVICE_TABLE(pci, ioapic_devices);
>> -
>> -static struct pci_driver ioapic_driver = {
>> -       .name           = "ioapic",
>> -       .id_table       = ioapic_devices,
>> -       .probe          = ioapic_probe,
>> -       .remove         = ioapic_remove,
>> -};
>> -
>> -static int __init ioapic_init(void)
>> -{
>> -       return pci_register_driver(&ioapic_driver);
>> -}
>> -module_init(ioapic_init);
>> -
>> -MODULE_LICENSE("GPL");
>> --
>> 1.7.10.4
>>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RFC Patch V2 15/16] pci, ioapic: kill ioapic PCI driver
  2014-06-17 16:49   ` Bjorn Helgaas
  2014-06-20  8:47     ` Jiang Liu
@ 2014-06-20  8:58     ` Jiang Liu
  1 sibling, 0 replies; 26+ messages in thread
From: Jiang Liu @ 2014-06-20  8:58 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Randy Dunlap,
	Yinghai Lu, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, x86,
	linux-kernel, linux-pci, linux-acpi



On 2014/6/18 0:49, Bjorn Helgaas wrote:
> Your subject lines aren't even consistent in the same patch series.  I suggest:
> 
>   PCI: Remove PCI ioapic driver
> 
> On Mon, Jun 16, 2014 at 11:29 PM, Jiang Liu <jiang.liu@linux.intel.com> wrote:
>> Originally the ioapic PCI driver is designed to support IOAPIC hotplug,
>> but it never works because no architecture has implemented required
>> interface to support it.
> 
> Please be specific about what these "required interfaces" are that no
> architecture has implemented.  Otherwise it's hard for me to be
> convinced that it's safe to remove this.
> 
>> We plan to reimplement it as an ACPI driver
>> instead of PCI driver due to:
>> 1) To support IOAPIC hotplug, an IOAPIC unit must have an companion
>>    ACPI device, but it may or may not be presented in PCI domain.
> 
> Please include the reason why there must be a companion ACPI device.
> 
> What about hotplugging IOAPICs on non-ACPI systems?  How would that
> work?  Will that require totally separate IOAPIC drivers?  I guess
> pci/ioapic.c isn't very big and contains mostly ACPI stuff, so maybe
> there's nothing worth sharing.
> 
> If there must be a companion ACPI device, I guess that implies that we
> can't support an IOAPIC on a plug-in card, because there won't be
> anything in the ACPI namespace about the card.  Is it possible to have
> an IOAPIC on a plug-in card?  I guess I don't know what we could do
> with it, since I don't know how we would learn about what is connected
> to the IOAPIC input pins.  There's no standard for describing that for
> plug-in IOAPICs, is there?
Hi Bjorn,
	As I know, ACPI is the only specification defining interfaces
to support IOAPIC hotplug on x86 and IA64, and seems IOAPIC is only used
on x86 and IA64 too.
	I suspect that there's a real product with IOAPIC on plug-in
card. Correct me if I'm wrong. If there are products with IOAPIC on
plug-in card, it could only be  supported by ACPIPHP because SHPC and
PCIe native hotplug have no  chance to update ACPI data structures.

Thanks!
Gerry

> 
>> 2) All other PCI devices have dependency on IOAPIC, so we must hot-add
>>    it before all other PCI devices and hot-remove it after all other
>>    PCI devices. So we need to explicitly control the order to add/remove
>>    IOAPIC devices.
>>
>> So kill the ioapic PCI driver and will reimplement it as an ACPI driver.
>>
>> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
>> ---
>>  drivers/pci/Kconfig  |    7 ---
>>  drivers/pci/Makefile |    2 -
>>  drivers/pci/ioapic.c |  121 --------------------------------------------------
>>  3 files changed, 130 deletions(-)
>>  delete mode 100644 drivers/pci/ioapic.c
>>
>> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
>> index 893503fa1782..39866d18004e 100644
>> --- a/drivers/pci/Kconfig
>> +++ b/drivers/pci/Kconfig
>> @@ -104,13 +104,6 @@ config PCI_PASID
>>
>>           If unsure, say N.
>>
>> -config PCI_IOAPIC
>> -       bool "PCI IO-APIC hotplug support" if X86
>> -       depends on PCI
>> -       depends on ACPI
>> -       depends on X86_IO_APIC
>> -       default !X86
>> -
>>  config PCI_LABEL
>>         def_bool y if (DMI || ACPI)
>>         select NLS
>> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
>> index e04fe2d9df3b..73e4af400a5a 100644
>> --- a/drivers/pci/Makefile
>> +++ b/drivers/pci/Makefile
>> @@ -13,8 +13,6 @@ obj-$(CONFIG_PCI_QUIRKS) += quirks.o
>>  # Build PCI Express stuff if needed
>>  obj-$(CONFIG_PCIEPORTBUS) += pcie/
>>
>> -obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
>> -
>>  # Build the PCI Hotplug drivers if we were asked to
>>  obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
>>  ifdef CONFIG_HOTPLUG_PCI
>> diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
>> deleted file mode 100644
>> index 6b2b7dddbbdb..000000000000
>> --- a/drivers/pci/ioapic.c
>> +++ /dev/null
>> @@ -1,121 +0,0 @@
>> -/*
>> - * IOAPIC/IOxAPIC/IOSAPIC driver
>> - *
>> - * Copyright (C) 2009 Fujitsu Limited.
>> - * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License version 2 as
>> - * published by the Free Software Foundation.
>> - */
>> -
>> -/*
>> - * This driver manages PCI I/O APICs added by hotplug after boot.  We try to
>> - * claim all I/O APIC PCI devices, but those present at boot were registered
>> - * when we parsed the ACPI MADT, so we'll fail when we try to re-register
>> - * them.
>> - */
>> -
>> -#include <linux/pci.h>
>> -#include <linux/module.h>
>> -#include <linux/acpi.h>
>> -#include <linux/slab.h>
>> -
>> -struct ioapic {
>> -       acpi_handle     handle;
>> -       u32             gsi_base;
>> -};
>> -
>> -static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
>> -{
>> -       acpi_handle handle;
>> -       acpi_status status;
>> -       unsigned long long gsb;
>> -       struct ioapic *ioapic;
>> -       int ret;
>> -       char *type;
>> -       struct resource *res;
>> -
>> -       handle = ACPI_HANDLE(&dev->dev);
>> -       if (!handle)
>> -               return -EINVAL;
>> -
>> -       status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
>> -       if (ACPI_FAILURE(status))
>> -               return -EINVAL;
>> -
>> -       /*
>> -        * The previous code in acpiphp evaluated _MAT if _GSB failed, but
>> -        * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
>> -        */
>> -
>> -       ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
>> -       if (!ioapic)
>> -               return -ENOMEM;
>> -
>> -       ioapic->handle = handle;
>> -       ioapic->gsi_base = (u32) gsb;
>> -
>> -       if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
>> -               type = "IOAPIC";
>> -       else
>> -               type = "IOxAPIC";
>> -
>> -       ret = pci_enable_device(dev);
>> -       if (ret < 0)
>> -               goto exit_free;
>> -
>> -       pci_set_master(dev);
>> -
>> -       if (pci_request_region(dev, 0, type))
>> -               goto exit_disable;
>> -
>> -       res = &dev->resource[0];
>> -       if (acpi_register_ioapic(ioapic->handle, res->start, ioapic->gsi_base))
>> -               goto exit_release;
>> -
>> -       pci_set_drvdata(dev, ioapic);
>> -       dev_info(&dev->dev, "%s at %pR, GSI %u\n", type, res, ioapic->gsi_base);
>> -       return 0;
>> -
>> -exit_release:
>> -       pci_release_region(dev, 0);
>> -exit_disable:
>> -       pci_disable_device(dev);
>> -exit_free:
>> -       kfree(ioapic);
>> -       return -ENODEV;
>> -}
>> -
>> -static void ioapic_remove(struct pci_dev *dev)
>> -{
>> -       struct ioapic *ioapic = pci_get_drvdata(dev);
>> -
>> -       acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
>> -       pci_release_region(dev, 0);
>> -       pci_disable_device(dev);
>> -       kfree(ioapic);
>> -}
>> -
>> -
>> -static DEFINE_PCI_DEVICE_TABLE(ioapic_devices) = {
>> -       { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOAPIC, ~0) },
>> -       { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_PIC_IOXAPIC, ~0) },
>> -       { }
>> -};
>> -MODULE_DEVICE_TABLE(pci, ioapic_devices);
>> -
>> -static struct pci_driver ioapic_driver = {
>> -       .name           = "ioapic",
>> -       .id_table       = ioapic_devices,
>> -       .probe          = ioapic_probe,
>> -       .remove         = ioapic_remove,
>> -};
>> -
>> -static int __init ioapic_init(void)
>> -{
>> -       return pci_register_driver(&ioapic_driver);
>> -}
>> -module_init(ioapic_init);
>> -
>> -MODULE_LICENSE("GPL");
>> --
>> 1.7.10.4
>>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [Patch] PCI/portdrv: Remove warning about invalid IRQ
  2014-06-18  5:56     ` [Patch] PCI/portdrv: Remove warning about invalid IRQ Jiang Liu
@ 2014-07-02 21:25       ` Bjorn Helgaas
  0 siblings, 0 replies; 26+ messages in thread
From: Bjorn Helgaas @ 2014-07-02 21:25 UTC (permalink / raw)
  To: Jiang Liu; +Cc: Ryan Desfosses, x86, linux-kernel, linux-pci

On Wed, Jun 18, 2014 at 01:56:21PM +0800, Jiang Liu wrote:
> For hot-added PCIe ports, it always generates a warning message on x86
> platforms when binding to portdrv as:
> 	"device [8086:0e0b] has invalid IRQ; check vendor BIOS".
> 
> It's due to that we check pci_dev->irq before actually allocating IRQ
> for the PCI device:
> 	if (!dev->irq && dev->pin) {
> 		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
> 			 "check vendor BIOS\n", dev->vendor, dev->device);
> 	}
>  	status = pcie_port_device_register(dev);
> 		-->pci_enable_device(dev);
> 			-->pci_enable_device_flags()
> 				-->do_pci_enable_device()
> 					-->pcibios_enable_device()
> 						-->pcibios_enable_irq()
> 
> This warning message isn't generated for PCIe ports present at boot time
> because x86 arch code has called acpi_pci_irq_enable() in pci_acpi_init()
> for each PCI device for safety.
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>

Applied to pci/misc for v3.17, thanks!

> ---
> Hi Bjorn,
> 	I have rebased it onto v3.16-rc1 and changed the patch title
> according to your suggestion.
> Thanks!
> Gerry
> ___
>  drivers/pci/pcie/portdrv_pci.c |    4 ----
>  1 file changed, 4 deletions(-)
> 
> diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
> index 80887eaa0668..2ccc9b926ea7 100644
> --- a/drivers/pci/pcie/portdrv_pci.c
> +++ b/drivers/pci/pcie/portdrv_pci.c
> @@ -203,10 +203,6 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
>  	     (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
>  		return -ENODEV;
>  
> -	if (!dev->irq && dev->pin) {
> -		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; check vendor BIOS\n",
> -			 dev->vendor, dev->device);
> -	}
>  	status = pcie_port_device_register(dev);
>  	if (status)
>  		return status;
> -- 
> 1.7.10.4
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [RFC Patch V2] x86/PCI/ACPI: kill private function resource_to_addr()
  2014-06-18 16:30     ` [RFC Patch V2] x86/PCI/ACPI: kill private function resource_to_addr() Jiang Liu
@ 2014-07-02 22:30       ` Bjorn Helgaas
  0 siblings, 0 replies; 26+ messages in thread
From: Bjorn Helgaas @ 2014-07-02 22:30 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Benjamin Herrenschmidt, Thomas Gleixner, Grant Likely,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Randy Dunlap,
	Yinghai Lu, x86, Konrad Rzeszutek Wilk, Andrew Morton, Tony Luck,
	Joerg Roedel, Paul Gortmaker, Greg Kroah-Hartman, linux-kernel,
	linux-pci, linux-acpi

On Thu, Jun 19, 2014 at 12:30:59AM +0800, Jiang Liu wrote:
> Replace private function resource_to_addr() to parse ACPI resources for
> PCI host bridge with public ACPI resource interfaces.
> 
> Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
> ---
> Hi Bjorn,
> 	Thanks for your suggestion. Then how about this version?

Looks good to me.  I assume you're merging this along with the rest of the
series.  Let me know if you need me to do anything.

Bjorn

> ---
>  arch/x86/pci/acpi.c |  142 ++++++++++++++++++---------------------------------
>  1 file changed, 51 insertions(+), 91 deletions(-)
> 
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index 91bef49df228..cc0975ef86d1 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -218,114 +218,74 @@ static void teardown_mcfg_map(struct pci_root_info *info)
>  }
>  #endif
>  
> -static acpi_status resource_to_addr(struct acpi_resource *resource,
> -				    struct acpi_resource_address64 *addr)
> -{
> -	acpi_status status;
> -	struct acpi_resource_memory24 *memory24;
> -	struct acpi_resource_memory32 *memory32;
> -	struct acpi_resource_fixed_memory32 *fixed_memory32;
> -
> -	memset(addr, 0, sizeof(*addr));
> -	switch (resource->type) {
> -	case ACPI_RESOURCE_TYPE_MEMORY24:
> -		memory24 = &resource->data.memory24;
> -		addr->resource_type = ACPI_MEMORY_RANGE;
> -		addr->minimum = memory24->minimum;
> -		addr->address_length = memory24->address_length;
> -		addr->maximum = addr->minimum + addr->address_length - 1;
> -		return AE_OK;
> -	case ACPI_RESOURCE_TYPE_MEMORY32:
> -		memory32 = &resource->data.memory32;
> -		addr->resource_type = ACPI_MEMORY_RANGE;
> -		addr->minimum = memory32->minimum;
> -		addr->address_length = memory32->address_length;
> -		addr->maximum = addr->minimum + addr->address_length - 1;
> -		return AE_OK;
> -	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
> -		fixed_memory32 = &resource->data.fixed_memory32;
> -		addr->resource_type = ACPI_MEMORY_RANGE;
> -		addr->minimum = fixed_memory32->address;
> -		addr->address_length = fixed_memory32->address_length;
> -		addr->maximum = addr->minimum + addr->address_length - 1;
> -		return AE_OK;
> -	case ACPI_RESOURCE_TYPE_ADDRESS16:
> -	case ACPI_RESOURCE_TYPE_ADDRESS32:
> -	case ACPI_RESOURCE_TYPE_ADDRESS64:
> -		status = acpi_resource_to_address64(resource, addr);
> -		if (ACPI_SUCCESS(status) &&
> -		    (addr->resource_type == ACPI_MEMORY_RANGE ||
> -		    addr->resource_type == ACPI_IO_RANGE) &&
> -		    addr->address_length > 0) {
> -			return AE_OK;
> -		}
> -		break;
> -	}
> -	return AE_ERROR;
> -}
> -
>  static acpi_status count_resource(struct acpi_resource *acpi_res, void *data)
>  {
>  	struct pci_root_info *info = data;
> -	struct acpi_resource_address64 addr;
> -	acpi_status status;
> +	struct resource r = {
> +		.flags = 0
> +	};
>  
> -	status = resource_to_addr(acpi_res, &addr);
> -	if (ACPI_SUCCESS(status))
> +	if (!acpi_dev_resource_memory(acpi_res, &r) &&
> +	    !acpi_dev_resource_address_space(acpi_res, &r))
> +		return AE_OK;
> +
> +	if ((r.flags & (IORESOURCE_IO | IORESOURCE_MEM)) && resource_size(&r))
>  		info->res_num++;
> +
>  	return AE_OK;
>  }
>  
>  static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
>  {
>  	struct pci_root_info *info = data;
> -	struct resource *res;
> -	struct acpi_resource_address64 addr;
> -	acpi_status status;
> -	unsigned long flags;
> -	u64 start, orig_end, end;
> +	struct resource *res = &info->res[info->res_num];
> +	u64 translation_offset = 0;
> +
> +	memset(res, 0, sizeof(*res));
> +	if (acpi_dev_resource_memory(acpi_res, res)) {
> +		res->flags &= IORESOURCE_MEM | IORESOURCE_IO;
> +	} else if (acpi_dev_resource_address_space(acpi_res, res)) {
> +		u64 orig_end;
> +		struct acpi_resource_address64 addr;
> +
> +		res->flags &= IORESOURCE_MEM | IORESOURCE_IO;
> +		if (res->flags == 0)
> +			return AE_OK;
>  
> -	status = resource_to_addr(acpi_res, &addr);
> -	if (!ACPI_SUCCESS(status))
> -		return AE_OK;
> +		if (ACPI_FAILURE(acpi_resource_to_address64(acpi_res, &addr)))
> +			return AE_OK;
>  
> -	if (addr.resource_type == ACPI_MEMORY_RANGE) {
> -		flags = IORESOURCE_MEM;
> -		if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
> -			flags |= IORESOURCE_PREFETCH;
> -	} else if (addr.resource_type == ACPI_IO_RANGE) {
> -		flags = IORESOURCE_IO;
> -	} else
> -		return AE_OK;
> +		if (addr.resource_type == ACPI_MEMORY_RANGE &&
> +		    addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
> +			res->flags |= IORESOURCE_PREFETCH;
>  
> -	start = addr.minimum + addr.translation_offset;
> -	orig_end = end = addr.maximum + addr.translation_offset;
> +		translation_offset = addr.translation_offset;
> +		orig_end = res->end;
> +		res->start += translation_offset;
> +		res->end += translation_offset;
>  
> -	/* Exclude non-addressable range or non-addressable portion of range */
> -	end = min(end, (u64)iomem_resource.end);
> -	if (end <= start) {
> -		dev_info(&info->bridge->dev,
> -			"host bridge window [%#llx-%#llx] "
> -			"(ignored, not CPU addressable)\n", start, orig_end);
> -		return AE_OK;
> -	} else if (orig_end != end) {
> -		dev_info(&info->bridge->dev,
> -			"host bridge window [%#llx-%#llx] "
> -			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
> -			start, orig_end, end + 1, orig_end);
> +		/* Exclude non-addressable range or non-addressable portion of range */
> +		res->end = min(res->end, (u64)iomem_resource.end);
> +		if (res->end <= res->start) {
> +			dev_info(&info->bridge->dev,
> +				"host bridge window [%#llx-%#llx] (ignored, not CPU addressable)\n",
> +				 res->start, orig_end);
> +			return AE_OK;
> +		} else if (orig_end != res->end) {
> +			dev_info(&info->bridge->dev,
> +				"host bridge window [%#llx-%#llx] ([%#llx-%#llx] ignored, not CPU addressable)\n",
> +				res->start, orig_end, res->end + 1, orig_end);
> +		}
>  	}
>  
> -	res = &info->res[info->res_num];
> -	res->name = info->name;
> -	res->flags = flags;
> -	res->start = start;
> -	res->end = end;
> -	info->res_offset[info->res_num] = addr.translation_offset;
> -	info->res_num++;
> -
> -	if (!pci_use_crs)
> -		dev_printk(KERN_DEBUG, &info->bridge->dev,
> -			   "host bridge window %pR (ignored)\n", res);
> +	if (res->flags && resource_size(res)) {
> +		res->name = info->name;
> +		info->res_offset[info->res_num] = translation_offset;
> +		info->res_num++;
> +		if (!pci_use_crs)
> +			dev_printk(KERN_DEBUG, &info->bridge->dev,
> +				   "host bridge window %pR (ignored)\n", res);
> +	}
>  
>  	return AE_OK;
>  }
> -- 
> 1.7.10.4
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2014-07-02 22:30 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-17  5:29 [RFC Patch V2 00/16] Enable support of IOAPIC hotplug on x86 platforms Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 01/16] x86, irq: Split out alloc_ioapic_save_registers() Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 02/16] x86, ioapic: Find usable ioapic id for 64bit Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 03/16] ACPI, x86/PCI: Move resource_to_addr() to acpi generic Jiang Liu
2014-06-17 16:05   ` Bjorn Helgaas
2014-06-18 16:30     ` [RFC Patch V2] x86/PCI/ACPI: kill private function resource_to_addr() Jiang Liu
2014-07-02 22:30       ` Bjorn Helgaas
2014-06-17  5:29 ` [RFC Patch V2 04/16] ACPI: Make map_mat_entry handle x2apic entry Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 05/16] ACPI: Move acpi_get_cpuid() to separated file Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 06/16] ACPI, ioapic: Add acpi_get_ioapic_id() Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 07/16] x86, irq, ACPI: protect acpi_pci_irq_enable() from reentrance Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 08/16] PCI: kill wrong warning message in pcieport driver Jiang Liu
2014-06-17 16:11   ` Bjorn Helgaas
2014-06-18  5:56     ` [Patch] PCI/portdrv: Remove warning about invalid IRQ Jiang Liu
2014-07-02 21:25       ` Bjorn Helgaas
2014-06-17  5:29 ` [RFC Patch V2 09/16] x86, irq: remove __init marker for functions will be used by IOAPIC hotplug Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 10/16] x86, irq: refine mp_register_ioapic() to prepare for " Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 11/16] x86, irq, ACPI: introduce a rwsem to protect IOAPIC operations from hotplug Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 12/16] x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-addition Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 13/16] x86, irq, ACPI: implement interface to support ACPI based IOAPIC hot-removal Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 14/16] x86, irq: introduce helper to check whether an IOAPIC has been registered Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 15/16] pci, ioapic: kill ioapic PCI driver Jiang Liu
2014-06-17 16:49   ` Bjorn Helgaas
2014-06-20  8:47     ` Jiang Liu
2014-06-20  8:58     ` Jiang Liu
2014-06-17  5:29 ` [RFC Patch V2 16/16] x86, irq, ACPI: implement ACPI driver to support IOAPIC hotplug Jiang Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.