linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH part2 0/6] PCI, x86: pci root bus hotplug support - part2
@ 2012-09-02 21:50 Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 1/6] x86, PCI: Separate pcibios_allocate_bridge_resources() Yinghai Lu
                   ` (5 more replies)
  0 siblings, 6 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-02 21:50 UTC (permalink / raw)
  To: Bjorn Helgaas, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Refactor x86 pci pcibios_allocate related function to take bus as parameter.

So later could use it for root bus add case.

could get from
        git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-root-bus-hotplug-part2

Yinghai Lu (6):
  x86, PCI: Separate pcibios_allocate_bridge_resources()
  x86, PCI: Separate pcibios_allocate_dev_resources()
  x86, PCI: Let pcibios_allocate_bus_resources() take bus instead
  x86, PCI: Separate rom resource claim out
  PCI, x86: Add pcibios_fw_addr_done
  PCI: Claim hw/fw allocated resources in hot add path.

 arch/x86/pci/i386.c |  192 ++++++++++++++++++++++++++++++++++-----------------
 drivers/pci/bus.c   |    2 +
 include/linux/pci.h |    1 +
 3 files changed, 131 insertions(+), 64 deletions(-)

-- 
1.7.7


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

* [PATCH part2 1/6] x86, PCI: Separate pcibios_allocate_bridge_resources()
  2012-09-02 21:50 [PATCH part2 0/6] PCI, x86: pci root bus hotplug support - part2 Yinghai Lu
@ 2012-09-02 21:50 ` Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 2/6] x86, PCI: Separate pcibios_allocate_dev_resources() Yinghai Lu
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-02 21:50 UTC (permalink / raw)
  To: Bjorn Helgaas, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Thus pcibios_allocate_bus_resources() could more simple and clean

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   46 ++++++++++++++++++++++++----------------------
 1 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index dd8ca6f..9800362 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -193,34 +193,36 @@ EXPORT_SYMBOL(pcibios_align_resource);
  *	    as well.
  */
 
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
 {
-	struct pci_bus *bus;
-	struct pci_dev *dev;
 	int idx;
 	struct resource *r;
 
+	for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+		r = &dev->resource[idx];
+		if (!r->flags)
+			continue;
+		if (!r->start || pci_claim_resource(dev, idx) < 0) {
+			/*
+			 * Something is wrong with the region.
+			 * Invalidate the resource to prevent
+			 * child resource allocations in this
+			 * range.
+			 */
+			r->start = r->end = 0;
+			r->flags = 0;
+		}
+	}
+}
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct pci_bus *bus;
+
 	/* Depth-First Search on bus tree */
 	list_for_each_entry(bus, bus_list, node) {
-		if ((dev = bus->self)) {
-			for (idx = PCI_BRIDGE_RESOURCES;
-			    idx < PCI_NUM_RESOURCES; idx++) {
-				r = &dev->resource[idx];
-				if (!r->flags)
-					continue;
-				if (!r->start ||
-				    pci_claim_resource(dev, idx) < 0) {
-					/*
-					 * Something is wrong with the region.
-					 * Invalidate the resource to prevent
-					 * child resource allocations in this
-					 * range.
-					 */
-					r->start = r->end = 0;
-					r->flags = 0;
-				}
-			}
-		}
+		if (bus->self)
+			pcibios_allocate_bridge_resources(bus->self);
 		pcibios_allocate_bus_resources(&bus->children);
 	}
 }
-- 
1.7.7


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

* [PATCH part2 2/6] x86, PCI: Separate pcibios_allocate_dev_resources()
  2012-09-02 21:50 [PATCH part2 0/6] PCI, x86: pci root bus hotplug support - part2 Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 1/6] x86, PCI: Separate pcibios_allocate_bridge_resources() Yinghai Lu
@ 2012-09-02 21:50 ` Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 3/6] x86, PCI: Let pcibios_allocate_bus_resources() take bus instead Yinghai Lu
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-02 21:50 UTC (permalink / raw)
  To: Bjorn Helgaas, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Thus pcibios_allocate_resources() could more simple and clean

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   42 +++++++++++++++++++++++-------------------
 1 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 9800362..5817cf2 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -232,9 +232,8 @@ struct pci_check_idx_range {
 	int end;
 };
 
-static void __init pcibios_allocate_resources(int pass)
+static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 {
-	struct pci_dev *dev = NULL;
 	int idx, disabled, i;
 	u16 command;
 	struct resource *r;
@@ -246,14 +245,13 @@ static void __init pcibios_allocate_resources(int pass)
 #endif
 	};
 
-	for_each_pci_dev(dev) {
-		pci_read_config_word(dev, PCI_COMMAND, &command);
-		for (i = 0; i < ARRAY_SIZE(idx_range); i++)
+	pci_read_config_word(dev, PCI_COMMAND, &command);
+	for (i = 0; i < ARRAY_SIZE(idx_range); i++)
 		for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
 			r = &dev->resource[idx];
-			if (r->parent)		/* Already allocated */
+			if (r->parent)	/* Already allocated */
 				continue;
-			if (!r->start)		/* Address not assigned at all */
+			if (!r->start)	/* Address not assigned at all */
 				continue;
 			if (r->flags & IORESOURCE_IO)
 				disabled = !(command & PCI_COMMAND_IO);
@@ -272,23 +270,29 @@ static void __init pcibios_allocate_resources(int pass)
 				}
 			}
 		}
-		if (!pass) {
-			r = &dev->resource[PCI_ROM_RESOURCE];
-			if (r->flags & IORESOURCE_ROM_ENABLE) {
-				/* Turn the ROM off, leave the resource region,
-				 * but keep it unregistered. */
-				u32 reg;
-				dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
-				r->flags &= ~IORESOURCE_ROM_ENABLE;
-				pci_read_config_dword(dev,
-						dev->rom_base_reg, &reg);
-				pci_write_config_dword(dev, dev->rom_base_reg,
+	if (!pass) {
+		r = &dev->resource[PCI_ROM_RESOURCE];
+		if (r->flags & IORESOURCE_ROM_ENABLE) {
+			/* Turn the ROM off, leave the resource region,
+			 * but keep it unregistered. */
+			u32 reg;
+			dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
+			r->flags &= ~IORESOURCE_ROM_ENABLE;
+			pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+			pci_write_config_dword(dev, dev->rom_base_reg,
 						reg & ~PCI_ROM_ADDRESS_ENABLE);
-			}
 		}
 	}
 }
 
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev = NULL;
+
+	for_each_pci_dev(dev)
+		pcibios_allocate_dev_resources(dev, pass);
+}
+
 static int __init pcibios_assign_resources(void)
 {
 	struct pci_dev *dev = NULL;
-- 
1.7.7


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

* [PATCH part2 3/6] x86, PCI: Let pcibios_allocate_bus_resources() take bus instead
  2012-09-02 21:50 [PATCH part2 0/6] PCI, x86: pci root bus hotplug support - part2 Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 1/6] x86, PCI: Separate pcibios_allocate_bridge_resources() Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 2/6] x86, PCI: Separate pcibios_allocate_dev_resources() Yinghai Lu
@ 2012-09-02 21:50 ` Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 4/6] x86, PCI: Separate rom resource claim out Yinghai Lu
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-02 21:50 UTC (permalink / raw)
  To: Bjorn Helgaas, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Will need call the same code for one single root bus during hot add.
So try to make it take bus instead of bus_list.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   38 +++++++++++++++++++++++++-------------
 1 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 5817cf2..84696ed 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -215,16 +215,15 @@ static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
 	}
 }
 
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+static void __init pcibios_allocate_bus_resources(struct pci_bus *bus)
 {
-	struct pci_bus *bus;
+	struct pci_bus *child;
 
 	/* Depth-First Search on bus tree */
-	list_for_each_entry(bus, bus_list, node) {
-		if (bus->self)
-			pcibios_allocate_bridge_resources(bus->self);
-		pcibios_allocate_bus_resources(&bus->children);
-	}
+	if (bus->self)
+		pcibios_allocate_bridge_resources(bus->self);
+	list_for_each_entry(child, &bus->children, node)
+		pcibios_allocate_bus_resources(child);
 }
 
 struct pci_check_idx_range {
@@ -285,12 +284,18 @@ static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 	}
 }
 
-static void __init pcibios_allocate_resources(int pass)
+static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
 {
-	struct pci_dev *dev = NULL;
+	struct pci_dev *dev;
+	struct pci_bus *child;
 
-	for_each_pci_dev(dev)
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		pcibios_allocate_dev_resources(dev, pass);
+
+		child = dev->subordinate;
+		if (child)
+			pcibios_allocate_resources(child, pass);
+	}
 }
 
 static int __init pcibios_assign_resources(void)
@@ -323,10 +328,17 @@ static int __init pcibios_assign_resources(void)
 
 void __init pcibios_resource_survey(void)
 {
+	struct pci_bus *bus;
+
 	DBG("PCI: Allocating resources\n");
-	pcibios_allocate_bus_resources(&pci_root_buses);
-	pcibios_allocate_resources(0);
-	pcibios_allocate_resources(1);
+
+	list_for_each_entry(bus, &pci_root_buses, node)
+		pcibios_allocate_bus_resources(bus);
+
+	list_for_each_entry(bus, &pci_root_buses, node)
+		pcibios_allocate_resources(bus, 0);
+	list_for_each_entry(bus, &pci_root_buses, node)
+		pcibios_allocate_resources(bus, 1);
 
 	e820_reserve_resources_late();
 	/*
-- 
1.7.7


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

* [PATCH part2 4/6] x86, PCI: Separate rom resource claim out
  2012-09-02 21:50 [PATCH part2 0/6] PCI, x86: pci root bus hotplug support - part2 Yinghai Lu
                   ` (2 preceding siblings ...)
  2012-09-02 21:50 ` [PATCH part2 3/6] x86, PCI: Let pcibios_allocate_bus_resources() take bus instead Yinghai Lu
@ 2012-09-02 21:50 ` Yinghai Lu
  2012-09-17 23:38   ` Bjorn Helgaas
  2012-09-02 21:50 ` [PATCH part2 5/6] PCI, x86: Add pcibios_fw_addr_done Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 6/6] PCI: Claim hw/fw allocated resources in hot add path Yinghai Lu
  5 siblings, 1 reply; 60+ messages in thread
From: Yinghai Lu @ 2012-09-02 21:50 UTC (permalink / raw)
  To: Bjorn Helgaas, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

So could use it with hot-added root bus.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   58 ++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 84696ed..4fdf0b2 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -298,27 +298,51 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
 	}
 }
 
-static int __init pcibios_assign_resources(void)
+static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
 {
-	struct pci_dev *dev = NULL;
 	struct resource *r;
 
-	if (!(pci_probe & PCI_ASSIGN_ROMS)) {
-		/*
-		 * Try to use BIOS settings for ROMs, otherwise let
-		 * pci_assign_unassigned_resources() allocate the new
-		 * addresses.
-		 */
-		for_each_pci_dev(dev) {
-			r = &dev->resource[PCI_ROM_RESOURCE];
-			if (!r->flags || !r->start)
-				continue;
-			if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
-				r->end -= r->start;
-				r->start = 0;
-			}
-		}
+	/*
+	 * Try to use BIOS settings for ROMs, otherwise let
+	 * pci_assign_unassigned_resources() allocate the new
+	 * addresses.
+	 */
+	r = &dev->resource[PCI_ROM_RESOURCE];
+	if (!r->flags || !r->start)
+		return;
+
+	if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
+		r->end -= r->start;
+		r->start = 0;
 	}
+}
+static void __init __pcibios_allocate_rom_resources(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	struct pci_bus *child;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pcibios_allocate_dev_rom_resource(dev);
+
+		child = dev->subordinate;
+		if (child)
+			__pcibios_allocate_rom_resources(child);
+	}
+}
+static void __init pcibios_allocate_rom_resources(struct pci_bus *bus)
+{
+	if (pci_probe & PCI_ASSIGN_ROMS)
+		return;
+
+	__pcibios_allocate_rom_resources(bus);
+}
+
+static int __init pcibios_assign_resources(void)
+{
+	struct pci_bus *bus;
+
+	list_for_each_entry(bus, &pci_root_buses, node)
+		pcibios_allocate_rom_resources(bus);
 
 	pci_assign_unassigned_resources();
 	pcibios_fw_addr_list_del();
-- 
1.7.7


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

* [PATCH part2 5/6] PCI, x86: Add pcibios_fw_addr_done
  2012-09-02 21:50 [PATCH part2 0/6] PCI, x86: pci root bus hotplug support - part2 Yinghai Lu
                   ` (3 preceding siblings ...)
  2012-09-02 21:50 ` [PATCH part2 4/6] x86, PCI: Separate rom resource claim out Yinghai Lu
@ 2012-09-02 21:50 ` Yinghai Lu
  2012-09-02 21:50 ` [PATCH part2 6/6] PCI: Claim hw/fw allocated resources in hot add path Yinghai Lu
  5 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-02 21:50 UTC (permalink / raw)
  To: Bjorn Helgaas, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Use it to skip not needed function after pcibios_fw_addr_list_del is called.

for pci root bus hot add, we will need to use pcibios_allocate_dev_resources(),
and don't want to mess up with fw_addr.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 4fdf0b2..abf2a61 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -51,6 +51,7 @@ struct pcibios_fwaddrmap {
 
 static LIST_HEAD(pcibios_fwaddrmappings);
 static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);
+static bool pcibios_fw_addr_done;
 
 /* Must be called with 'pcibios_fwaddrmap_lock' lock held. */
 static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
@@ -72,6 +73,9 @@ pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr)
 	unsigned long flags;
 	struct pcibios_fwaddrmap *map;
 
+	if (pcibios_fw_addr_done)
+		return;
+
 	spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
 	map = pcibios_fwaddrmap_lookup(dev);
 	if (!map) {
@@ -97,6 +101,9 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
 	struct pcibios_fwaddrmap *map;
 	resource_size_t fw_addr = 0;
 
+	if (pcibios_fw_addr_done)
+		return fw_addr;
+
 	spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
 	map = pcibios_fwaddrmap_lookup(dev);
 	if (map)
@@ -106,7 +113,7 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
 	return fw_addr;
 }
 
-static void pcibios_fw_addr_list_del(void)
+static void __init pcibios_fw_addr_list_del(void)
 {
 	unsigned long flags;
 	struct pcibios_fwaddrmap *entry, *next;
@@ -118,6 +125,7 @@ static void pcibios_fw_addr_list_del(void)
 		kfree(entry);
 	}
 	spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
+	pcibios_fw_addr_done = true;
 }
 
 static int
-- 
1.7.7


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

* [PATCH part2 6/6] PCI: Claim hw/fw allocated resources in hot add path.
  2012-09-02 21:50 [PATCH part2 0/6] PCI, x86: pci root bus hotplug support - part2 Yinghai Lu
                   ` (4 preceding siblings ...)
  2012-09-02 21:50 ` [PATCH part2 5/6] PCI, x86: Add pcibios_fw_addr_done Yinghai Lu
@ 2012-09-02 21:50 ` Yinghai Lu
  2012-09-18  0:12   ` Bjorn Helgaas
  5 siblings, 1 reply; 60+ messages in thread
From: Yinghai Lu @ 2012-09-02 21:50 UTC (permalink / raw)
  To: Bjorn Helgaas, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

During testing remove/rescan root bus 00, found
[  338.142574] bus: 'pci': really_probe: probing driver ata_piix with device 0000:00:01.1
[  338.146788] ata_piix 0000:00:01.1: device not available (can't reserve [io  0x01f0-0x01f7])
[  338.150565] ata_piix: probe of 0000:00:01.1 failed with error -22

because that fixed resource is not claimed from
        arch/x86/pci/i386.c::pcibios_allocate_resources()
that is init path.

Try to claim those resources, so on the remove/rescan will still use old
resources.

It is some kind honoring HW/FW setting in the registers during hot add.
esp root-bus hot add is through acpi, BIOS have chance to set some register
for us.

-v2: add rom resource claiming.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   28 +++++++++++++++++++++-------
 drivers/pci/bus.c   |    2 ++
 include/linux/pci.h |    1 +
 3 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index abf2a61..3cb7d66 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -201,13 +201,15 @@ EXPORT_SYMBOL(pcibios_align_resource);
  *	    as well.
  */
 
-static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
+static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
 {
 	int idx;
 	struct resource *r;
 
 	for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
 		r = &dev->resource[idx];
+		if (r->parent)	/* Already allocated */
+			continue;
 		if (!r->flags)
 			continue;
 		if (!r->start || pci_claim_resource(dev, idx) < 0) {
@@ -223,7 +225,7 @@ static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
 	}
 }
 
-static void __init pcibios_allocate_bus_resources(struct pci_bus *bus)
+static void pcibios_allocate_bus_resources(struct pci_bus *bus)
 {
 	struct pci_bus *child;
 
@@ -239,7 +241,7 @@ struct pci_check_idx_range {
 	int end;
 };
 
-static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
+static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 {
 	int idx, disabled, i;
 	u16 command;
@@ -292,7 +294,7 @@ static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 	}
 }
 
-static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
+static void pcibios_allocate_resources(struct pci_bus *bus, int pass)
 {
 	struct pci_dev *dev;
 	struct pci_bus *child;
@@ -306,7 +308,7 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
 	}
 }
 
-static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
+static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
 {
 	struct resource *r;
 
@@ -324,7 +326,7 @@ static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
 		r->start = 0;
 	}
 }
-static void __init __pcibios_allocate_rom_resources(struct pci_bus *bus)
+static void __pcibios_allocate_rom_resources(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	struct pci_bus *child;
@@ -337,7 +339,7 @@ static void __init __pcibios_allocate_rom_resources(struct pci_bus *bus)
 			__pcibios_allocate_rom_resources(child);
 	}
 }
-static void __init pcibios_allocate_rom_resources(struct pci_bus *bus)
+static void pcibios_allocate_rom_resources(struct pci_bus *bus)
 {
 	if (pci_probe & PCI_ASSIGN_ROMS)
 		return;
@@ -358,6 +360,18 @@ static int __init pcibios_assign_resources(void)
 	return 0;
 }
 
+void pcibios_resource_survey_bus(struct pci_bus *bus)
+{
+	dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n");
+
+	pcibios_allocate_bus_resources(bus);
+
+	pcibios_allocate_resources(bus, 0);
+	pcibios_allocate_resources(bus, 1);
+
+	pcibios_allocate_rom_resources(bus);
+}
+
 void __init pcibios_resource_survey(void)
 {
 	struct pci_bus *bus;
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 4b0970b..2882d01 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -154,6 +154,8 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 	return ret;
 }
 
+void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
+
 /**
  * pci_bus_add_device - add a single device
  * @dev: device to add
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1b460e1..29a4704 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -676,6 +676,7 @@ extern struct list_head pci_root_buses;	/* list of all known PCI buses */
 /* Some device drivers need know if pci is initiated */
 extern int no_pci_devices(void);
 
+void pcibios_resource_survey_bus(struct pci_bus *bus);
 void pcibios_fixup_bus(struct pci_bus *);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
 /* Architecture specific versions may override this (weak) */
-- 
1.7.7


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

* Re: [PATCH part2 4/6] x86, PCI: Separate rom resource claim out
  2012-09-02 21:50 ` [PATCH part2 4/6] x86, PCI: Separate rom resource claim out Yinghai Lu
@ 2012-09-17 23:38   ` Bjorn Helgaas
  2012-09-18  3:18     ` Yinghai Lu
  0 siblings, 1 reply; 60+ messages in thread
From: Bjorn Helgaas @ 2012-09-17 23:38 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Taku Izumi, Jiang Liu, x86, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-acpi

On Sun, Sep 2, 2012 at 3:50 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> So could use it with hot-added root bus.
>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> ---
>  arch/x86/pci/i386.c |   58 ++++++++++++++++++++++++++++++++++++---------------
>  1 files changed, 41 insertions(+), 17 deletions(-)
>
> diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
> index 84696ed..4fdf0b2 100644
> --- a/arch/x86/pci/i386.c
> +++ b/arch/x86/pci/i386.c
> @@ -298,27 +298,51 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
>         }
>  }
>
> -static int __init pcibios_assign_resources(void)
> +static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
>  {
> -       struct pci_dev *dev = NULL;
>         struct resource *r;
>
> -       if (!(pci_probe & PCI_ASSIGN_ROMS)) {
> -               /*
> -                * Try to use BIOS settings for ROMs, otherwise let
> -                * pci_assign_unassigned_resources() allocate the new
> -                * addresses.
> -                */
> -               for_each_pci_dev(dev) {
> -                       r = &dev->resource[PCI_ROM_RESOURCE];
> -                       if (!r->flags || !r->start)
> -                               continue;
> -                       if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
> -                               r->end -= r->start;
> -                               r->start = 0;
> -                       }
> -               }
> +       /*
> +        * Try to use BIOS settings for ROMs, otherwise let
> +        * pci_assign_unassigned_resources() allocate the new
> +        * addresses.
> +        */
> +       r = &dev->resource[PCI_ROM_RESOURCE];
> +       if (!r->flags || !r->start)
> +               return;
> +
> +       if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
> +               r->end -= r->start;
> +               r->start = 0;
>         }
> +}
> +static void __init __pcibios_allocate_rom_resources(struct pci_bus *bus)
> +{
> +       struct pci_dev *dev;
> +       struct pci_bus *child;
> +
> +       list_for_each_entry(dev, &bus->devices, bus_list) {
> +               pcibios_allocate_dev_rom_resource(dev);
> +
> +               child = dev->subordinate;
> +               if (child)
> +                       __pcibios_allocate_rom_resources(child);

I really dislike the "__" prefix on the function names.  It seems
pointless to add another function and the "__" when all you need is a
test of PCI_ASSIGN_ROMS.  Also, it makes the structure of
__pcibios_allocate_rom_resources() different from
pcibios_allocate_resources() when they should be exactly the same.

What if you made pcibios_assign_resources() look like this:

    if (!!(pci_probe & PCI_ASSIGN_ROMS)) {
        list_for_each_entry(bus, &pci_root_buses, node)
            pcibios_allocate_rom_resources(bus);
    }

Then I don't think you'd need the extra function.

> +       }
> +}
> +static void __init pcibios_allocate_rom_resources(struct pci_bus *bus)
> +{
> +       if (pci_probe & PCI_ASSIGN_ROMS)
> +               return;
> +
> +       __pcibios_allocate_rom_resources(bus);
> +}
> +
> +static int __init pcibios_assign_resources(void)
> +{
> +       struct pci_bus *bus;
> +
> +       list_for_each_entry(bus, &pci_root_buses, node)
> +               pcibios_allocate_rom_resources(bus);
>
>         pci_assign_unassigned_resources();
>         pcibios_fw_addr_list_del();
> --
> 1.7.7
>

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

* Re: [PATCH part2 6/6] PCI: Claim hw/fw allocated resources in hot add path.
  2012-09-02 21:50 ` [PATCH part2 6/6] PCI: Claim hw/fw allocated resources in hot add path Yinghai Lu
@ 2012-09-18  0:12   ` Bjorn Helgaas
  2012-09-18  4:44     ` Yinghai Lu
  0 siblings, 1 reply; 60+ messages in thread
From: Bjorn Helgaas @ 2012-09-18  0:12 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Taku Izumi, Jiang Liu, x86, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-acpi

On Sun, Sep 2, 2012 at 3:50 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> During testing remove/rescan root bus 00, found
> [  338.142574] bus: 'pci': really_probe: probing driver ata_piix with device 0000:00:01.1
> [  338.146788] ata_piix 0000:00:01.1: device not available (can't reserve [io  0x01f0-0x01f7])
> [  338.150565] ata_piix: probe of 0000:00:01.1 failed with error -22
>
> because that fixed resource is not claimed from
>         arch/x86/pci/i386.c::pcibios_allocate_resources()
> that is init path.
>
> Try to claim those resources, so on the remove/rescan will still use old
> resources.
>
> It is some kind honoring HW/FW setting in the registers during hot add.
> esp root-bus hot add is through acpi, BIOS have chance to set some register
> for us.
>
> -v2: add rom resource claiming.
>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> ---
>  arch/x86/pci/i386.c |   28 +++++++++++++++++++++-------
>  drivers/pci/bus.c   |    2 ++
>  include/linux/pci.h |    1 +
>  3 files changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
> index abf2a61..3cb7d66 100644
> --- a/arch/x86/pci/i386.c
> +++ b/arch/x86/pci/i386.c
> @@ -201,13 +201,15 @@ EXPORT_SYMBOL(pcibios_align_resource);
>   *         as well.
>   */
>
> -static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
> +static void pcibios_allocate_bridge_resources(struct pci_dev *dev)

This patch has a little too much going on at the same time.  Can you
split the __init removal into its own patch so we can focus on what's
left by itself?

>  {
>         int idx;
>         struct resource *r;
>
>         for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
>                 r = &dev->resource[idx];
> +               if (r->parent)  /* Already allocated */
> +                       continue;

This is also a potentially interesting change that maybe should be in
its own patch.

>                 if (!r->flags)
>                         continue;
>                 if (!r->start || pci_claim_resource(dev, idx) < 0) {
> @@ -223,7 +225,7 @@ static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
>         }
>  }
>
> -static void __init pcibios_allocate_bus_resources(struct pci_bus *bus)
> +static void pcibios_allocate_bus_resources(struct pci_bus *bus)
>  {
>         struct pci_bus *child;
>
> @@ -239,7 +241,7 @@ struct pci_check_idx_range {
>         int end;
>  };
>
> -static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
> +static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
>  {
>         int idx, disabled, i;
>         u16 command;
> @@ -292,7 +294,7 @@ static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
>         }
>  }
>
> -static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
> +static void pcibios_allocate_resources(struct pci_bus *bus, int pass)
>  {
>         struct pci_dev *dev;
>         struct pci_bus *child;
> @@ -306,7 +308,7 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
>         }
>  }
>
> -static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
> +static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
>  {
>         struct resource *r;
>
> @@ -324,7 +326,7 @@ static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
>                 r->start = 0;
>         }
>  }
> -static void __init __pcibios_allocate_rom_resources(struct pci_bus *bus)
> +static void __pcibios_allocate_rom_resources(struct pci_bus *bus)
>  {
>         struct pci_dev *dev;
>         struct pci_bus *child;
> @@ -337,7 +339,7 @@ static void __init __pcibios_allocate_rom_resources(struct pci_bus *bus)
>                         __pcibios_allocate_rom_resources(child);
>         }
>  }
> -static void __init pcibios_allocate_rom_resources(struct pci_bus *bus)
> +static void pcibios_allocate_rom_resources(struct pci_bus *bus)
>  {
>         if (pci_probe & PCI_ASSIGN_ROMS)
>                 return;
> @@ -358,6 +360,18 @@ static int __init pcibios_assign_resources(void)
>         return 0;
>  }
>
> +void pcibios_resource_survey_bus(struct pci_bus *bus)
> +{
> +       dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n");
> +
> +       pcibios_allocate_bus_resources(bus);
> +
> +       pcibios_allocate_resources(bus, 0);
> +       pcibios_allocate_resources(bus, 1);
> +
> +       pcibios_allocate_rom_resources(bus);
> +}
> +
>  void __init pcibios_resource_survey(void)

I wish pcibios_resource_survey() could look like this:

    void __init pcibios_resource_survey(void)
    {
        list_for_each_entry(bus, &pci_root_buses, node)
            pcibios_resource_survey_bus(bus)

        e820_reserve_resources_late();
        ...

but maybe there's a reason why pcibios_allocate_rom_resources() really
has to be in the pcibios_assign_resources() fs_initcall rather than in
pcibios_resource_survey().

>  {
>         struct pci_bus *bus;
> diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
> index 4b0970b..2882d01 100644
> --- a/drivers/pci/bus.c
> +++ b/drivers/pci/bus.c
> @@ -154,6 +154,8 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
>         return ret;
>  }
>
> +void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
> +
>  /**
>   * pci_bus_add_device - add a single device
>   * @dev: device to add
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 1b460e1..29a4704 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -676,6 +676,7 @@ extern struct list_head pci_root_buses;     /* list of all known PCI buses */
>  /* Some device drivers need know if pci is initiated */
>  extern int no_pci_devices(void);
>
> +void pcibios_resource_survey_bus(struct pci_bus *bus);
>  void pcibios_fixup_bus(struct pci_bus *);
>  int __must_check pcibios_enable_device(struct pci_dev *, int mask);
>  /* Architecture specific versions may override this (weak) */
> --
> 1.7.7
>

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

* Re: [PATCH part2 4/6] x86, PCI: Separate rom resource claim out
  2012-09-17 23:38   ` Bjorn Helgaas
@ 2012-09-18  3:18     ` Yinghai Lu
  0 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-18  3:18 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Taku Izumi, Jiang Liu, x86, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-acpi

On Mon, Sep 17, 2012 at 4:38 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Sun, Sep 2, 2012 at 3:50 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>> So could use it with hot-added root bus.
>>
>> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
>> ---
>>  arch/x86/pci/i386.c |   58 ++++++++++++++++++++++++++++++++++++---------------
>>  1 files changed, 41 insertions(+), 17 deletions(-)
>>
>> diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
>> index 84696ed..4fdf0b2 100644
>> --- a/arch/x86/pci/i386.c
>> +++ b/arch/x86/pci/i386.c
>> @@ -298,27 +298,51 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
>>         }
>>  }
>>
>> +static void __init __pcibios_allocate_rom_resources(struct pci_bus *bus)
>> +{
>> +       struct pci_dev *dev;
>> +       struct pci_bus *child;
>> +
>> +       list_for_each_entry(dev, &bus->devices, bus_list) {
>> +               pcibios_allocate_dev_rom_resource(dev);
>> +
>> +               child = dev->subordinate;
>> +               if (child)
>> +                       __pcibios_allocate_rom_resources(child);
>
> I really dislike the "__" prefix on the function names.  It seems
> pointless to add another function and the "__" when all you need is a
> test of PCI_ASSIGN_ROMS.  Also, it makes the structure of
> __pcibios_allocate_rom_resources() different from
> pcibios_allocate_resources() when they should be exactly the same.
>
> What if you made pcibios_assign_resources() look like this:
>
>     if (!!(pci_probe & PCI_ASSIGN_ROMS)) {
>         list_for_each_entry(bus, &pci_root_buses, node)
>             pcibios_allocate_rom_resources(bus);
>     }
>
> Then I don't think you'd need the extra function.

ok, will just move pci_probe checking back to
pcibios_allocate_rom_resources directly.

Yinghai

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

* Re: [PATCH part2 6/6] PCI: Claim hw/fw allocated resources in hot add path.
  2012-09-18  0:12   ` Bjorn Helgaas
@ 2012-09-18  4:44     ` Yinghai Lu
  2012-09-18  5:36       ` Yinghai Lu
  0 siblings, 1 reply; 60+ messages in thread
From: Yinghai Lu @ 2012-09-18  4:44 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Taku Izumi, Jiang Liu, x86, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-acpi

On Mon, Sep 17, 2012 at 5:12 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Sun, Sep 2, 2012 at 3:50 PM, Yinghai Lu <yinghai@kernel.org> wrote:

>> -static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
>> +static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
>
> This patch has a little too much going on at the same time.  Can you
> split the __init removal into its own patch so we can focus on what's
> left by itself?

ok.

>
>>  {
>>         int idx;
>>         struct resource *r;
>>
>>         for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
>>                 r = &dev->resource[idx];
>> +               if (r->parent)  /* Already allocated */
>> +                       continue;
>
> This is also a potentially interesting change that maybe should be in
> its own patch.

oh, we don't need that extra checking anymore. because support
removing non-root bus is dropped.

>> +void pcibios_resource_survey_bus(struct pci_bus *bus)
>> +{
>> +       dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n");
>> +
>> +       pcibios_allocate_bus_resources(bus);
>> +
>> +       pcibios_allocate_resources(bus, 0);
>> +       pcibios_allocate_resources(bus, 1);
>> +
>> +       pcibios_allocate_rom_resources(bus);
>> +}
>> +
>>  void __init pcibios_resource_survey(void)
>
> I wish pcibios_resource_survey() could look like this:
>
>     void __init pcibios_resource_survey(void)
>     {
>         list_for_each_entry(bus, &pci_root_buses, node)
>             pcibios_resource_survey_bus(bus)
>
>         e820_reserve_resources_late();
>         ...
>
> but maybe there's a reason why pcibios_allocate_rom_resources() really
> has to be in the pcibios_assign_resources() fs_initcall rather than in
> pcibios_resource_survey().

that should be another patch later.

Thanks

Yinghai

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

* Re: [PATCH part2 6/6] PCI: Claim hw/fw allocated resources in hot add path.
  2012-09-18  4:44     ` Yinghai Lu
@ 2012-09-18  5:36       ` Yinghai Lu
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
  0 siblings, 1 reply; 60+ messages in thread
From: Yinghai Lu @ 2012-09-18  5:36 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Taku Izumi, Jiang Liu, x86, Andrew Morton, Linus Torvalds,
	Greg Kroah-Hartman, linux-pci, linux-kernel, linux-acpi

On Mon, Sep 17, 2012 at 9:44 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Mon, Sep 17, 2012 at 5:12 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
>> On Sun, Sep 2, 2012 at 3:50 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>
>>> -static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
>>> +static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
>>
>> This patch has a little too much going on at the same time.  Can you
>> split the __init removal into its own patch so we can focus on what's
>> left by itself?
>
> ok.
>
>>
>>>  {
>>>         int idx;
>>>         struct resource *r;
>>>
>>>         for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
>>>                 r = &dev->resource[idx];
>>> +               if (r->parent)  /* Already allocated */
>>> +                       continue;
>>
>> This is also a potentially interesting change that maybe should be in
>> its own patch.
>
> oh, we don't need that extra checking anymore. because support
> removing non-root bus is dropped.

I updated for-pci-root-bus-hotplug-part2.

http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-root-bus-hotplug-part2

Thanks

Yinghai

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

* [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support
  2012-09-18  5:36       ` Yinghai Lu
@ 2012-09-19 18:54         ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 01/40] PCI: fix default vga ref_count Yinghai Lu
                             ` (40 more replies)
  0 siblings, 41 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

It supports pci root bus removal with
	echo "PCI0 3" > /sys/kernel/debug/acpi/sci_notify

add with
	echo "PCI0 0" > /sys/kernel/debug/acpi/sci_notify

based on pci/next

We need to separate pci root bus add from acpiphp. so user could only root bus
hotplug and pciehp that will make system fw simple.
Also later CONFIG_HOTPLUG will be removed, so pci root bus hotplug will be
enabled by default and user still need select acpiphp and pciehp for normal
pci device hotplug support.

could get from
        git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-root-bus-hotplug

-v6: do not depend on busn-alloc anymore.

part1: cleanup for pci/next
[PATCH 01/40] PCI: fix default vga ref_count
[PATCH 02/40] PCI, x86: clear initial value for root info resources
[PATCH 03/40] PCI, ia64: clear initial value for root info resources
[PATCH 04/40] PCI, acpiphp: Add is_hotplug_bridge detection
[PATCH 05/40] PCI: Add root bus children dev's res to fail list
[PATCH 06/40] PCI: Split out stop_bus_device and remove_bus_dev

part2: reserve BIOS allocated resource for hotadd root bus
[PATCH 07/40] x86, PCI: Separate pcibios_allocate_bridge_resources()
[PATCH 08/40] x86, PCI: Separate pcibios_allocate_dev_resources()
[PATCH 09/40] x86, PCI: Let pcibios_allocate_bus_resources() take us instead
[PATCH 10/40] x86, PCI: Separate rom resource claim out
[PATCH 11/40] PCI, x86: Add pcibios_fw_addr_done
[PATCH 12/40] PCI, x86: Remove __init for hw/fw allocated functions
[PATCH 13/40] PCI: Claim hw/fw allocated resources in hot add path.

part3: pci_assign_unsissigned_bus_resources() for root bus add.
[PATCH 14/40] PCI: Separate out pci_assign_unassigned_bus_resources()
[PATCH 15/40] PCI: Move back pci_rescan_bus() to probe.c
[PATCH 16/40] PCI: pci_bus_size_bridges() should not size own bridge
[PATCH 17/40] PCI: Use __pci_bus_size_bridges() directly in pci_assign_unassigned_bus_resources()
[PATCH 18/40] PCI: Rescan bus using callback method too
[PATCH 19/40] PCI, sysfs: Clean up rescan/remove with schedule_callback

part4: Separate root bus add from acpiphp and add removal support.
[PATCH 20/40] PCI: Fix a device reference count leakage issue in
[PATCH 21/40] PCI: Add pci_stop_and_remove_root_bus()
[PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host
[PATCH 23/40] PCI, ACPI: Pass device instead of handle when config
[PATCH 24/40] PCI, acpi: Update acpi_pci_driver add/remove interface
[PATCH 25/40] PCI, ACPI: Make acpi_pci_root_remove remove pci root
[PATCH 26/40] PCI, ACPI: del root bus prt
[PATCH 27/40] ACPI: acpi_bus_trim to support two steps.
[PATCH 28/40] PCI, ACPI: Add pci_root_hp hot removal notification
[PATCH 29/40] PCI, ACPI: Add alloc_acpi_hp_work()
[PATCH 30/40] PCI, acpiphp: Use acpi_hp_work
[PATCH 31/40] PCI, pci_root_hp: Use acpi_hp_work
[PATCH 32/40] PCI, ACPI: Make kacpi_hotplug_wq static

part5: add/remove calling for acpi_pci_drivers.
[PATCH 33/40] ACPI, PCI: Use normal list for struct acpi_pci_driver
[PATCH 34/40] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging
[PATCH 35/40] ACPI, PCI: Protect global lists in
[PATCH 36/40] PCI: Set dev_node early for pci_dev
[PATCH 37/40] PCI, x86: Move pci_enable_bridges() down
[PATCH 38/40] ACPI, PCI: Skip extra pci_enable_bridges for non
[PATCH 39/40] PCI, acpiphp: Don't ailout even no slots found yet.

part6: acpi add/remove simulation
[PATCH 40/40] ACPI: Enable SCI_EMULATE to manually simulate physical

 arch/ia64/pci/pci.c                |    3 +-
 arch/x86/pci/acpi.c                |    3 +-
 arch/x86/pci/i386.c                |  185 ++++++++++++++++--------
 drivers/acpi/Kconfig               |   10 ++
 drivers/acpi/Makefile              |    2 +
 drivers/acpi/osl.c                 |   24 +++-
 drivers/acpi/pci_root.c            |  123 ++++++++++------
 drivers/acpi/pci_root_hp.c         |  278 ++++++++++++++++++++++++++++++++++++
 drivers/acpi/pci_slot.c            |   12 +-
 drivers/acpi/scan.c                |    5 +-
 drivers/acpi/sci_emu.c             |  145 +++++++++++++++++++
 drivers/gpu/vga/vgaarb.c           |   14 ++-
 drivers/pci/bus.c                  |    2 +
 drivers/pci/hotplug/acpiphp.h      |    1 -
 drivers/pci/hotplug/acpiphp_core.c |   23 +---
 drivers/pci/hotplug/acpiphp_glue.c |  165 +++++++--------------
 drivers/pci/pci-sysfs.c            |   41 ++++--
 drivers/pci/probe.c                |   26 ++++-
 drivers/pci/remove.c               |   87 +++++++++--
 drivers/pci/search.c               |   10 +-
 drivers/pci/setup-bus.c            |   54 +++-----
 include/acpi/acpi_bus.h            |    1 +
 include/acpi/acpiosxf.h            |    9 +-
 include/linux/acpi.h               |    6 +-
 include/linux/pci.h                |    5 +
 25 files changed, 899 insertions(+), 335 deletions(-)
 create mode 100644 drivers/acpi/pci_root_hp.c
 create mode 100644 drivers/acpi/sci_emu.c

-- 
1.7.7


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

* [PATCH 01/40] PCI: fix default vga ref_count
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-21 20:52             ` Bjorn Helgaas
  2012-09-23 15:25             ` Jiang Liu
  2012-09-19 18:54           ` [PATCH 02/40] PCI, x86: clear initial value for root info resources Yinghai Lu
                             ` (39 subsequent siblings)
  40 siblings, 2 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu, Dave Airlie, Julia Lawall,
	Matthew Garrett

when __ARCH_HAS_VGA_DEFAULT_DEVICE is not defined, aka EFIFB is not used,
for static path, vga_default setting is through vga_arbiter_add_pci_device.
and later x86 pci_fixup_video, will skip setting again.
- subsys_initcall(vga_arb_device_init) come first to call vga_arbiter_add_pci_device. It will call pci_get_dev to hold one reference.

for hotplug add path, even vga_arbiter_add_pci_device is called via notifier,
but it will check VGA_RSRC_LEGACY_MASK that is not set for hotplug path.
So x86 pci_fixup_video will take over to call vga_set_default_device().
It will not hold one refrence.

Later for hotplug remove path, vga_arbiter_del_pci_device that does not check
VGA_RSRC_LEGACY_MASK will call put_device and it will cause ref_count to
decrease extra. that will have that pci device get deleted early wrongly.

Need to make get/put balance for both cases.

-v2: According to Bjorn, update vga_set_default_device instead...

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: x86@kernel.org
Cc: Dave Airlie <airlied@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Julia Lawall <julia@diku.dk>
Cc: Matthew Garrett <mjg@redhat.com>
---
 drivers/gpu/vga/vgaarb.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index b6852b7..0888951e 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -141,6 +141,12 @@ EXPORT_SYMBOL_GPL(vga_default_device);
 
 void vga_set_default_device(struct pci_dev *pdev)
 {
+	if (vga_default)
+		pci_dev_put(vga_default);
+
+	if (pdev)
+		pdev = pci_dev_get(pdev);
+
 	vga_default = pdev;
 }
 #endif
@@ -577,7 +583,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
 #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 	if (vga_default == NULL &&
 	    ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK))
-		vga_default = pci_dev_get(pdev);
+		vga_set_default_device(pdev);
 #endif
 
 	vga_arbiter_check_bridge_sharing(vgadev);
@@ -613,10 +619,8 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
 	}
 
 #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
-	if (vga_default == pdev) {
-		pci_dev_put(vga_default);
-		vga_default = NULL;
-	}
+	if (vga_default == pdev)
+		vga_set_default_device(NULL);
 #endif
 
 	if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
-- 
1.7.7


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

* [PATCH 02/40] PCI, x86: clear initial value for root info resources
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
  2012-09-19 18:54           ` [PATCH 01/40] PCI: fix default vga ref_count Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 03/40] PCI, ia64: " Yinghai Lu
                             ` (38 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Found one system one root bus hot remove get panic.
Panic happens when try to release hostbridge resource.

It turns out that resource get reject during put into resource tree
because of conflicts.
Also that resource parent pointer have random value.

That invalid value cause it pass through check __release_pci_root_info
and panic in release_resource.

Try to use kzalloc instead.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: x86@kernel.org
---
 arch/x86/pci/acpi.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 505acdd..192397c 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -305,7 +305,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 	res->flags = flags;
 	res->start = start;
 	res->end = end;
-	res->child = NULL;
 
 	if (!pci_use_crs) {
 		dev_printk(KERN_DEBUG, &info->bridge->dev,
@@ -434,7 +433,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 
 	size = sizeof(*info->res) * info->res_num;
 	info->res_num = 0;
-	info->res = kmalloc(size, GFP_KERNEL);
+	info->res = kzalloc(size, GFP_KERNEL);
 	if (!info->res)
 		return;
 
-- 
1.7.7


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

* [PATCH 03/40] PCI, ia64: clear initial value for root info resources
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
  2012-09-19 18:54           ` [PATCH 01/40] PCI: fix default vga ref_count Yinghai Lu
  2012-09-19 18:54           ` [PATCH 02/40] PCI, x86: clear initial value for root info resources Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 04/40] PCI, acpiphp: Add is_hotplug_bridge detection Yinghai Lu
                             ` (37 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu, Tony Luck, Fenghua Yu,
	linux-ia64

after
	PCI, x86: clear initial value for root info resources

change ia64 code accordingly, because later ia64 will support root bus removal too.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64@vger.kernel.org
---
 arch/ia64/pci/pci.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index a7ebe94..5faa66c 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -295,7 +295,6 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
 	window->resource.flags = flags;
 	window->resource.start = addr.minimum + offset;
 	window->resource.end = window->resource.start + addr.address_length - 1;
-	window->resource.child = NULL;
 	window->offset = offset;
 
 	if (insert_resource(root, &window->resource)) {
@@ -357,7 +356,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
 			&windows);
 	if (windows) {
 		controller->window =
-			kmalloc_node(sizeof(*controller->window) * windows,
+			kzalloc_node(sizeof(*controller->window) * windows,
 				     GFP_KERNEL, controller->node);
 		if (!controller->window)
 			goto out2;
-- 
1.7.7


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

* [PATCH 04/40] PCI, acpiphp: Add is_hotplug_bridge detection
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (2 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 03/40] PCI, ia64: " Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 05/40] PCI: Add root bus children dev's res to fail list Yinghai Lu
                             ` (36 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

When system support hotplug bridge with children hotplug slots, we need to make sure
that parent bridge get preallocated resource so later when device is plugged into
children slot, those children devices will get resource allocated.

We do not meet this problem, because for pcie hotplug card, when acpiphp is used,
pci_scan_bridge will set that for us when detect hotplug bit in slot cap.

Reported-and-tested-by: Jason Baron <jbaron@redhat.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Acked-by: Jason Baron <jbaron@redhat.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 7be4ca5..085eec7 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -783,6 +783,29 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
 	}
 }
 
+static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
+{
+	struct acpiphp_func *func;
+
+	if (!dev->subordinate)
+		return;
+
+	/* quirk, or pcie could set it already */
+	if (dev->is_hotplug_bridge)
+		return;
+
+	if (PCI_SLOT(dev->devfn) != slot->device)
+		return;
+
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		if (PCI_FUNC(dev->devfn) == func->function) {
+			/* check if this bridge has ejectable slots */
+			if ((detect_ejectable_slots(func->handle) > 0))
+				dev->is_hotplug_bridge = 1;
+			break;
+		}
+	}
+}
 /**
  * enable_device - enable, configure a slot
  * @slot: slot to be enabled
@@ -817,8 +840,10 @@ static int __ref enable_device(struct acpiphp_slot *slot)
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 				max = pci_scan_bridge(bus, dev, max, pass);
-				if (pass && dev->subordinate)
+				if (pass && dev->subordinate) {
+					check_hotplug_bridge(slot, dev);
 					pci_bus_size_bridges(dev->subordinate);
+				}
 			}
 		}
 	}
-- 
1.7.7


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

* [PATCH 05/40] PCI: Add root bus children dev's res to fail list
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (3 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 04/40] PCI, acpiphp: Add is_hotplug_bridge detection Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 06/40] PCI: Split out stop_bus_device and remove_bus_dev again Yinghai Lu
                             ` (35 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

We can stop according to try number now and do not need to use root_bus checking
as stop sign anymore.
Also in extreme case we could need to reallocate device just under bus 0.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/setup-bus.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 1e808ca..9e625d84 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -283,7 +283,7 @@ static void assign_requested_resources_sorted(struct list_head *head,
 		idx = res - &dev_res->dev->resource[0];
 		if (resource_size(res) &&
 		    pci_assign_resource(dev_res->dev, idx)) {
-			if (fail_head && !pci_is_root_bus(dev_res->dev->bus)) {
+			if (fail_head) {
 				/*
 				 * if the failed res is for ROM BAR, and it will
 				 * be enabled later, don't add it to the list
-- 
1.7.7


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

* [PATCH 06/40] PCI: Split out stop_bus_device and remove_bus_dev again.
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (4 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 05/40] PCI: Add root bus children dev's res to fail list Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 07/40] x86, PCI: Separate pcibios_allocate_bridge_resources() Yinghai Lu
                             ` (34 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

So later could use them for pci root bus hotplug support.

Also restore old behavoir: stop all at first then remove all.

-v2: only split the functions.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/remove.c |   51 ++++++++++++++++++++++++++++++++++---------------
 1 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 4f9ca91..513972f 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -56,25 +56,13 @@ void pci_remove_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pci_remove_bus);
 
-/**
- * pci_stop_and_remove_bus_device - remove a PCI device and any children
- * @dev: the device to remove
- *
- * Remove a PCI device from the device lists, informing the drivers
- * that the device has been removed.  We also remove any subordinate
- * buses and children in a depth-first manner.
- *
- * For each device we remove, delete the device structure from the
- * device lists, remove the /proc entry, and notify userspace
- * (/sbin/hotplug).
- */
-void pci_stop_and_remove_bus_device(struct pci_dev *dev)
+static void pci_stop_bus_device(struct pci_dev *dev)
 {
 	struct pci_bus *bus = dev->subordinate;
 	struct pci_dev *child, *tmp;
 
 	/*
-	 * Removing an SR-IOV PF device removes all the associated VFs,
+	 * Stopping an SR-IOV PF device removes all the associated VFs,
 	 * which will update the bus->devices list and confuse the
 	 * iterator.  Therefore, iterate in reverse so we remove the VFs
 	 * first, then the PF.
@@ -82,13 +70,44 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
 	if (bus) {
 		list_for_each_entry_safe_reverse(child, tmp,
 						 &bus->devices, bus_list)
-			pci_stop_and_remove_bus_device(child);
+			pci_stop_bus_device(child);
+	}
+
+	pci_stop_dev(dev);
+}
+
+static void pci_remove_bus_device(struct pci_dev *dev)
+{
+	struct pci_bus *bus = dev->subordinate;
+	struct pci_dev *child, *tmp;
+
+	if (bus) {
+		list_for_each_entry_safe(child, tmp,
+					 &bus->devices, bus_list)
+			pci_remove_bus_device(child);
 
 		pci_remove_bus(bus);
 		dev->subordinate = NULL;
 	}
 
-	pci_stop_dev(dev);
 	pci_destroy_dev(dev);
 }
+
+/**
+ * pci_stop_and_remove_bus_device - remove a PCI device and any children
+ * @dev: the device to remove
+ *
+ * Remove a PCI device from the device lists, informing the drivers
+ * that the device has been removed.  We also remove any subordinate
+ * buses and children in a depth-first manner.
+ *
+ * For each device we remove, delete the device structure from the
+ * device lists, remove the /proc entry, and notify userspace
+ * (/sbin/hotplug).
+ */
+void pci_stop_and_remove_bus_device(struct pci_dev *dev)
+{
+	pci_stop_bus_device(dev);
+	pci_remove_bus_device(dev);
+}
 EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
-- 
1.7.7


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

* [PATCH 07/40] x86, PCI: Separate pcibios_allocate_bridge_resources()
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (5 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 06/40] PCI: Split out stop_bus_device and remove_bus_dev again Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 08/40] x86, PCI: Separate pcibios_allocate_dev_resources() Yinghai Lu
                             ` (33 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Thus pcibios_allocate_bus_resources() could more simple and clean

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   46 ++++++++++++++++++++++++----------------------
 1 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index dd8ca6f..9800362 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -193,34 +193,36 @@ EXPORT_SYMBOL(pcibios_align_resource);
  *	    as well.
  */
 
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
 {
-	struct pci_bus *bus;
-	struct pci_dev *dev;
 	int idx;
 	struct resource *r;
 
+	for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+		r = &dev->resource[idx];
+		if (!r->flags)
+			continue;
+		if (!r->start || pci_claim_resource(dev, idx) < 0) {
+			/*
+			 * Something is wrong with the region.
+			 * Invalidate the resource to prevent
+			 * child resource allocations in this
+			 * range.
+			 */
+			r->start = r->end = 0;
+			r->flags = 0;
+		}
+	}
+}
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct pci_bus *bus;
+
 	/* Depth-First Search on bus tree */
 	list_for_each_entry(bus, bus_list, node) {
-		if ((dev = bus->self)) {
-			for (idx = PCI_BRIDGE_RESOURCES;
-			    idx < PCI_NUM_RESOURCES; idx++) {
-				r = &dev->resource[idx];
-				if (!r->flags)
-					continue;
-				if (!r->start ||
-				    pci_claim_resource(dev, idx) < 0) {
-					/*
-					 * Something is wrong with the region.
-					 * Invalidate the resource to prevent
-					 * child resource allocations in this
-					 * range.
-					 */
-					r->start = r->end = 0;
-					r->flags = 0;
-				}
-			}
-		}
+		if (bus->self)
+			pcibios_allocate_bridge_resources(bus->self);
 		pcibios_allocate_bus_resources(&bus->children);
 	}
 }
-- 
1.7.7


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

* [PATCH 08/40] x86, PCI: Separate pcibios_allocate_dev_resources()
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (6 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 07/40] x86, PCI: Separate pcibios_allocate_bridge_resources() Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 09/40] x86, PCI: Let pcibios_allocate_bus_resources() take bus instead Yinghai Lu
                             ` (32 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Thus pcibios_allocate_resources() could more simple and clean

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   42 +++++++++++++++++++++++-------------------
 1 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 9800362..5817cf2 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -232,9 +232,8 @@ struct pci_check_idx_range {
 	int end;
 };
 
-static void __init pcibios_allocate_resources(int pass)
+static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 {
-	struct pci_dev *dev = NULL;
 	int idx, disabled, i;
 	u16 command;
 	struct resource *r;
@@ -246,14 +245,13 @@ static void __init pcibios_allocate_resources(int pass)
 #endif
 	};
 
-	for_each_pci_dev(dev) {
-		pci_read_config_word(dev, PCI_COMMAND, &command);
-		for (i = 0; i < ARRAY_SIZE(idx_range); i++)
+	pci_read_config_word(dev, PCI_COMMAND, &command);
+	for (i = 0; i < ARRAY_SIZE(idx_range); i++)
 		for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
 			r = &dev->resource[idx];
-			if (r->parent)		/* Already allocated */
+			if (r->parent)	/* Already allocated */
 				continue;
-			if (!r->start)		/* Address not assigned at all */
+			if (!r->start)	/* Address not assigned at all */
 				continue;
 			if (r->flags & IORESOURCE_IO)
 				disabled = !(command & PCI_COMMAND_IO);
@@ -272,23 +270,29 @@ static void __init pcibios_allocate_resources(int pass)
 				}
 			}
 		}
-		if (!pass) {
-			r = &dev->resource[PCI_ROM_RESOURCE];
-			if (r->flags & IORESOURCE_ROM_ENABLE) {
-				/* Turn the ROM off, leave the resource region,
-				 * but keep it unregistered. */
-				u32 reg;
-				dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
-				r->flags &= ~IORESOURCE_ROM_ENABLE;
-				pci_read_config_dword(dev,
-						dev->rom_base_reg, &reg);
-				pci_write_config_dword(dev, dev->rom_base_reg,
+	if (!pass) {
+		r = &dev->resource[PCI_ROM_RESOURCE];
+		if (r->flags & IORESOURCE_ROM_ENABLE) {
+			/* Turn the ROM off, leave the resource region,
+			 * but keep it unregistered. */
+			u32 reg;
+			dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
+			r->flags &= ~IORESOURCE_ROM_ENABLE;
+			pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+			pci_write_config_dword(dev, dev->rom_base_reg,
 						reg & ~PCI_ROM_ADDRESS_ENABLE);
-			}
 		}
 	}
 }
 
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev = NULL;
+
+	for_each_pci_dev(dev)
+		pcibios_allocate_dev_resources(dev, pass);
+}
+
 static int __init pcibios_assign_resources(void)
 {
 	struct pci_dev *dev = NULL;
-- 
1.7.7


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

* [PATCH 09/40] x86, PCI: Let pcibios_allocate_bus_resources() take bus instead
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (7 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 08/40] x86, PCI: Separate pcibios_allocate_dev_resources() Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 10/40] x86, PCI: Separate rom resource claim out Yinghai Lu
                             ` (31 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Will need call the same code for one single root bus during hot add.
So try to make it take bus instead of bus_list.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   38 +++++++++++++++++++++++++-------------
 1 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 5817cf2..84696ed 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -215,16 +215,15 @@ static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
 	}
 }
 
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+static void __init pcibios_allocate_bus_resources(struct pci_bus *bus)
 {
-	struct pci_bus *bus;
+	struct pci_bus *child;
 
 	/* Depth-First Search on bus tree */
-	list_for_each_entry(bus, bus_list, node) {
-		if (bus->self)
-			pcibios_allocate_bridge_resources(bus->self);
-		pcibios_allocate_bus_resources(&bus->children);
-	}
+	if (bus->self)
+		pcibios_allocate_bridge_resources(bus->self);
+	list_for_each_entry(child, &bus->children, node)
+		pcibios_allocate_bus_resources(child);
 }
 
 struct pci_check_idx_range {
@@ -285,12 +284,18 @@ static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 	}
 }
 
-static void __init pcibios_allocate_resources(int pass)
+static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
 {
-	struct pci_dev *dev = NULL;
+	struct pci_dev *dev;
+	struct pci_bus *child;
 
-	for_each_pci_dev(dev)
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		pcibios_allocate_dev_resources(dev, pass);
+
+		child = dev->subordinate;
+		if (child)
+			pcibios_allocate_resources(child, pass);
+	}
 }
 
 static int __init pcibios_assign_resources(void)
@@ -323,10 +328,17 @@ static int __init pcibios_assign_resources(void)
 
 void __init pcibios_resource_survey(void)
 {
+	struct pci_bus *bus;
+
 	DBG("PCI: Allocating resources\n");
-	pcibios_allocate_bus_resources(&pci_root_buses);
-	pcibios_allocate_resources(0);
-	pcibios_allocate_resources(1);
+
+	list_for_each_entry(bus, &pci_root_buses, node)
+		pcibios_allocate_bus_resources(bus);
+
+	list_for_each_entry(bus, &pci_root_buses, node)
+		pcibios_allocate_resources(bus, 0);
+	list_for_each_entry(bus, &pci_root_buses, node)
+		pcibios_allocate_resources(bus, 1);
 
 	e820_reserve_resources_late();
 	/*
-- 
1.7.7


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

* [PATCH 10/40] x86, PCI: Separate rom resource claim out
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (8 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 09/40] x86, PCI: Let pcibios_allocate_bus_resources() take bus instead Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 11/40] PCI, x86: Add pcibios_fw_addr_done Yinghai Lu
                             ` (30 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

So could use it with hot-added root bus.

-v2: remove extra functions.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   52 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 84696ed..42dd755 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -298,27 +298,45 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
 	}
 }
 
-static int __init pcibios_assign_resources(void)
+static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
 {
-	struct pci_dev *dev = NULL;
 	struct resource *r;
 
-	if (!(pci_probe & PCI_ASSIGN_ROMS)) {
-		/*
-		 * Try to use BIOS settings for ROMs, otherwise let
-		 * pci_assign_unassigned_resources() allocate the new
-		 * addresses.
-		 */
-		for_each_pci_dev(dev) {
-			r = &dev->resource[PCI_ROM_RESOURCE];
-			if (!r->flags || !r->start)
-				continue;
-			if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
-				r->end -= r->start;
-				r->start = 0;
-			}
-		}
+	/*
+	 * Try to use BIOS settings for ROMs, otherwise let
+	 * pci_assign_unassigned_resources() allocate the new
+	 * addresses.
+	 */
+	r = &dev->resource[PCI_ROM_RESOURCE];
+	if (!r->flags || !r->start)
+		return;
+
+	if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
+		r->end -= r->start;
+		r->start = 0;
 	}
+}
+static void __init pcibios_allocate_rom_resources(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	struct pci_bus *child;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pcibios_allocate_dev_rom_resource(dev);
+
+		child = dev->subordinate;
+		if (child)
+			pcibios_allocate_rom_resources(child);
+	}
+}
+
+static int __init pcibios_assign_resources(void)
+{
+	struct pci_bus *bus;
+
+	if (!(pci_probe & PCI_ASSIGN_ROMS))
+		list_for_each_entry(bus, &pci_root_buses, node)
+			pcibios_allocate_rom_resources(bus);
 
 	pci_assign_unassigned_resources();
 	pcibios_fw_addr_list_del();
-- 
1.7.7


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

* [PATCH 11/40] PCI, x86: Add pcibios_fw_addr_done
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (9 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 10/40] x86, PCI: Separate rom resource claim out Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 12/40] PCI, x86: Remove __init for hw/fw allocated functions Yinghai Lu
                             ` (29 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Use it to skip not needed function after pcibios_fw_addr_list_del is called.

for pci root bus hot add, we will need to use pcibios_allocate_dev_resources(),
and don't want to mess up with fw_addr.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 42dd755..edfc376 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -51,6 +51,7 @@ struct pcibios_fwaddrmap {
 
 static LIST_HEAD(pcibios_fwaddrmappings);
 static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);
+static bool pcibios_fw_addr_done;
 
 /* Must be called with 'pcibios_fwaddrmap_lock' lock held. */
 static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
@@ -72,6 +73,9 @@ pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr)
 	unsigned long flags;
 	struct pcibios_fwaddrmap *map;
 
+	if (pcibios_fw_addr_done)
+		return;
+
 	spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
 	map = pcibios_fwaddrmap_lookup(dev);
 	if (!map) {
@@ -97,6 +101,9 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
 	struct pcibios_fwaddrmap *map;
 	resource_size_t fw_addr = 0;
 
+	if (pcibios_fw_addr_done)
+		return fw_addr;
+
 	spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
 	map = pcibios_fwaddrmap_lookup(dev);
 	if (map)
@@ -106,7 +113,7 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
 	return fw_addr;
 }
 
-static void pcibios_fw_addr_list_del(void)
+static void __init pcibios_fw_addr_list_del(void)
 {
 	unsigned long flags;
 	struct pcibios_fwaddrmap *entry, *next;
@@ -118,6 +125,7 @@ static void pcibios_fw_addr_list_del(void)
 		kfree(entry);
 	}
 	spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
+	pcibios_fw_addr_done = true;
 }
 
 static int
-- 
1.7.7


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

* [PATCH 12/40] PCI, x86: Remove __init for hw/fw allocated functions
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (10 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 11/40] PCI, x86: Add pcibios_fw_addr_done Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 13/40] PCI: Claim hw/fw allocated resources in hot add path Yinghai Lu
                             ` (28 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

will need it for hot add path.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index edfc376..1806e91 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -201,7 +201,7 @@ EXPORT_SYMBOL(pcibios_align_resource);
  *	    as well.
  */
 
-static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
+static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
 {
 	int idx;
 	struct resource *r;
@@ -223,7 +223,7 @@ static void __init pcibios_allocate_bridge_resources(struct pci_dev *dev)
 	}
 }
 
-static void __init pcibios_allocate_bus_resources(struct pci_bus *bus)
+static void pcibios_allocate_bus_resources(struct pci_bus *bus)
 {
 	struct pci_bus *child;
 
@@ -239,7 +239,7 @@ struct pci_check_idx_range {
 	int end;
 };
 
-static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
+static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 {
 	int idx, disabled, i;
 	u16 command;
@@ -292,7 +292,7 @@ static void __init pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
 	}
 }
 
-static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
+static void pcibios_allocate_resources(struct pci_bus *bus, int pass)
 {
 	struct pci_dev *dev;
 	struct pci_bus *child;
@@ -306,7 +306,7 @@ static void __init pcibios_allocate_resources(struct pci_bus *bus, int pass)
 	}
 }
 
-static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
+static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
 {
 	struct resource *r;
 
@@ -324,7 +324,7 @@ static void __init pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
 		r->start = 0;
 	}
 }
-static void __init pcibios_allocate_rom_resources(struct pci_bus *bus)
+static void pcibios_allocate_rom_resources(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	struct pci_bus *child;
-- 
1.7.7


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

* [PATCH 13/40] PCI: Claim hw/fw allocated resources in hot add path.
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (11 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 12/40] PCI, x86: Remove __init for hw/fw allocated functions Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 14/40] PCI: Separate out pci_assign_unassigned_bus_resources() Yinghai Lu
                             ` (27 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

During testing remove/rescan root bus 00, found
[  338.142574] bus: 'pci': really_probe: probing driver ata_piix with device 0000:00:01.1
[  338.146788] ata_piix 0000:00:01.1: device not available (can't reserve [io  0x01f0-0x01f7])
[  338.150565] ata_piix: probe of 0000:00:01.1 failed with error -22

because that fixed resource is not claimed from
        arch/x86/pci/i386.c::pcibios_allocate_resources()
that is init path.

Try to claim those resources, so on the remove/rescan will still use old
resources.

It is some kind honoring HW/FW setting in the registers during hot add.
esp root-bus hot add is through acpi, BIOS have chance to set some register
for us.

-v2: add rom resource claiming.
-v3: separate __init removing to another patch, also
   put pci_probe checking with caller from rom resource allocating

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/pci/i386.c |   13 +++++++++++++
 drivers/pci/bus.c   |    2 ++
 include/linux/pci.h |    1 +
 3 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 1806e91..e0b7f30 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -352,6 +352,19 @@ static int __init pcibios_assign_resources(void)
 	return 0;
 }
 
+void pcibios_resource_survey_bus(struct pci_bus *bus)
+{
+	dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n");
+
+	pcibios_allocate_bus_resources(bus);
+
+	pcibios_allocate_resources(bus, 0);
+	pcibios_allocate_resources(bus, 1);
+
+	if (!(pci_probe & PCI_ASSIGN_ROMS))
+		pcibios_allocate_rom_resources(bus);
+}
+
 void __init pcibios_resource_survey(void)
 {
 	struct pci_bus *bus;
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 4b0970b..2882d01 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -154,6 +154,8 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
 	return ret;
 }
 
+void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
+
 /**
  * pci_bus_add_device - add a single device
  * @dev: device to add
diff --git a/include/linux/pci.h b/include/linux/pci.h
index be1de01..ec25403 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -676,6 +676,7 @@ extern struct list_head pci_root_buses;	/* list of all known PCI buses */
 /* Some device drivers need know if pci is initiated */
 extern int no_pci_devices(void);
 
+void pcibios_resource_survey_bus(struct pci_bus *bus);
 void pcibios_fixup_bus(struct pci_bus *);
 int __must_check pcibios_enable_device(struct pci_dev *, int mask);
 /* Architecture specific versions may override this (weak) */
-- 
1.7.7


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

* [PATCH 14/40] PCI: Separate out pci_assign_unassigned_bus_resources()
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (12 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 13/40] PCI: Claim hw/fw allocated resources in hot add path Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 15/40] PCI: Move back pci_rescan_bus() to probe.c Yinghai Lu
                             ` (26 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

It is main portion of pci_rescan_bus().

Separate it out and need to use it for pci root bus hot add later.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/setup-bus.c |   32 ++++++++++++++++++--------------
 include/linux/pci.h     |    1 +
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 9e625d84..7d7c1c9 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1550,25 +1550,12 @@ enable_all:
 }
 EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
 
-#ifdef CONFIG_HOTPLUG
-/**
- * pci_rescan_bus - scan a PCI bus for devices.
- * @bus: PCI bus to scan
- *
- * Scan a PCI bus and child buses for new devices, adds them,
- * and enables them.
- *
- * Returns the max number of subordinate bus discovered.
- */
-unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
 {
-	unsigned int max;
 	struct pci_dev *dev;
 	LIST_HEAD(add_list); /* list of resources that
 					want additional resources */
 
-	max = pci_scan_child_bus(bus);
-
 	down_read(&pci_bus_sem);
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
@@ -1581,6 +1568,23 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
 	BUG_ON(!list_empty(&add_list));
 
 	pci_enable_bridges(bus);
+}
+#ifdef CONFIG_HOTPLUG
+/**
+ * pci_rescan_bus - scan a PCI bus for devices.
+ * @bus: PCI bus to scan
+ *
+ * Scan a PCI bus and child buses for new devices, adds them,
+ * and enables them.
+ *
+ * Returns the max number of subordinate bus discovered.
+ */
+unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+{
+	unsigned int max;
+
+	max = pci_scan_child_bus(bus);
+	pci_assign_unassigned_bus_resources(bus);
 	pci_bus_add_devices(bus);
 
 	return max;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ec25403..02b8e10 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -981,6 +981,7 @@ void pci_bus_size_bridges(struct pci_bus *bus);
 int pci_claim_resource(struct pci_dev *, int);
 void pci_assign_unassigned_resources(void);
 void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
+void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
 void pdev_enable_device(struct pci_dev *);
 int pci_enable_resources(struct pci_dev *, int mask);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
-- 
1.7.7


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

* [PATCH 15/40] PCI: Move back pci_rescan_bus() to probe.c
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (13 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 14/40] PCI: Separate out pci_assign_unassigned_bus_resources() Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 16/40] PCI: pci_bus_size_bridges() should not size own bridge Yinghai Lu
                             ` (25 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

We have pci_assign_unassigned_bus_resources() in as global function now.

So could move back pci_rescan_bus to probe.c where it should be.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c     |   21 +++++++++++++++++++++
 drivers/pci/setup-bus.c |   22 ----------------------
 2 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 2396111..47238dd 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1888,6 +1888,27 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge)
 	return max;
 }
 
+/**
+ * pci_rescan_bus - scan a PCI bus for devices.
+ * @bus: PCI bus to scan
+ *
+ * Scan a PCI bus and child buses for new devices, adds them,
+ * and enables them.
+ *
+ * Returns the max number of subordinate bus discovered.
+ */
+unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
+{
+	unsigned int max;
+
+	max = pci_scan_child_bus(bus);
+	pci_assign_unassigned_bus_resources(bus);
+	pci_bus_add_devices(bus);
+
+	return max;
+}
+EXPORT_SYMBOL_GPL(pci_rescan_bus);
+
 EXPORT_SYMBOL(pci_add_new_bus);
 EXPORT_SYMBOL(pci_scan_slot);
 EXPORT_SYMBOL(pci_scan_bridge);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 7d7c1c9..31821d4 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1569,25 +1569,3 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
 
 	pci_enable_bridges(bus);
 }
-#ifdef CONFIG_HOTPLUG
-/**
- * pci_rescan_bus - scan a PCI bus for devices.
- * @bus: PCI bus to scan
- *
- * Scan a PCI bus and child buses for new devices, adds them,
- * and enables them.
- *
- * Returns the max number of subordinate bus discovered.
- */
-unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
-{
-	unsigned int max;
-
-	max = pci_scan_child_bus(bus);
-	pci_assign_unassigned_bus_resources(bus);
-	pci_bus_add_devices(bus);
-
-	return max;
-}
-EXPORT_SYMBOL_GPL(pci_rescan_bus);
-#endif
-- 
1.7.7


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

* [PATCH 16/40] PCI: pci_bus_size_bridges() should not size own bridge
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (14 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 15/40] PCI: Move back pci_rescan_bus() to probe.c Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 17/40] PCI: Use __pci_bus_size_bridges() directly in pci_assign_unassigned_bus_resources() Yinghai Lu
                             ` (24 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

During checking acpiphp code, found following sequence:
        pci_bus_size_bridges(bus);
        pci_bus_assign_resources(bus);
	pci_enable_bridges(bus);

The problem is that when bus is not root bus, pci_bus_size_bridges would also size
own pci bridge bus->self if that bridge resource is not inserted before.
but later pci_bus_assign_resources will not allocate those size bridge res.

So try make it less confusing, let it does not include self sizing.
and add with_self parameter info __pci_bus_size_bridge()

Fixes caller in pci hotplug componets.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/hotplug/acpiphp_glue.c |    3 ++-
 drivers/pci/setup-bus.c            |   24 +++++++++++++++---------
 include/linux/pci.h                |    1 +
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 085eec7..6cb1923 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -842,7 +842,8 @@ static int __ref enable_device(struct acpiphp_slot *slot)
 				max = pci_scan_bridge(bus, dev, max, pass);
 				if (pass && dev->subordinate) {
 					check_hotplug_bridge(slot, dev);
-					pci_bus_size_bridges(dev->subordinate);
+					pci_bus_size_bridges_with_self(
+							dev->subordinate);
 				}
 			}
 		}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 31821d4..85f7ec73 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1044,8 +1044,8 @@ handle_done:
 	;
 }
 
-void __ref __pci_bus_size_bridges(struct pci_bus *bus,
-			struct list_head *realloc_head)
+static void __ref __pci_bus_size_bridges(struct pci_bus *bus,
+			struct list_head *realloc_head, bool with_self)
 {
 	struct pci_dev *dev;
 	unsigned long mask, prefmask;
@@ -1063,13 +1063,13 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
 
 		case PCI_CLASS_BRIDGE_PCI:
 		default:
-			__pci_bus_size_bridges(b, realloc_head);
+			__pci_bus_size_bridges(b, realloc_head, true);
 			break;
 		}
 	}
 
-	/* The root bus? */
-	if (!bus->self)
+	/* Is root bus or not wanted? */
+	if (!bus->self || !with_self)
 		return;
 
 	switch (bus->self->class >> 8) {
@@ -1109,9 +1109,15 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
 	}
 }
 
+void __ref pci_bus_size_bridges_with_self(struct pci_bus *bus)
+{
+	__pci_bus_size_bridges(bus, NULL, true);
+}
+EXPORT_SYMBOL(pci_bus_size_bridges_with_self);
+
 void __ref pci_bus_size_bridges(struct pci_bus *bus)
 {
-	__pci_bus_size_bridges(bus, NULL);
+	__pci_bus_size_bridges(bus, NULL, false);
 }
 EXPORT_SYMBOL(pci_bus_size_bridges);
 
@@ -1424,7 +1430,7 @@ again:
 	/* Depth first, calculate sizes and alignments of all
 	   subordinate buses. */
 	list_for_each_entry(bus, &pci_root_buses, node)
-		__pci_bus_size_bridges(bus, add_list);
+		__pci_bus_size_bridges(bus, add_list, false);
 
 	/* Depth last, allocate resources and update the hardware. */
 	list_for_each_entry(bus, &pci_root_buses, node)
@@ -1501,7 +1507,7 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
 				  IORESOURCE_PREFETCH;
 
 again:
-	__pci_bus_size_bridges(parent, &add_list);
+	__pci_bus_size_bridges(parent, &add_list, true);
 	__pci_bridge_assign_resources(bridge, &add_list, &fail_head);
 	BUG_ON(!list_empty(&add_list));
 	tried_times++;
@@ -1562,7 +1568,7 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
 		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 			if (dev->subordinate)
 				__pci_bus_size_bridges(dev->subordinate,
-							 &add_list);
+						 &add_list, true);
 	up_read(&pci_bus_sem);
 	__pci_bus_assign_resources(bus, &add_list, NULL);
 	BUG_ON(!list_empty(&add_list));
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 02b8e10..7404077 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -978,6 +978,7 @@ int pci_vpd_truncate(struct pci_dev *dev, size_t size);
 resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx);
 void pci_bus_assign_resources(const struct pci_bus *bus);
 void pci_bus_size_bridges(struct pci_bus *bus);
+void pci_bus_size_bridges_with_self(struct pci_bus *bus);
 int pci_claim_resource(struct pci_dev *, int);
 void pci_assign_unassigned_resources(void);
 void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge);
-- 
1.7.7


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

* [PATCH 17/40] PCI: Use __pci_bus_size_bridges() directly in pci_assign_unassigned_bus_resources()
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (15 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 16/40] PCI: pci_bus_size_bridges() should not size own bridge Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 18/40] PCI: Rescan bus using callback method too Yinghai Lu
                             ` (23 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Now __pci_bus_size_bridges() will not include self bridge.
So we don't need to have our own version in
 pci_assign_unassigned_bus_resources anymore.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/setup-bus.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 85f7ec73..56155c9 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1558,17 +1558,11 @@ EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
 
 void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
 {
-	struct pci_dev *dev;
 	LIST_HEAD(add_list); /* list of resources that
 					want additional resources */
 
 	down_read(&pci_bus_sem);
-	list_for_each_entry(dev, &bus->devices, bus_list)
-		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
-		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
-			if (dev->subordinate)
-				__pci_bus_size_bridges(dev->subordinate,
-						 &add_list, true);
+	__pci_bus_size_bridges(bus, &add_list, false);
 	up_read(&pci_bus_sem);
 	__pci_bus_assign_resources(bus, &add_list, NULL);
 	BUG_ON(!list_empty(&add_list));
-- 
1.7.7


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

* [PATCH 18/40] PCI: Rescan bus using callback method too
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (16 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 17/40] PCI: Use __pci_bus_size_bridges() directly in pci_assign_unassigned_bus_resources() Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 19/40] PCI, sysfs: Clean up rescan/remove with schedule_callback Yinghai Lu
                             ` (22 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Just like removal.

Because We could add new bus under the bridges...

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/pci-sysfs.c |   28 +++++++++++++++++++---------
 1 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 02d107b..60e04b2 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -356,24 +356,34 @@ remove_store(struct device *dev, struct device_attribute *dummy,
 	return count;
 }
 
+static void bus_rescan_callback(struct device *dev)
+{
+	struct pci_bus *bus = to_pci_bus(dev);
+
+	mutex_lock(&pci_remove_rescan_mutex);
+	if (!pci_is_root_bus(bus) && list_empty(&bus->devices))
+		pci_rescan_bus_bridge_resize(bus->self);
+	else
+		pci_rescan_bus(bus);
+	mutex_unlock(&pci_remove_rescan_mutex);
+}
+
 static ssize_t
 dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
 		 const char *buf, size_t count)
 {
+	int ret = 0;
 	unsigned long val;
-	struct pci_bus *bus = to_pci_bus(dev);
 
 	if (strict_strtoul(buf, 0, &val) < 0)
 		return -EINVAL;
 
-	if (val) {
-		mutex_lock(&pci_remove_rescan_mutex);
-		if (!pci_is_root_bus(bus) && list_empty(&bus->devices))
-			pci_rescan_bus_bridge_resize(bus->self);
-		else
-			pci_rescan_bus(bus);
-		mutex_unlock(&pci_remove_rescan_mutex);
-	}
+	if (val)
+		ret = device_schedule_callback(dev, bus_rescan_callback);
+
+	if (ret)
+		count = ret;
+
 	return count;
 }
 
-- 
1.7.7


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

* [PATCH 19/40] PCI, sysfs: Clean up rescan/remove with schedule_callback
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (17 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 18/40] PCI: Rescan bus using callback method too Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 20/40] PCI: Fix a device reference count leakage issue in pci_dev_present() Yinghai Lu
                             ` (21 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Change to use three return according to Bjorn.

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/pci-sysfs.c |   25 ++++++++++++++-----------
 1 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 60e04b2..b308558 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -340,7 +340,7 @@ static ssize_t
 remove_store(struct device *dev, struct device_attribute *dummy,
 	     const char *buf, size_t count)
 {
-	int ret = 0;
+	int err;
 	unsigned long val;
 
 	if (strict_strtoul(buf, 0, &val) < 0)
@@ -349,10 +349,13 @@ remove_store(struct device *dev, struct device_attribute *dummy,
 	/* An attribute cannot be unregistered by one of its own methods,
 	 * so we have to use this roundabout approach.
 	 */
-	if (val)
-		ret = device_schedule_callback(dev, remove_callback);
-	if (ret)
-		count = ret;
+	if (!val)
+		return count;
+
+	err = device_schedule_callback(dev, remove_callback);
+	if (err)
+		return err;
+
 	return count;
 }
 
@@ -372,17 +375,17 @@ static ssize_t
 dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
 		 const char *buf, size_t count)
 {
-	int ret = 0;
+	int err;
 	unsigned long val;
 
 	if (strict_strtoul(buf, 0, &val) < 0)
 		return -EINVAL;
+	if (!val)
+		return count;
 
-	if (val)
-		ret = device_schedule_callback(dev, bus_rescan_callback);
-
-	if (ret)
-		count = ret;
+	err = device_schedule_callback(dev, bus_rescan_callback);
+	if (err)
+		return err;
 
 	return count;
 }
-- 
1.7.7


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

* [PATCH 20/40] PCI: Fix a device reference count leakage issue in pci_dev_present()
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (18 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 19/40] PCI, sysfs: Clean up rescan/remove with schedule_callback Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 21/40] PCI: Add pci_stop_and_remove_root_bus() Yinghai Lu
                             ` (20 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi

From: Jiang Liu <jiang.liu@huawei.com>

Function pci_get_dev_by_id() will hold a reference count on the pci device
returned, so pci_dev_present() should release the corresponding reference
count to avoid memory leakage.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
---
 drivers/pci/search.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index bf969ba..d0627fa 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -319,13 +319,13 @@ int pci_dev_present(const struct pci_device_id *ids)
 	WARN_ON(in_interrupt());
 	while (ids->vendor || ids->subvendor || ids->class_mask) {
 		found = pci_get_dev_by_id(ids, NULL);
-		if (found)
-			goto exit;
+		if (found) {
+			pci_dev_put(found);
+			return 1;
+		}
 		ids++;
 	}
-exit:
-	if (found)
-		return 1;
+
 	return 0;
 }
 EXPORT_SYMBOL(pci_dev_present);
-- 
1.7.7


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

* [PATCH 21/40] PCI: Add pci_stop_and_remove_root_bus()
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (19 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 20/40] PCI: Fix a device reference count leakage issue in pci_dev_present() Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge Yinghai Lu
                             ` (19 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

It supports both pci root bus and pci bus under pci bridge.

-v2: clear pci_bridge's subordinate.
-v3: only handle root bus. and also put Jiang's get/put pair in
-v4: fold pci_stop/remove_bus_devices in... reducing confusing.
-v5: split device_register/unregister to avoid extra get...
     also remove extra blank line.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c  |    3 ++-
 drivers/pci/remove.c |   36 ++++++++++++++++++++++++++++++++++++
 include/linux/pci.h  |    2 ++
 3 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 47238dd..ab845aa 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1660,7 +1660,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
 	bridge->dev.parent = parent;
 	bridge->dev.release = pci_release_bus_bridge_dev;
 	dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
-	error = device_register(&bridge->dev);
+	device_initialize(&bridge->dev);
+	error = device_add(&bridge->dev);
 	if (error)
 		goto bridge_dev_reg_err;
 	b->bridge = get_device(&bridge->dev);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 513972f..7c0fd92 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -111,3 +111,39 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
 	pci_remove_bus_device(dev);
 }
 EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
+
+void pci_stop_root_bus(struct pci_bus *bus)
+{
+	struct pci_dev *child, *tmp;
+	struct pci_host_bridge *host_bridge;
+
+	if (!pci_is_root_bus(bus))
+		return;
+
+	host_bridge = to_pci_host_bridge(bus->bridge);
+	list_for_each_entry_safe_reverse(child, tmp,
+					 &bus->devices, bus_list)
+		pci_stop_bus_device(child);
+
+	/* stop the host bridge */
+	device_del(&host_bridge->dev);
+}
+
+void pci_remove_root_bus(struct pci_bus *bus)
+{
+	struct pci_dev *child, *tmp;
+	struct pci_host_bridge *host_bridge;
+
+	if (!pci_is_root_bus(bus))
+		return;
+
+	host_bridge = to_pci_host_bridge(bus->bridge);
+	list_for_each_entry_safe(child, tmp,
+				 &bus->devices, bus_list)
+		pci_remove_bus_device(child);
+	pci_remove_bus(bus);
+	host_bridge->bus = NULL;
+
+	/* remove the host bridge */
+	put_device(&host_bridge->dev);
+}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7404077..88ae237 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -735,6 +735,8 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
 extern void pci_remove_bus(struct pci_bus *b);
 extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
+void pci_stop_root_bus(struct pci_bus *bus);
+void pci_remove_root_bus(struct pci_bus *bus);
 void pci_setup_cardbus(struct pci_bus *bus);
 extern void pci_sort_breadthfirst(void);
 #define dev_is_pci(d) ((d)->bus == &pci_bus_type)
-- 
1.7.7


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

* [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (20 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 21/40] PCI: Add pci_stop_and_remove_root_bus() Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-10-12 10:36             ` Tang Chen
  2012-09-19 18:54           ` [PATCH 23/40] PCI, ACPI: Pass device instead of handle when config root bridge Yinghai Lu
                             ` (18 subsequent siblings)
  40 siblings, 1 reply; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

It causes confusion.

We may only need acpi hp for pci host bridge.

Split host bridge hot-add support to pci_root_hp, and keep acpiphp simple.

Also remove not used res_lock in the struct.

-v2: put back pci_root_hp change in one patch
-v3: add pcibios_resource_survey_bus() calling
-v4: remove not needed code with remove_bridge
-v5: put back support for acpiphp support for slots just on root bus.
-v6: change some functions to *_p2p_* to make it more clean.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/Makefile              |    1 +
 drivers/acpi/pci_root_hp.c         |  238 ++++++++++++++++++++++++++++++++++++
 drivers/pci/hotplug/acpiphp_glue.c |   59 +++-------
 3 files changed, 254 insertions(+), 44 deletions(-)
 create mode 100644 drivers/acpi/pci_root_hp.c

diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 47199e2..c9abd4c 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -36,6 +36,7 @@ acpi-y				+= processor_core.o
 acpi-y				+= ec.o
 acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
 acpi-y				+= pci_root.o pci_link.o pci_irq.o pci_bind.o
+acpi-$(CONFIG_HOTPLUG)		+= pci_root_hp.o
 acpi-y				+= power.o
 acpi-y				+= event.o
 acpi-y				+= sysfs.o
diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c
new file mode 100644
index 0000000..e07c31b
--- /dev/null
+++ b/drivers/acpi/pci_root_hp.c
@@ -0,0 +1,238 @@
+/*
+ * Separated from drivers/pci/hotplug/acpiphp_glue.c
+ *	only support root bridge
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+
+static LIST_HEAD(acpi_root_bridge_list);
+struct acpi_root_bridge {
+	struct list_head list;
+	acpi_handle handle;
+	u32 flags;
+};
+
+/* bridge flags */
+#define ROOT_BRIDGE_HAS_EJ0	(0x00000002)
+#define ROOT_BRIDGE_HAS_PS3	(0x00000080)
+
+#define ACPI_STA_FUNCTIONING	(0x00000008)
+
+static struct acpi_root_bridge *acpi_root_handle_to_bridge(acpi_handle handle)
+{
+	struct acpi_root_bridge *bridge;
+
+	list_for_each_entry(bridge, &acpi_root_bridge_list, list)
+		if (bridge->handle == handle)
+			return bridge;
+
+	return NULL;
+}
+
+/* allocate and initialize host bridge data structure */
+static void add_acpi_root_bridge(acpi_handle handle)
+{
+	struct acpi_root_bridge *bridge;
+	acpi_handle dummy_handle;
+	acpi_status status;
+
+	/* if the bridge doesn't have _STA, we assume it is always there */
+	status = acpi_get_handle(handle, "_STA", &dummy_handle);
+	if (ACPI_SUCCESS(status)) {
+		unsigned long long tmp;
+
+		status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_DEBUG "%s: _STA evaluation failure\n",
+						 __func__);
+			return;
+		}
+		if ((tmp & ACPI_STA_FUNCTIONING) == 0)
+			/* don't register this object */
+			return;
+	}
+
+	bridge = kzalloc(sizeof(struct acpi_root_bridge), GFP_KERNEL);
+	if (!bridge)
+		return;
+
+	bridge->handle = handle;
+
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &dummy_handle)))
+		bridge->flags |= ROOT_BRIDGE_HAS_EJ0;
+	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &dummy_handle)))
+		bridge->flags |= ROOT_BRIDGE_HAS_PS3;
+
+	list_add(&bridge->list, &acpi_root_bridge_list);
+}
+
+struct acpi_root_hp_work {
+	struct work_struct work;
+	acpi_handle handle;
+	u32 type;
+	void *context;
+};
+
+static void alloc_acpi_root_hp_work(acpi_handle handle, u32 type,
+					void *context,
+					void (*func)(struct work_struct *work))
+{
+	struct acpi_root_hp_work *hp_work;
+	int ret;
+
+	hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
+	if (!hp_work)
+		return;
+
+	hp_work->handle = handle;
+	hp_work->type = type;
+	hp_work->context = context;
+
+	INIT_WORK(&hp_work->work, func);
+	ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
+	if (!ret)
+		kfree(hp_work);
+}
+
+/* Program resources in newly inserted bridge */
+static void acpi_root_configure_bridge(acpi_handle handle)
+{
+	struct acpi_pci_root *root = acpi_pci_find_root(handle);
+
+	pcibios_resource_survey_bus(root->bus);
+	pci_assign_unassigned_bus_resources(root->bus);
+}
+
+static void handle_root_bridge_insertion(acpi_handle handle)
+{
+	struct acpi_device *device, *pdevice;
+	acpi_handle phandle;
+	int ret_val;
+
+	acpi_get_parent(handle, &phandle);
+	if (acpi_bus_get_device(phandle, &pdevice)) {
+		printk(KERN_DEBUG "no parent device, assuming NULL\n");
+		pdevice = NULL;
+	}
+	if (!acpi_bus_get_device(handle, &device)) {
+		/* check if  pci root_bus is removed */
+		struct acpi_pci_root *root = acpi_driver_data(device);
+		if (pci_find_bus(root->segment, root->secondary.start))
+			return;
+
+		printk(KERN_DEBUG "bus exists... trim\n");
+		/* this shouldn't be in here, so remove
+		 * the bus then re-add it...
+		 */
+		ret_val = acpi_bus_trim(device, 1);
+		printk(KERN_DEBUG "acpi_bus_trim return %x\n", ret_val);
+	}
+	if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {
+		printk(KERN_ERR "cannot add bridge to acpi list\n");
+		return;
+	}
+	acpi_root_configure_bridge(handle);
+	if (acpi_bus_start(device))
+		printk(KERN_ERR "cannot start bridge\n");
+}
+
+static void _handle_hotplug_event_root(struct work_struct *work)
+{
+	struct acpi_root_bridge *bridge;
+	char objname[64];
+	struct acpi_buffer buffer = { .length = sizeof(objname),
+				      .pointer = objname };
+	struct acpi_root_hp_work *hp_work;
+	acpi_handle handle;
+	u32 type;
+
+	hp_work = container_of(work, struct acpi_root_hp_work, work);
+	handle = hp_work->handle;
+	type = hp_work->type;
+
+	bridge = acpi_root_handle_to_bridge(handle);
+
+	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		/* bus enumerate */
+		printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
+				 objname);
+		if (!bridge) {
+			handle_root_bridge_insertion(handle);
+			add_acpi_root_bridge(handle);
+		}
+
+		break;
+
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		/* device check */
+		printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
+				 objname);
+		if (!bridge) {
+			handle_root_bridge_insertion(handle);
+			add_acpi_root_bridge(handle);
+		}
+		break;
+
+	default:
+		printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
+				 type, objname);
+		break;
+	}
+
+	kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
+}
+
+static void handle_hotplug_event_root(acpi_handle handle, u32 type,
+					void *context)
+{
+	alloc_acpi_root_hp_work(handle, type, context,
+				_handle_hotplug_event_root);
+}
+
+static acpi_status __init
+find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	char objname[64];
+	struct acpi_buffer buffer = { .length = sizeof(objname),
+				      .pointer = objname };
+	int *count = (int *)context;
+
+	if (!acpi_is_root_bridge(handle))
+		return AE_OK;
+
+	(*count)++;
+
+	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+
+	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				handle_hotplug_event_root, NULL);
+	printk(KERN_DEBUG "acpi root: %s notify handler installed\n", objname);
+
+	add_acpi_root_bridge(handle);
+
+	return AE_OK;
+}
+
+static int __init acpi_pci_root_hp_init(void)
+{
+	int num = 0;
+
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+		ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
+
+	printk(KERN_DEBUG "Found %d acpi root devices\n", num);
+
+	return 0;
+}
+
+subsys_initcall(acpi_pci_root_hp_init);
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 6cb1923..00fa414 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -521,10 +521,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
 	acpi_status status;
 	acpi_handle handle = bridge->handle;
 
-	status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+	if (bridge->type != BRIDGE_TYPE_HOST) {
+		status = acpi_remove_notify_handler(handle,
+					    ACPI_SYSTEM_NOTIFY,
 					    handle_hotplug_event_bridge);
-	if (ACPI_FAILURE(status))
-		err("failed to remove notify handler\n");
+		if (ACPI_FAILURE(status))
+			err("failed to remove notify handler\n");
+	}
 
 	if ((bridge->type != BRIDGE_TYPE_HOST) &&
 	    ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
@@ -607,9 +610,6 @@ static void remove_bridge(acpi_handle handle)
 	bridge = acpiphp_handle_to_bridge(handle);
 	if (bridge)
 		cleanup_bridge(bridge);
-	else
-		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					   handle_hotplug_event_bridge);
 }
 
 static int power_on_slot(struct acpiphp_slot *slot)
@@ -1110,18 +1110,12 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
 }
 
 /* Program resources in newly inserted bridge */
-static int acpiphp_configure_bridge (acpi_handle handle)
+static int acpiphp_configure_p2p_bridge(acpi_handle handle)
 {
-	struct pci_bus *bus;
+	struct pci_dev *pdev = acpi_get_pci_dev(handle);
+	struct pci_bus *bus = pdev->subordinate;
 
-	if (acpi_is_root_bridge(handle)) {
-		struct acpi_pci_root *root = acpi_pci_find_root(handle);
-		bus = root->bus;
-	} else {
-		struct pci_dev *pdev = acpi_get_pci_dev(handle);
-		bus = pdev->subordinate;
-		pci_dev_put(pdev);
-	}
+	pci_dev_put(pdev);
 
 	pci_bus_size_bridges(bus);
 	pci_bus_assign_resources(bus);
@@ -1131,7 +1125,7 @@ static int acpiphp_configure_bridge (acpi_handle handle)
 	return 0;
 }
 
-static void handle_bridge_insertion(acpi_handle handle, u32 type)
+static void handle_p2p_bridge_insertion(acpi_handle handle, u32 type)
 {
 	struct acpi_device *device, *pdevice;
 	acpi_handle phandle;
@@ -1151,9 +1145,9 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
 		err("cannot add bridge to acpi list\n");
 		return;
 	}
-	if (!acpiphp_configure_bridge(handle) &&
+	if (!acpiphp_configure_p2p_bridge(handle) &&
 		!acpi_bus_start(device))
-		add_bridge(handle);
+		add_p2p_bridge(handle);
 	else
 		err("cannot configure and start bridge\n");
 
@@ -1239,7 +1233,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
 
 	if (acpi_bus_get_device(handle, &device)) {
 		/* This bridge must have just been physically inserted */
-		handle_bridge_insertion(handle, type);
+		handle_p2p_bridge_insertion(handle, type);
 		goto out;
 	}
 
@@ -1416,21 +1410,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
 			      _handle_hotplug_event_func);
 }
 
-static acpi_status
-find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
-	int *count = (int *)context;
-
-	if (!acpi_is_root_bridge(handle))
-		return AE_OK;
-
-	(*count)++;
-	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    handle_hotplug_event_bridge, NULL);
-
-	return AE_OK ;
-}
-
 static struct acpi_pci_driver acpi_pci_hp_driver = {
 	.add =		add_bridge,
 	.remove =	remove_bridge,
@@ -1441,15 +1420,7 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
  */
 int __init acpiphp_glue_init(void)
 {
-	int num = 0;
-
-	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-			ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
-
-	if (num <= 0)
-		return -1;
-	else
-		acpi_pci_register_driver(&acpi_pci_hp_driver);
+	acpi_pci_register_driver(&acpi_pci_hp_driver);
 
 	return 0;
 }
-- 
1.7.7


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

* [PATCH 23/40] PCI, ACPI: Pass device instead of handle when config root bridge
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (21 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 24/40] PCI, acpi: Update acpi_pci_driver add/remove interface Yinghai Lu
                             ` (17 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

So we can avoid one calling of acpi_pci_find_root().

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root_hp.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c
index e07c31b..eb4344c 100644
--- a/drivers/acpi/pci_root_hp.c
+++ b/drivers/acpi/pci_root_hp.c
@@ -102,9 +102,9 @@ static void alloc_acpi_root_hp_work(acpi_handle handle, u32 type,
 }
 
 /* Program resources in newly inserted bridge */
-static void acpi_root_configure_bridge(acpi_handle handle)
+static void acpi_root_configure_bridge(struct acpi_device *device)
 {
-	struct acpi_pci_root *root = acpi_pci_find_root(handle);
+	struct acpi_pci_root *root = acpi_driver_data(device);
 
 	pcibios_resource_survey_bus(root->bus);
 	pci_assign_unassigned_bus_resources(root->bus);
@@ -138,7 +138,7 @@ static void handle_root_bridge_insertion(acpi_handle handle)
 		printk(KERN_ERR "cannot add bridge to acpi list\n");
 		return;
 	}
-	acpi_root_configure_bridge(handle);
+	acpi_root_configure_bridge(device);
 	if (acpi_bus_start(device))
 		printk(KERN_ERR "cannot start bridge\n");
 }
-- 
1.7.7


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

* [PATCH 24/40] PCI, acpi: Update acpi_pci_driver add/remove interface
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (22 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 23/40] PCI, ACPI: Pass device instead of handle when config root bridge Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 25/40] PCI, ACPI: Make acpi_pci_root_remove remove pci root bus too Yinghai Lu
                             ` (16 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

To take acpi_pci_root pointer instead, so later caller will not need to

check the apci_pci_root list to find it.

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c            |    4 ++--
 drivers/acpi/pci_slot.c            |   12 +++++++-----
 drivers/pci/hotplug/acpiphp_glue.c |   12 +++++++-----
 include/linux/acpi.h               |    4 ++--
 4 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 72a2c98..3d92c0e 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -90,7 +90,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
 		return 0;
 
 	list_for_each_entry(root, &acpi_pci_roots, node) {
-		driver->add(root->device->handle);
+		driver->add(root);
 		n++;
 	}
 
@@ -116,7 +116,7 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 		return;
 
 	list_for_each_entry(root, &acpi_pci_roots, node)
-		driver->remove(root->device->handle);
+		driver->remove(root);
 }
 
 EXPORT_SYMBOL(acpi_pci_unregister_driver);
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index e50e31a..1c16c20 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -67,8 +67,8 @@ struct acpi_pci_slot {
 	struct list_head list;		/* node in the list of slots */
 };
 
-static int acpi_pci_slot_add(acpi_handle handle);
-static void acpi_pci_slot_remove(acpi_handle handle);
+static int acpi_pci_slot_add(struct acpi_pci_root *root);
+static void acpi_pci_slot_remove(struct acpi_pci_root *root);
 
 static LIST_HEAD(slot_list);
 static DEFINE_MUTEX(slot_list_lock);
@@ -295,11 +295,11 @@ walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
  * @handle: points to an acpi_pci_root
  */
 static int
-acpi_pci_slot_add(acpi_handle handle)
+acpi_pci_slot_add(struct acpi_pci_root *root)
 {
 	acpi_status status;
 
-	status = walk_root_bridge(handle, register_slot);
+	status = walk_root_bridge(root->device->handle, register_slot);
 	if (ACPI_FAILURE(status))
 		err("%s: register_slot failure - %d\n", __func__, status);
 
@@ -311,12 +311,14 @@ acpi_pci_slot_add(acpi_handle handle)
  * @handle: points to an acpi_pci_root
  */
 static void
-acpi_pci_slot_remove(acpi_handle handle)
+acpi_pci_slot_remove(struct acpi_pci_root *root)
 {
 	struct acpi_pci_slot *slot, *tmp;
 	struct pci_bus *pbus;
+	acpi_handle handle;
 
 	mutex_lock(&slot_list_lock);
+	handle = root->device->handle;
 	list_for_each_entry_safe(slot, tmp, &slot_list, list) {
 		if (slot->root_handle == handle) {
 			list_del(&slot->list);
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 00fa414..201c5f7 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -382,10 +382,10 @@ static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
 
 
 /* allocate and initialize host bridge data structure */
-static void add_host_bridge(acpi_handle *handle)
+static void add_host_bridge(struct acpi_pci_root *root)
 {
+	acpi_handle handle = root->device->handle;
 	struct acpiphp_bridge *bridge;
-	struct acpi_pci_root *root = acpi_pci_find_root(handle);
 
 	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 	if (bridge == NULL)
@@ -468,8 +468,9 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
 
 
 /* find hot-pluggable slots, and then find P2P bridge */
-static int add_bridge(acpi_handle handle)
+static int add_bridge(struct acpi_pci_root *root)
 {
+	acpi_handle handle = root->device->handle;
 	acpi_status status;
 	unsigned long long tmp;
 	acpi_handle dummy_handle;
@@ -490,7 +491,7 @@ static int add_bridge(acpi_handle handle)
 	/* check if this bridge has ejectable slots */
 	if (detect_ejectable_slots(handle) > 0) {
 		dbg("found PCI host-bus bridge with hot-pluggable slots\n");
-		add_host_bridge(handle);
+		add_host_bridge(root);
 	}
 
 	/* search P2P bridges under this host bridge */
@@ -591,8 +592,9 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
 	return AE_OK;
 }
 
-static void remove_bridge(acpi_handle handle)
+static void remove_bridge(struct acpi_pci_root *root)
 {
+	acpi_handle handle = root->device->handle;
 	struct acpiphp_bridge *bridge;
 
 	/* cleanup p2p bridges under this host bridge
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 4f2a762..a686098 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -139,8 +139,8 @@ void acpi_pci_irq_disable (struct pci_dev *dev);
 
 struct acpi_pci_driver {
 	struct acpi_pci_driver *next;
-	int (*add)(acpi_handle handle);
-	void (*remove)(acpi_handle handle);
+	int (*add)(struct acpi_pci_root *root);
+	void (*remove)(struct acpi_pci_root *root);
 };
 
 int acpi_pci_register_driver(struct acpi_pci_driver *driver);
-- 
1.7.7


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

* [PATCH 25/40] PCI, ACPI: Make acpi_pci_root_remove remove pci root bus too
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (23 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 24/40] PCI, acpi: Update acpi_pci_driver add/remove interface Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 26/40] PCI, ACPI: del root bus prt Yinghai Lu
                             ` (15 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

It will call new added pci_stop_and_remove_bus() to stop/remove pci root bus.

Also checking if that pci_root_bus get removed already in bus remove in /sys

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
---
 drivers/acpi/pci_root.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 3d92c0e..92ec5c9 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -652,10 +652,26 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);
 
+	/* that root bus could be removed already */
+	if (!pci_find_bus(root->segment, root->secondary.start)) {
+		dev_printk(KERN_DEBUG, &device->dev,
+		  "freeing acpi_pci_root, but pci root bus was removed before");
+		goto out;
+	}
+
+	pci_stop_root_bus(root->bus);
+
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
+	dev_printk(KERN_DEBUG, &device->dev,
+		"freeing acpi_pci_root, will remove pci root bus at first");
+	pci_remove_root_bus(root->bus);
+
+out:
+	list_del(&root->node);
 	kfree(root);
+
 	return 0;
 }
 
-- 
1.7.7


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

* [PATCH 26/40] PCI, ACPI: del root bus prt
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (24 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 25/40] PCI, ACPI: Make acpi_pci_root_remove remove pci root bus too Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 27/40] ACPI: acpi_bus_trim to support two steps Yinghai Lu
                             ` (14 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

corresponding to add path.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 92ec5c9..b72c85c 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -650,6 +650,8 @@ static int acpi_pci_root_start(struct acpi_device *device)
 
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
+	acpi_status status;
+	acpi_handle handle;
 	struct acpi_pci_root *root = acpi_driver_data(device);
 
 	/* that root bus could be removed already */
@@ -664,6 +666,10 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
+	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
+	if (ACPI_SUCCESS(status))
+		acpi_pci_irq_del_prt(root->bus);
+
 	dev_printk(KERN_DEBUG, &device->dev,
 		"freeing acpi_pci_root, will remove pci root bus at first");
 	pci_remove_root_bus(root->bus);
-- 
1.7.7


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

* [PATCH 27/40] ACPI: acpi_bus_trim to support two steps.
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (25 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 26/40] PCI, ACPI: del root bus prt Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 28/40] PCI, ACPI: Add pci_root_hp hot removal notification support Yinghai Lu
                             ` (13 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

current all acpi_bus_trim callers have rmdevice to 1.
that means it will remove all acpi devices.

When 0, is passed, it will keep one parent.

For root bus hotremove support, we need to have pci device removed before
acpi devices.

So try to keep all acpi devices, and only stop drivers with them.

This change should be safe because all current callers all have 1 passed.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
---
 drivers/acpi/scan.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index d1ecca2..d1a1f25 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1539,10 +1539,7 @@ int acpi_bus_trim(struct acpi_device *start, int rmdevice)
 			child = parent;
 			parent = parent->parent;
 
-			if (level == 0)
-				err = acpi_bus_remove(child, rmdevice);
-			else
-				err = acpi_bus_remove(child, 1);
+			err = acpi_bus_remove(child, rmdevice);
 
 			continue;
 		}
-- 
1.7.7


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

* [PATCH 28/40] PCI, ACPI: Add pci_root_hp hot removal notification support.
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (26 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 27/40] ACPI: acpi_bus_trim to support two steps Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 29/40] PCI, ACPI: Add alloc_acpi_hp_work() Yinghai Lu
                             ` (12 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Add missing hot_remove support for root device.

How to use it?
Find out root bus number to acpi root name mapping from dmesg or /sys

  echo "\_SB.PCIB 3" > /sys/kernel/debug/acpi/sci_notify
to remove root bus

-v2: separate stop and remove, so could use acpi_pci_bind_notify()...

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
---
 drivers/acpi/pci_root_hp.c |   67 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c
index eb4344c..434ee35 100644
--- a/drivers/acpi/pci_root_hp.c
+++ b/drivers/acpi/pci_root_hp.c
@@ -73,6 +73,12 @@ static void add_acpi_root_bridge(acpi_handle handle)
 	list_add(&bridge->list, &acpi_root_bridge_list);
 }
 
+static void remove_acpi_root_bridge(struct acpi_root_bridge *bridge)
+{
+	list_del(&bridge->list);
+	kfree(bridge);
+}
+
 struct acpi_root_hp_work {
 	struct work_struct work;
 	acpi_handle handle;
@@ -143,6 +149,61 @@ static void handle_root_bridge_insertion(acpi_handle handle)
 		printk(KERN_ERR "cannot start bridge\n");
 }
 
+static int acpi_root_evaluate_object(acpi_handle handle, char *cmd, int val)
+{
+	acpi_status status;
+	struct acpi_object_list arg_list;
+	union acpi_object arg;
+
+	arg_list.count = 1;
+	arg_list.pointer = &arg;
+	arg.type = ACPI_TYPE_INTEGER;
+	arg.integer.value = val;
+
+	status = acpi_evaluate_object(handle, cmd, &arg_list, NULL);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_WARNING "%s: %s to %d failed\n",
+				 __func__, cmd, val);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void handle_root_bridge_removal(acpi_handle handle,
+		 struct acpi_root_bridge *bridge)
+{
+	u32 flags = 0;
+	struct acpi_device *device;
+
+	if (bridge) {
+		flags = bridge->flags;
+		remove_acpi_root_bridge(bridge);
+	}
+
+	if (!acpi_bus_get_device(handle, &device)) {
+		int ret_val;
+
+		/* remove pci devices at first */
+		ret_val = acpi_bus_trim(device, 0);
+		printk(KERN_DEBUG "acpi_bus_trim stop return %x\n", ret_val);
+
+		/* remove acpi devices */
+		ret_val = acpi_bus_trim(device, 1);
+		printk(KERN_DEBUG "acpi_bus_trim remove return %x\n", ret_val);
+	}
+
+	if (flags & ROOT_BRIDGE_HAS_PS3) {
+		acpi_status status;
+
+		status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
+		if (ACPI_FAILURE(status))
+			printk(KERN_WARNING "%s: _PS3 failed\n", __func__);
+	}
+	if (flags & ROOT_BRIDGE_HAS_EJ0)
+		acpi_root_evaluate_object(handle, "_EJ0", 1);
+}
+
 static void _handle_hotplug_event_root(struct work_struct *work)
 {
 	struct acpi_root_bridge *bridge;
@@ -183,6 +244,12 @@ static void _handle_hotplug_event_root(struct work_struct *work)
 		}
 		break;
 
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		/* request device eject */
+		printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__,
+				 objname);
+		handle_root_bridge_removal(handle, bridge);
+		break;
 	default:
 		printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
 				 type, objname);
-- 
1.7.7


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

* [PATCH 29/40] PCI, ACPI: Add alloc_acpi_hp_work()
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (27 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 28/40] PCI, ACPI: Add pci_root_hp hot removal notification support Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 30/40] PCI, acpiphp: Use acpi_hp_work Yinghai Lu
                             ` (11 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Will use it with acpiphp and pci_root_hp events handling

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
---
 drivers/acpi/osl.c      |   21 +++++++++++++++++++++
 include/acpi/acpiosxf.h |    9 +++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 9eaf708..0719fa7 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1592,3 +1592,24 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 {
 	__acpi_os_prepare_sleep = func;
 }
+
+void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
+			void (*func)(struct work_struct *work))
+{
+	struct acpi_hp_work *hp_work;
+	int ret;
+
+	hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
+	if (!hp_work)
+		return;
+
+	hp_work->handle = handle;
+	hp_work->type = type;
+	hp_work->context = context;
+
+	INIT_WORK(&hp_work->work, func);
+	ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
+	if (!ret)
+		kfree(hp_work);
+}
+EXPORT_SYMBOL(alloc_acpi_hp_work);
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 0650f5f..6ff92ea 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -196,6 +196,15 @@ void acpi_os_fixed_event_count(u32 fixed_event_number);
  */
 extern struct workqueue_struct *kacpi_hotplug_wq;
 
+struct acpi_hp_work {
+	struct work_struct work;
+	acpi_handle handle;
+	u32 type;
+	void *context;
+};
+void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
+			void (*func)(struct work_struct *work));
+
 acpi_thread_id acpi_os_get_thread_id(void);
 
 acpi_status
-- 
1.7.7


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

* [PATCH 30/40] PCI, acpiphp: Use acpi_hp_work
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (28 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 29/40] PCI, ACPI: Add alloc_acpi_hp_work() Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 31/40] PCI, pci_root_hp: " Yinghai Lu
                             ` (10 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Remove local defined acpiphp_hp_work.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
---
 drivers/pci/hotplug/acpiphp_glue.c |   42 +++++------------------------------
 1 files changed, 6 insertions(+), 36 deletions(-)

diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 201c5f7..e9e2e06 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1189,34 +1189,6 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
 	return AE_OK ;
 }
 
-struct acpiphp_hp_work {
-	struct work_struct work;
-	acpi_handle handle;
-	u32 type;
-	void *context;
-};
-
-static void alloc_acpiphp_hp_work(acpi_handle handle, u32 type,
-				  void *context,
-				  void (*func)(struct work_struct *work))
-{
-	struct acpiphp_hp_work *hp_work;
-	int ret;
-
-	hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
-	if (!hp_work)
-		return;
-
-	hp_work->handle = handle;
-	hp_work->type = type;
-	hp_work->context = context;
-
-	INIT_WORK(&hp_work->work, func);
-	ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
-	if (!ret)
-		kfree(hp_work);
-}
-
 static void _handle_hotplug_event_bridge(struct work_struct *work)
 {
 	struct acpiphp_bridge *bridge;
@@ -1225,11 +1197,11 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
 				      .pointer = objname };
 	struct acpi_device *device;
 	int num_sub_bridges = 0;
-	struct acpiphp_hp_work *hp_work;
+	struct acpi_hp_work *hp_work;
 	acpi_handle handle;
 	u32 type;
 
-	hp_work = container_of(work, struct acpiphp_hp_work, work);
+	hp_work = container_of(work, struct acpi_hp_work, work);
 	handle = hp_work->handle;
 	type = hp_work->type;
 
@@ -1332,8 +1304,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
 	 * For now just re-add this work to the kacpi_hotplug_wq so we
 	 * don't deadlock on hotplug actions.
 	 */
-	alloc_acpiphp_hp_work(handle, type, context,
-			      _handle_hotplug_event_bridge);
+	alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
 }
 
 static void _handle_hotplug_event_func(struct work_struct *work)
@@ -1342,12 +1313,12 @@ static void _handle_hotplug_event_func(struct work_struct *work)
 	char objname[64];
 	struct acpi_buffer buffer = { .length = sizeof(objname),
 				      .pointer = objname };
-	struct acpiphp_hp_work *hp_work;
+	struct acpi_hp_work *hp_work;
 	acpi_handle handle;
 	u32 type;
 	void *context;
 
-	hp_work = container_of(work, struct acpiphp_hp_work, work);
+	hp_work = container_of(work, struct acpi_hp_work, work);
 	handle = hp_work->handle;
 	type = hp_work->type;
 	context = hp_work->context;
@@ -1408,8 +1379,7 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
 	 * For now just re-add this work to the kacpi_hotplug_wq so we
 	 * don't deadlock on hotplug actions.
 	 */
-	alloc_acpiphp_hp_work(handle, type, context,
-			      _handle_hotplug_event_func);
+	alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
 }
 
 static struct acpi_pci_driver acpi_pci_hp_driver = {
-- 
1.7.7


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

* [PATCH 31/40] PCI, pci_root_hp: Use acpi_hp_work
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (29 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 30/40] PCI, acpiphp: Use acpi_hp_work Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 32/40] PCI, ACPI: Make kacpi_hotplug_wq static Yinghai Lu
                             ` (9 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Remove local copy: acpi_root_hp_work

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
---
 drivers/acpi/pci_root_hp.c |   34 +++-------------------------------
 1 files changed, 3 insertions(+), 31 deletions(-)

diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c
index 434ee35..e573298 100644
--- a/drivers/acpi/pci_root_hp.c
+++ b/drivers/acpi/pci_root_hp.c
@@ -79,34 +79,6 @@ static void remove_acpi_root_bridge(struct acpi_root_bridge *bridge)
 	kfree(bridge);
 }
 
-struct acpi_root_hp_work {
-	struct work_struct work;
-	acpi_handle handle;
-	u32 type;
-	void *context;
-};
-
-static void alloc_acpi_root_hp_work(acpi_handle handle, u32 type,
-					void *context,
-					void (*func)(struct work_struct *work))
-{
-	struct acpi_root_hp_work *hp_work;
-	int ret;
-
-	hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
-	if (!hp_work)
-		return;
-
-	hp_work->handle = handle;
-	hp_work->type = type;
-	hp_work->context = context;
-
-	INIT_WORK(&hp_work->work, func);
-	ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
-	if (!ret)
-		kfree(hp_work);
-}
-
 /* Program resources in newly inserted bridge */
 static void acpi_root_configure_bridge(struct acpi_device *device)
 {
@@ -210,11 +182,11 @@ static void _handle_hotplug_event_root(struct work_struct *work)
 	char objname[64];
 	struct acpi_buffer buffer = { .length = sizeof(objname),
 				      .pointer = objname };
-	struct acpi_root_hp_work *hp_work;
+	struct acpi_hp_work *hp_work;
 	acpi_handle handle;
 	u32 type;
 
-	hp_work = container_of(work, struct acpi_root_hp_work, work);
+	hp_work = container_of(work, struct acpi_hp_work, work);
 	handle = hp_work->handle;
 	type = hp_work->type;
 
@@ -262,7 +234,7 @@ static void _handle_hotplug_event_root(struct work_struct *work)
 static void handle_hotplug_event_root(acpi_handle handle, u32 type,
 					void *context)
 {
-	alloc_acpi_root_hp_work(handle, type, context,
+	alloc_acpi_hp_work(handle, type, context,
 				_handle_hotplug_event_root);
 }
 
-- 
1.7.7


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

* [PATCH 32/40] PCI, ACPI: Make kacpi_hotplug_wq static
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (30 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 31/40] PCI, pci_root_hp: " Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 33/40] ACPI, PCI: Use normal list for struct acpi_pci_driver Yinghai Lu
                             ` (8 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

No external user anymore.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
---
 drivers/acpi/osl.c      |    3 +--
 include/acpi/acpiosxf.h |    2 --
 2 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 0719fa7..311a921 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -84,8 +84,7 @@ static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
-struct workqueue_struct *kacpi_hotplug_wq;
-EXPORT_SYMBOL(kacpi_hotplug_wq);
+static struct workqueue_struct *kacpi_hotplug_wq;
 
 /*
  * This list of permanent mappings is for memory that may be accessed from
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 6ff92ea..9f68f69 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -194,8 +194,6 @@ void acpi_os_fixed_event_count(u32 fixed_event_number);
 /*
  * Threads and Scheduling
  */
-extern struct workqueue_struct *kacpi_hotplug_wq;
-
 struct acpi_hp_work {
 	struct work_struct work;
 	acpi_handle handle;
-- 
1.7.7


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

* [PATCH 33/40] ACPI, PCI: Use normal list for struct acpi_pci_driver
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (31 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 32/40] PCI, ACPI: Make kacpi_hotplug_wq static Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 34/40] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Yinghai Lu
                             ` (7 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

From: Jiang Liu <jiang.liu@huawei.com>

Use normal list for struct acpi_pci_driver to simplify code.

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c |   16 +++-------------
 include/linux/acpi.h    |    2 +-
 2 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index b72c85c..325cf5c 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -72,8 +72,8 @@ static struct acpi_driver acpi_pci_root_driver = {
 };
 
 static LIST_HEAD(acpi_pci_roots);
+static LIST_HEAD(acpi_pci_drivers);
 
-static struct acpi_pci_driver *sub_driver;
 static DEFINE_MUTEX(osc_lock);
 
 int acpi_pci_register_driver(struct acpi_pci_driver *driver)
@@ -81,10 +81,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
 	int n = 0;
 	struct acpi_pci_root *root;
 
-	struct acpi_pci_driver **pptr = &sub_driver;
-	while (*pptr)
-		pptr = &(*pptr)->next;
-	*pptr = driver;
+	list_add_tail(&driver->node, &acpi_pci_drivers);
 
 	if (!driver->add)
 		return 0;
@@ -103,14 +100,7 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 {
 	struct acpi_pci_root *root;
 
-	struct acpi_pci_driver **pptr = &sub_driver;
-	while (*pptr) {
-		if (*pptr == driver)
-			break;
-		pptr = &(*pptr)->next;
-	}
-	BUG_ON(!*pptr);
-	*pptr = (*pptr)->next;
+	list_del(&driver->node);
 
 	if (!driver->remove)
 		return;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index a686098..90be989 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -138,7 +138,7 @@ void acpi_penalize_isa_irq(int irq, int active);
 void acpi_pci_irq_disable (struct pci_dev *dev);
 
 struct acpi_pci_driver {
-	struct acpi_pci_driver *next;
+	struct list_head node;
 	int (*add)(struct acpi_pci_root *root);
 	void (*remove)(struct acpi_pci_root *root);
 };
-- 
1.7.7


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

* [PATCH 34/40] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (32 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 33/40] ACPI, PCI: Use normal list for struct acpi_pci_driver Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 35/40] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c Yinghai Lu
                             ` (6 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

From: Jiang Liu <jiang.liu@huawei.com>

When hot-plugging PCI root bridge, acpi_pci_drivers' add()/remove()
methods should be invoked to notify registered drivers.

-v2: Move add calling to acpi_pci_root_start - Yinghai
-v3: use acpi_pci_root pointer instead of handle - Yinghai
-v3: Fold stop ioapic/iommu drivers after pci devices change in. - Yinghai

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 325cf5c..0ea5ad0 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -633,6 +633,11 @@ end:
 static int acpi_pci_root_start(struct acpi_device *device)
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);
+	struct acpi_pci_driver *driver;
+
+	list_for_each_entry(driver, &acpi_pci_drivers, node)
+		if (driver->add)
+			driver->add(root);
 
 	pci_bus_add_devices(root->bus);
 	return 0;
@@ -643,6 +648,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
 	acpi_status status;
 	acpi_handle handle;
 	struct acpi_pci_root *root = acpi_driver_data(device);
+	struct acpi_pci_driver *driver;
 
 	/* that root bus could be removed already */
 	if (!pci_find_bus(root->segment, root->secondary.start)) {
@@ -651,8 +657,13 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
 		goto out;
 	}
 
+	/* stop normal pci drivers before we stop ioapic and dmar etc */
 	pci_stop_root_bus(root->bus);
 
+	list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
+		if (driver->remove)
+			driver->remove(root);
+
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
-- 
1.7.7


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

* [PATCH 35/40] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (33 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 34/40] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 36/40] PCI: Set dev_node early for pci_dev Yinghai Lu
                             ` (5 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

From: Jiang Liu <jiang.liu@huawei.com>

There are two global lists inf file drivers/acpi/pci_root.c.
One is for registered acpi_pci_drivers, the other is for
enumerated ACPI PCI root bridge objects. These two global
lists may change dynamically when registering/deregistering
acpi_pci_drivers or adding/removing ACPI PCI root bridge
objects. So protect them by mutex lock.

-v2: remove -rcu

Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c |   70 +++++++++++++++++++++++++++--------------------
 1 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 0ea5ad0..67f7733 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -27,7 +27,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci.h>
@@ -71,6 +71,8 @@ static struct acpi_driver acpi_pci_root_driver = {
 		},
 };
 
+/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
+static DEFINE_MUTEX(acpi_pci_root_lock);
 static LIST_HEAD(acpi_pci_roots);
 static LIST_HEAD(acpi_pci_drivers);
 
@@ -81,47 +83,46 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
 	int n = 0;
 	struct acpi_pci_root *root;
 
+	mutex_lock(&acpi_pci_root_lock);
 	list_add_tail(&driver->node, &acpi_pci_drivers);
-
-	if (!driver->add)
-		return 0;
-
-	list_for_each_entry(root, &acpi_pci_roots, node) {
-		driver->add(root);
-		n++;
-	}
+	if (driver->add)
+		list_for_each_entry(root, &acpi_pci_roots, node) {
+			driver->add(root);
+			n++;
+		}
+	mutex_unlock(&acpi_pci_root_lock);
 
 	return n;
 }
-
 EXPORT_SYMBOL(acpi_pci_register_driver);
 
 void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 {
 	struct acpi_pci_root *root;
 
+	mutex_lock(&acpi_pci_root_lock);
 	list_del(&driver->node);
-
-	if (!driver->remove)
-		return;
-
-	list_for_each_entry(root, &acpi_pci_roots, node)
-		driver->remove(root);
+	if (driver->remove)
+		list_for_each_entry(root, &acpi_pci_roots, node)
+			driver->remove(root);
+	mutex_unlock(&acpi_pci_root_lock);
 }
-
 EXPORT_SYMBOL(acpi_pci_unregister_driver);
 
 acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
 {
 	struct acpi_pci_root *root;
-	
+	struct acpi_handle *handle = NULL;
+
 	list_for_each_entry(root, &acpi_pci_roots, node)
 		if ((root->segment == (u16) seg) &&
-		    (root->secondary.start == (u16) bus))
-			return root->device->handle;
-	return NULL;		
-}
+		    (root->secondary.start == (u16) bus)) {
+			handle = root->device->handle;
+			break;
+		}
 
+	return handle;
+}
 EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
 
 /**
@@ -459,7 +460,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
 		printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
 		result = -ENODEV;
-		goto end;
+		goto out_free;
 	}
 
 	/* Check _CRS first, then _BBN.  If no _BBN, default to zero. */
@@ -484,7 +485,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 		else {
 			printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
 			result = -ENODEV;
-			goto end;
+			goto out_free;
 		}
 	}
 
@@ -508,7 +509,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	 * TBD: Need PCI interface for enumeration/configuration of roots.
 	 */
 
-	/* TBD: Locking */
+	mutex_lock(&acpi_pci_root_lock);
 	list_add_tail(&root->node, &acpi_pci_roots);
 
 	printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
@@ -528,7 +529,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 			    "Bus %04x:%02x not present in PCI namespace\n",
 			    root->segment, (unsigned int)root->secondary.start);
 		result = -ENODEV;
-		goto end;
+		goto out_del_root;
 	}
 
 	/*
@@ -538,7 +539,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	 */
 	result = acpi_pci_bind_root(device);
 	if (result)
-		goto end;
+		goto out_del_root;
 
 	/*
 	 * PCI Routing Table
@@ -621,11 +622,14 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	if (device->wakeup.flags.run_wake)
 		device_set_run_wake(root->bus->bridge, true);
 
+	mutex_unlock(&acpi_pci_root_lock);
+
 	return 0;
 
-end:
-	if (!list_empty(&root->node))
-		list_del(&root->node);
+out_del_root:
+	list_del(&root->node);
+	mutex_unlock(&acpi_pci_root_lock);
+out_free:
 	kfree(root);
 	return result;
 }
@@ -635,11 +639,14 @@ static int acpi_pci_root_start(struct acpi_device *device)
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
+	mutex_lock(&acpi_pci_root_lock);
 	list_for_each_entry(driver, &acpi_pci_drivers, node)
 		if (driver->add)
 			driver->add(root);
 
 	pci_bus_add_devices(root->bus);
+	mutex_unlock(&acpi_pci_root_lock);
+
 	return 0;
 }
 
@@ -650,6 +657,8 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
 	struct acpi_pci_root *root = acpi_driver_data(device);
 	struct acpi_pci_driver *driver;
 
+	mutex_lock(&acpi_pci_root_lock);
+
 	/* that root bus could be removed already */
 	if (!pci_find_bus(root->segment, root->secondary.start)) {
 		dev_printk(KERN_DEBUG, &device->dev,
@@ -677,6 +686,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
 
 out:
 	list_del(&root->node);
+	mutex_unlock(&acpi_pci_root_lock);
 	kfree(root);
 
 	return 0;
-- 
1.7.7


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

* [PATCH 36/40] PCI: Set dev_node early for pci_dev
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (34 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 35/40] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 37/40] PCI, x86: Move pci_enable_bridges() down Yinghai Lu
                             ` (4 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

otherwise irq_desc for pci bridge with hot-added ioapic can not be
on local node.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/probe.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ab845aa..460ac84 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1295,6 +1295,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 	dev->dev.release = pci_release_dev;
 	pci_dev_get(dev);
 
+	set_dev_node(&dev->dev, pcibus_to_node(bus));
 	dev->dev.dma_mask = &dev->dma_mask;
 	dev->dev.dma_parms = &dev->dma_parms;
 	dev->dev.coherent_dma_mask = 0xffffffffull;
-- 
1.7.7


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

* [PATCH 37/40] PCI, x86: Move pci_enable_bridges() down
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (35 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 36/40] PCI: Set dev_node early for pci_dev Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 38/40] ACPI, PCI: Skip extra pci_enable_bridges for non hot-add root Yinghai Lu
                             ` (3 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

After we get hot-added ioapic registered.

pci_enable_bridges will try to enable ioapic irq for pci bridge.

So need to move it down.

Or We can move out pcibios_enable_irq() out of pci_enable_device()
and call pcibios_enable_irq in pci_bus_add_devices ?
also will need to move ...
        pcibios_resource_survey_bus(root->bus);
        pci_assign_unassigned_bus_resources(root->bus);
to the start add ....

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c |    3 +++
 drivers/pci/probe.c     |    1 +
 drivers/pci/setup-bus.c |    2 --
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 67f7733..670511f 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -644,6 +644,9 @@ static int acpi_pci_root_start(struct acpi_device *device)
 		if (driver->add)
 			driver->add(root);
 
+	/* need to after hot-added ioapic is registered */
+	pci_enable_bridges(root->bus);
+
 	pci_bus_add_devices(root->bus);
 	mutex_unlock(&acpi_pci_root_lock);
 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 460ac84..5975fd5 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1905,6 +1905,7 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
 
 	max = pci_scan_child_bus(bus);
 	pci_assign_unassigned_bus_resources(bus);
+	pci_enable_bridges(bus);
 	pci_bus_add_devices(bus);
 
 	return max;
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 56155c9..63cb3ba 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1566,6 +1566,4 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
 	up_read(&pci_bus_sem);
 	__pci_bus_assign_resources(bus, &add_list, NULL);
 	BUG_ON(!list_empty(&add_list));
-
-	pci_enable_bridges(bus);
 }
-- 
1.7.7


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

* [PATCH 38/40] ACPI, PCI: Skip extra pci_enable_bridges for non hot-add root
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (36 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 37/40] PCI, x86: Move pci_enable_bridges() down Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 39/40] PCI, acpiphp: Don't ailout even no slots found yet Yinghai Lu
                             ` (2 subsequent siblings)
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Pre-installed will be handled later, need to skip the one only for hot-added
roots.

Otherwise will get anonying failing message about can not reserve, irq ...

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c    |    3 ++-
 drivers/acpi/pci_root_hp.c |    1 +
 include/acpi/acpi_bus.h    |    1 +
 3 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 670511f..6151d83 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -645,7 +645,8 @@ static int acpi_pci_root_start(struct acpi_device *device)
 			driver->add(root);
 
 	/* need to after hot-added ioapic is registered */
-	pci_enable_bridges(root->bus);
+	if (root->hot_added)
+		pci_enable_bridges(root->bus);
 
 	pci_bus_add_devices(root->bus);
 	mutex_unlock(&acpi_pci_root_lock);
diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c
index e573298..1f60533 100644
--- a/drivers/acpi/pci_root_hp.c
+++ b/drivers/acpi/pci_root_hp.c
@@ -86,6 +86,7 @@ static void acpi_root_configure_bridge(struct acpi_device *device)
 
 	pcibios_resource_survey_bus(root->bus);
 	pci_assign_unassigned_bus_resources(root->bus);
+	root->hot_added = true;
 }
 
 static void handle_root_bridge_insertion(acpi_handle handle)
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index bde976e..47de196 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -406,6 +406,7 @@ struct acpi_pci_root {
 
 	u32 osc_support_set;	/* _OSC state of support bits */
 	u32 osc_control_set;	/* _OSC state of control bits */
+	bool hot_added;
 	phys_addr_t mcfg_addr;
 };
 
-- 
1.7.7


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

* [PATCH 39/40] PCI, acpiphp: Don't ailout even no slots found yet.
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (37 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 38/40] ACPI, PCI: Skip extra pci_enable_bridges for non hot-add root Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-09-19 18:54           ` [PATCH 40/40] ACPI: Enable SCI_EMULATE to manually simulate physical hotplug testing Yinghai Lu
  2012-10-17  7:50           ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yijing Wang
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Yinghai Lu

Could have root bus hot add later and there may be slot there that need acpiphp.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/hotplug/acpiphp.h      |    1 -
 drivers/pci/hotplug/acpiphp_core.c |   23 ++---------------------
 drivers/pci/hotplug/acpiphp_glue.c |   22 ----------------------
 3 files changed, 2 insertions(+), 44 deletions(-)

diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index a1afb5b..b3ead7a 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -193,7 +193,6 @@ extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
 /* acpiphp_glue.c */
 extern int acpiphp_glue_init (void);
 extern void acpiphp_glue_exit (void);
-extern int acpiphp_get_num_slots (void);
 typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
 
 extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 96316b7..c2fd309 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -50,7 +50,6 @@
 bool acpiphp_debug;
 
 /* local variables */
-static int num_slots;
 static struct acpiphp_attention_info *attention_info;
 
 #define DRIVER_VERSION	"0.5"
@@ -272,25 +271,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 	return 0;
 }
 
-static int __init init_acpi(void)
-{
-	int retval;
-
-	/* initialize internal data structure etc. */
-	retval = acpiphp_glue_init();
-
-	/* read initial number of slots */
-	if (!retval) {
-		num_slots = acpiphp_get_num_slots();
-		if (num_slots == 0) {
-			acpiphp_glue_exit();
-			retval = -ENODEV;
-		}
-	}
-
-	return retval;
-}
-
 /**
  * release_slot - free up the memory used by a slot
  * @hotplug_slot: slot to free
@@ -379,7 +359,8 @@ static int __init acpiphp_init(void)
 		return 0;
 
 	/* read all the ACPI info from the system */
-	return init_acpi();
+	/* initialize internal data structure etc. */
+	return acpiphp_glue_init();
 }
 
 
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index e9e2e06..1f26706 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1408,28 +1408,6 @@ void  acpiphp_glue_exit(void)
 	acpi_pci_unregister_driver(&acpi_pci_hp_driver);
 }
 
-
-/**
- * acpiphp_get_num_slots - count number of slots in a system
- */
-int __init acpiphp_get_num_slots(void)
-{
-	struct acpiphp_bridge *bridge;
-	int num_slots = 0;
-
-	list_for_each_entry(bridge, &bridge_list, list) {
-		dbg("Bus %04x:%02x has %d slot%s\n",
-				pci_domain_nr(bridge->pci_bus),
-				bridge->pci_bus->number, bridge->nr_slots,
-				bridge->nr_slots == 1 ? "" : "s");
-		num_slots += bridge->nr_slots;
-	}
-
-	dbg("Total %d slots\n", num_slots);
-	return num_slots;
-}
-
-
 /**
  * acpiphp_enable_slot - power on slot
  * @slot: ACPI PHP slot
-- 
1.7.7


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

* [PATCH 40/40] ACPI: Enable SCI_EMULATE to manually simulate physical hotplug testing.
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (38 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 39/40] PCI, acpiphp: Don't ailout even no slots found yet Yinghai Lu
@ 2012-09-19 18:54           ` Yinghai Lu
  2012-10-17  7:50           ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yijing Wang
  40 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-19 18:54 UTC (permalink / raw)
  To: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86
  Cc: Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Ashok Raj, Yinghai Lu

From: Ashok Raj <ashok.raj@intel.com>

Emulate an ACPI SCI interrupt to emulate a hot-plug event. Useful
for testing ACPI based hot-plug on systems that don't have the
necessary firmware support.

Enable CONFIG_ACPI_SCI_EMULATE on kernel compile.

Now you will notice /sys/kernel/debug/acpi/sci_notify when new kernel is
booted.

echo "\_SB.PCIB 1" > /sys/kernel/debug/acpi/sci_notify to trigger a hot-add
of root bus that is corresponding to PCIB.

echo "\_SB.PCIB 3" > /sys/kernel/debug/acpi/sci_notify to trigger a hot-remove
of root bus that is corresponding to PCIB.

-v2: Update to current upstream, and remove not related stuff.
-v3: According to Len's request, update it to use debugfs.  - Yinghai Lu

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org

===================================================================
---
 drivers/acpi/Kconfig   |   10 +++
 drivers/acpi/Makefile  |    1 +
 drivers/acpi/sci_emu.c |  145 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+), 0 deletions(-)
 create mode 100644 drivers/acpi/sci_emu.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 8099895..227f7ee 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -272,6 +272,16 @@ config ACPI_BLACKLIST_YEAR
 	  Enter 0 to disable this mechanism and allow ACPI to
 	  run by default no matter what the year.  (default)
 
+config ACPI_SCI_EMULATE
+        bool "ACPI SCI Event Emulation Support"
+        depends on DEBUG_FS
+	default n
+	help
+	  This will enable your system to emulate sci hotplug event
+	  notification through proc file system. For example user needs to
+	  echo "XXX 0" > /sys/kernel/debug/acpi/sci_notify (where, XXX is
+	  a target ACPI device object name present under \_SB scope).
+
 config ACPI_DEBUG
 	bool "Debug Statements"
 	default n
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index c9abd4c..40b3021 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -31,6 +31,7 @@ acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o
 # ACPI Bus and Device Drivers
 #
 acpi-y				+= bus.o glue.o
+acpi-$(CONFIG_ACPI_SCI_EMULATE)	+= sci_emu.o
 acpi-y				+= scan.o
 acpi-y				+= processor_core.o
 acpi-y				+= ec.o
diff --git a/drivers/acpi/sci_emu.c b/drivers/acpi/sci_emu.c
new file mode 100644
index 0000000..2f13ca1
--- /dev/null
+++ b/drivers/acpi/sci_emu.c
@@ -0,0 +1,145 @@
+/*
+ *  Code to emulate SCI interrupt for Hotplug node insertion/removal
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <acpi/acpi_drivers.h>
+
+#include "internal.h"
+
+#include "acpica/accommon.h"
+#include "acpica/acnamesp.h"
+#include "acpica/acevents.h"
+
+#define _COMPONENT		ACPI_SYSTEM_COMPONENT
+ACPI_MODULE_NAME("sci_emu");
+MODULE_LICENSE("GPL");
+
+static struct dentry *sci_notify_dentry;
+
+static void sci_notify_client(char *acpi_name, u32 event)
+{
+	struct acpi_namespace_node *node;
+	acpi_status status, status1;
+	acpi_handle hlsb, hsb;
+	union acpi_operand_object *obj_desc;
+
+	status = acpi_get_handle(NULL, "\\_SB", &hsb);
+	status1 = acpi_get_handle(hsb, acpi_name, &hlsb);
+	if (ACPI_FAILURE(status) || ACPI_FAILURE(status1)) {
+		pr_err(PREFIX
+	"acpi getting handle to <\\_SB.%s> failed inside notify_client\n",
+			acpi_name);
+		return;
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		pr_err(PREFIX "Acquiring acpi namespace mutext failed\n");
+		return;
+	}
+
+	node = acpi_ns_validate_handle(hlsb);
+	if (!node) {
+		acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+		pr_err(PREFIX "Mapping handle to node failed\n");
+		return;
+	}
+
+	/*
+	 * Check for internal object and make sure there is a handler
+	 * registered for this object
+	 */
+	obj_desc = acpi_ns_get_attached_object(node);
+	if (obj_desc) {
+		if (obj_desc->common_notify.notify_list[0]) {
+			/*
+			 * Release the lock and queue the item for later
+			 * exectuion
+			 */
+			acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+			status = acpi_ev_queue_notify_request(node, event);
+			if (ACPI_FAILURE(status))
+				pr_err(PREFIX "acpi_ev_queue_notify_request failed\n");
+			else
+				pr_info(PREFIX "Notify event is queued\n");
+			return;
+		}
+	} else {
+		pr_info(PREFIX "Notify handler not registered for this device\n");
+	}
+
+	acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+	return;
+}
+
+static ssize_t sci_notify_write(struct file *file, const char __user *user_buf,
+				 size_t count, loff_t *ppos)
+{
+	u32 event;
+	char *name1 = NULL;
+	char *name2 = NULL;
+	const char *delim = " ";
+	char *temp_buf = NULL;
+	char *temp_buf_addr = NULL;
+
+	temp_buf = kmalloc(count+1, GFP_ATOMIC);
+	if (!temp_buf) {
+		pr_warn(PREFIX "sci_notify_wire: Memory allocation failed\n");
+		return count;
+	}
+	temp_buf[count] = '\0';
+	temp_buf_addr = temp_buf;
+	if (copy_from_user(temp_buf, user_buf, count))
+		goto out;
+
+	name1 = strsep(&temp_buf, delim);
+	name2 = strsep(&temp_buf, delim);
+
+	if (name1 && name2) {
+		ssize_t ret;
+		unsigned long val;
+
+		ret = kstrtoul(name2, 10, &val);
+		if (ret) {
+			pr_warn(PREFIX "unknown event\n");
+			goto out;
+		}
+
+		event = (u32)val;
+	} else {
+		pr_warn(PREFIX "unknown device\n");
+		goto out;
+	}
+
+	pr_info(PREFIX "ACPI device name is <%s>, event code is <%d>\n",
+		name1, event);
+
+	sci_notify_client(name1, event);
+
+out:
+	kfree(temp_buf_addr);
+	return count;
+}
+
+static const struct file_operations sci_notify_fops = {
+	.write = sci_notify_write,
+};
+
+static int __init acpi_sci_notify_init(void)
+{
+	if (acpi_debugfs_dir == NULL)
+		return -ENOENT;
+
+	sci_notify_dentry = debugfs_create_file("sci_notify", S_IWUSR,
+				acpi_debugfs_dir, NULL, &sci_notify_fops);
+	if (sci_notify_dentry == NULL)
+		return -ENODEV;
+
+	return 0;
+}
+
+device_initcall(acpi_sci_notify_init);
-- 
1.7.7


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

* Re: [PATCH 01/40] PCI: fix default vga ref_count
  2012-09-19 18:54           ` [PATCH 01/40] PCI: fix default vga ref_count Yinghai Lu
@ 2012-09-21 20:52             ` Bjorn Helgaas
  2012-09-21 21:18               ` Yinghai Lu
  2012-09-23 15:25             ` Jiang Liu
  1 sibling, 1 reply; 60+ messages in thread
From: Bjorn Helgaas @ 2012-09-21 20:52 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Len Brown, Taku Izumi, Jiang Liu, x86, Andrew Morton,
	Linus Torvalds, Greg Kroah-Hartman, linux-pci, linux-kernel,
	linux-acpi, Dave Airlie, Julia Lawall, Matthew Garrett

On Wed, Sep 19, 2012 at 12:54 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> when __ARCH_HAS_VGA_DEFAULT_DEVICE is not defined, aka EFIFB is not used,
> for static path, vga_default setting is through vga_arbiter_add_pci_device.
> and later x86 pci_fixup_video, will skip setting again.
> - subsys_initcall(vga_arb_device_init) come first to call vga_arbiter_add_pci_device. It will call pci_get_dev to hold one reference.
>
> for hotplug add path, even vga_arbiter_add_pci_device is called via notifier,
> but it will check VGA_RSRC_LEGACY_MASK that is not set for hotplug path.
> So x86 pci_fixup_video will take over to call vga_set_default_device().
> It will not hold one refrence.
>
> Later for hotplug remove path, vga_arbiter_del_pci_device that does not check
> VGA_RSRC_LEGACY_MASK will call put_device and it will cause ref_count to
> decrease extra. that will have that pci device get deleted early wrongly.
>
> Need to make get/put balance for both cases.
>
> -v2: According to Bjorn, update vga_set_default_device instead...
>
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> Cc: x86@kernel.org
> Cc: Dave Airlie <airlied@redhat.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Julia Lawall <julia@diku.dk>
> Cc: Matthew Garrett <mjg@redhat.com>
> ---
>  drivers/gpu/vga/vgaarb.c |   14 +++++++++-----
>  1 files changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
> index b6852b7..0888951e 100644
> --- a/drivers/gpu/vga/vgaarb.c
> +++ b/drivers/gpu/vga/vgaarb.c
> @@ -141,6 +141,12 @@ EXPORT_SYMBOL_GPL(vga_default_device);
>
>  void vga_set_default_device(struct pci_dev *pdev)
>  {
> +       if (vga_default)
> +               pci_dev_put(vga_default);
> +
> +       if (pdev)
> +               pdev = pci_dev_get(pdev);
> +
>         vga_default = pdev;

I think this is equivalent to:

    pci_dev_put(vga_default);
    vga_default = pci_dev_get(pdev);

I haven't seen an answer to Matthew's question about whether we want
to check for "vga_default == pdev".

>  }
>  #endif
> @@ -577,7 +583,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
>  #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
>         if (vga_default == NULL &&
>             ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK))
> -               vga_default = pci_dev_get(pdev);
> +               vga_set_default_device(pdev);
>  #endif
>
>         vga_arbiter_check_bridge_sharing(vgadev);
> @@ -613,10 +619,8 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
>         }
>
>  #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
> -       if (vga_default == pdev) {
> -               pci_dev_put(vga_default);
> -               vga_default = NULL;
> -       }
> +       if (vga_default == pdev)
> +               vga_set_default_device(NULL);
>  #endif
>
>         if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
> --
> 1.7.7
>

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

* Re: [PATCH 01/40] PCI: fix default vga ref_count
  2012-09-21 20:52             ` Bjorn Helgaas
@ 2012-09-21 21:18               ` Yinghai Lu
  0 siblings, 0 replies; 60+ messages in thread
From: Yinghai Lu @ 2012-09-21 21:18 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Len Brown, Taku Izumi, Jiang Liu, x86, Andrew Morton,
	Linus Torvalds, Greg Kroah-Hartman, linux-pci, linux-kernel,
	linux-acpi, Dave Airlie, Julia Lawall, Matthew Garrett

[-- Attachment #1: Type: text/plain, Size: 900 bytes --]

On Fri, Sep 21, 2012 at 1:52 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> On Wed, Sep 19, 2012 at 12:54 PM, Yinghai Lu <yinghai@kernel.org> wrote:
>> --- a/drivers/gpu/vga/vgaarb.c
>> +++ b/drivers/gpu/vga/vgaarb.c
>> @@ -141,6 +141,12 @@ EXPORT_SYMBOL_GPL(vga_default_device);
>>
>>  void vga_set_default_device(struct pci_dev *pdev)
>>  {
>> +       if (vga_default)
>> +               pci_dev_put(vga_default);
>> +
>> +       if (pdev)
>> +               pdev = pci_dev_get(pdev);
>> +
>>         vga_default = pdev;
>
> I think this is equivalent to:
>
>     pci_dev_put(vga_default);
>     vga_default = pci_dev_get(pdev);

ah, i missed that, pci_dev_put and pci_dev_get check that inside.

>
> I haven't seen an answer to Matthew's question about whether we want
> to check for "vga_default == pdev".

yes, that could avoid the extra put/get pair.

Please check updated version.

-Yinghai

[-- Attachment #2: fix_vgarab_add_x.patch --]
[-- Type: application/octet-stream, Size: 2560 bytes --]

Subject: [PATCH] PCI: fix default vga ref_count

when __ARCH_HAS_VGA_DEFAULT_DEVICE is not defined, aka EFIFB is not used,
for static path, vga_default setting is through vga_arbiter_add_pci_device.
and later x86 pci_fixup_video, will skip setting again.
- subsys_initcall(vga_arb_device_init) come first to call vga_arbiter_add_pci_device. It will call pci_get_dev to hold one reference.

for hotplug add path, even vga_arbiter_add_pci_device is called via notifier,
but it will check VGA_RSRC_LEGACY_MASK that is not set for hotplug path.
So x86 pci_fixup_video will take over to call vga_set_default_device().
It will not hold one refrence.

Later for hotplug remove path, vga_arbiter_del_pci_device that does not check
VGA_RSRC_LEGACY_MASK will call put_device and it will cause ref_count to
decrease extra. that will have that pci device get deleted early wrongly.

Need to make get/put balance for both cases.

-v2: According to Bjorn, update vga_set_default_device instead...
-v3: Remove extra checking about null that pointed out by Bjorn.
     Add extra check for same value, to avoid extra put/get pair, suggested by
	Matthew.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: x86@kernel.org
Cc: Dave Airlie <airlied@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Julia Lawall <julia@diku.dk>
Cc: Matthew Garrett <mjg@redhat.com>

---
 drivers/gpu/vga/vgaarb.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

Index: linux-2.6/drivers/gpu/vga/vgaarb.c
===================================================================
--- linux-2.6.orig/drivers/gpu/vga/vgaarb.c
+++ linux-2.6/drivers/gpu/vga/vgaarb.c
@@ -141,7 +141,11 @@ EXPORT_SYMBOL_GPL(vga_default_device);
 
 void vga_set_default_device(struct pci_dev *pdev)
 {
-	vga_default = pdev;
+	if (vga_default == pdev)
+		return;
+
+	pci_dev_put(vga_default);
+	vga_default = pci_dev_get(pdev);
 }
 #endif
 
@@ -577,7 +581,7 @@ static bool vga_arbiter_add_pci_device(s
 #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 	if (vga_default == NULL &&
 	    ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK))
-		vga_default = pci_dev_get(pdev);
+		vga_set_default_device(pdev);
 #endif
 
 	vga_arbiter_check_bridge_sharing(vgadev);
@@ -613,10 +617,8 @@ static bool vga_arbiter_del_pci_device(s
 	}
 
 #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
-	if (vga_default == pdev) {
-		pci_dev_put(vga_default);
-		vga_default = NULL;
-	}
+	if (vga_default == pdev)
+		vga_set_default_device(NULL);
 #endif
 
 	if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))

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

* Re: [PATCH 01/40] PCI: fix default vga ref_count
  2012-09-19 18:54           ` [PATCH 01/40] PCI: fix default vga ref_count Yinghai Lu
  2012-09-21 20:52             ` Bjorn Helgaas
@ 2012-09-23 15:25             ` Jiang Liu
  1 sibling, 0 replies; 60+ messages in thread
From: Jiang Liu @ 2012-09-23 15:25 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi, Dave Airlie, Julia Lawall,
	Matthew Garrett

On 09/20/2012 02:54 AM, Yinghai Lu wrote:
> when __ARCH_HAS_VGA_DEFAULT_DEVICE is not defined, aka EFIFB is not used,
> for static path, vga_default setting is through vga_arbiter_add_pci_device.
> and later x86 pci_fixup_video, will skip setting again.
> - subsys_initcall(vga_arb_device_init) come first to call vga_arbiter_add_pci_device. It will call pci_get_dev to hold one reference.
> 
> for hotplug add path, even vga_arbiter_add_pci_device is called via notifier,
> but it will check VGA_RSRC_LEGACY_MASK that is not set for hotplug path.
> So x86 pci_fixup_video will take over to call vga_set_default_device().
> It will not hold one refrence.
> 
> Later for hotplug remove path, vga_arbiter_del_pci_device that does not check
> VGA_RSRC_LEGACY_MASK will call put_device and it will cause ref_count to
> decrease extra. that will have that pci device get deleted early wrongly.
> 
> Need to make get/put balance for both cases.
> 
> -v2: According to Bjorn, update vga_set_default_device instead...
> 
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> Cc: x86@kernel.org
> Cc: Dave Airlie <airlied@redhat.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Julia Lawall <julia@diku.dk>
> Cc: Matthew Garrett <mjg@redhat.com>
> ---
>  drivers/gpu/vga/vgaarb.c |   14 +++++++++-----
>  1 files changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
> index b6852b7..0888951e 100644
> --- a/drivers/gpu/vga/vgaarb.c
> +++ b/drivers/gpu/vga/vgaarb.c
> @@ -141,6 +141,12 @@ EXPORT_SYMBOL_GPL(vga_default_device);
>  
>  void vga_set_default_device(struct pci_dev *pdev)
>  {
> +	if (vga_default)
> +		pci_dev_put(vga_default);
> +
> +	if (pdev)
> +		pdev = pci_dev_get(pdev);
> +
>  	vga_default = pdev;
>  }
Seems it could be simplified as
void vga_set_default_device(struct pci_dev *pdev)
{
	pci_dev_put(vga_default);
 	vga_default = pci_dev_get(pdev);
}
--Gerry

>  #endif
> @@ -577,7 +583,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
>  #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
>  	if (vga_default == NULL &&
>  	    ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK))
> -		vga_default = pci_dev_get(pdev);
> +		vga_set_default_device(pdev);
>  #endif
>  
>  	vga_arbiter_check_bridge_sharing(vgadev);
> @@ -613,10 +619,8 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
>  	}
>  
>  #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
> -	if (vga_default == pdev) {
> -		pci_dev_put(vga_default);
> -		vga_default = NULL;
> -	}
> +	if (vga_default == pdev)
> +		vga_set_default_device(NULL);
>  #endif
>  
>  	if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
> 


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

* Re: [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge
  2012-09-19 18:54           ` [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge Yinghai Lu
@ 2012-10-12 10:36             ` Tang Chen
  0 siblings, 0 replies; 60+ messages in thread
From: Tang Chen @ 2012-10-12 10:36 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi

Hi Yinghai,

When I was reviewing this patch, I found a little problem.

Please refer to email:
[PATCH 0/3] Find pci root bridges by comparing HID from 
acpi_device_info, not acpi_device.

I could be wrong. :)
If I didn't consider your idea correct, or you have a better solution,
please let me know.

Thanks. :)


On 09/20/2012 02:54 AM, Yinghai Lu wrote:
> It causes confusion.
>
> We may only need acpi hp for pci host bridge.
>
> Split host bridge hot-add support to pci_root_hp, and keep acpiphp simple.
>
> Also remove not used res_lock in the struct.
>
> -v2: put back pci_root_hp change in one patch
> -v3: add pcibios_resource_survey_bus() calling
> -v4: remove not needed code with remove_bridge
> -v5: put back support for acpiphp support for slots just on root bus.
> -v6: change some functions to *_p2p_* to make it more clean.
>
> Signed-off-by: Yinghai Lu<yinghai@kernel.org>
> ---
>   drivers/acpi/Makefile              |    1 +
>   drivers/acpi/pci_root_hp.c         |  238 ++++++++++++++++++++++++++++++++++++
>   drivers/pci/hotplug/acpiphp_glue.c |   59 +++-------
>   3 files changed, 254 insertions(+), 44 deletions(-)
>   create mode 100644 drivers/acpi/pci_root_hp.c
>
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index 47199e2..c9abd4c 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -36,6 +36,7 @@ acpi-y				+= processor_core.o
>   acpi-y				+= ec.o
>   acpi-$(CONFIG_ACPI_DOCK)	+= dock.o
>   acpi-y				+= pci_root.o pci_link.o pci_irq.o pci_bind.o
> +acpi-$(CONFIG_HOTPLUG)		+= pci_root_hp.o
>   acpi-y				+= power.o
>   acpi-y				+= event.o
>   acpi-y				+= sysfs.o
> diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c
> new file mode 100644
> index 0000000..e07c31b
> --- /dev/null
> +++ b/drivers/acpi/pci_root_hp.c
> @@ -0,0 +1,238 @@
> +/*
> + * Separated from drivers/pci/hotplug/acpiphp_glue.c
> + *	only support root bridge
> + */
> +
> +#include<linux/init.h>
> +#include<linux/module.h>
> +
> +#include<linux/kernel.h>
> +#include<linux/pci.h>
> +#include<linux/mutex.h>
> +#include<linux/slab.h>
> +#include<linux/acpi.h>
> +
> +static LIST_HEAD(acpi_root_bridge_list);
> +struct acpi_root_bridge {
> +	struct list_head list;
> +	acpi_handle handle;
> +	u32 flags;
> +};
> +
> +/* bridge flags */
> +#define ROOT_BRIDGE_HAS_EJ0	(0x00000002)
> +#define ROOT_BRIDGE_HAS_PS3	(0x00000080)
> +
> +#define ACPI_STA_FUNCTIONING	(0x00000008)
> +
> +static struct acpi_root_bridge *acpi_root_handle_to_bridge(acpi_handle handle)
> +{
> +	struct acpi_root_bridge *bridge;
> +
> +	list_for_each_entry(bridge,&acpi_root_bridge_list, list)
> +		if (bridge->handle == handle)
> +			return bridge;
> +
> +	return NULL;
> +}
> +
> +/* allocate and initialize host bridge data structure */
> +static void add_acpi_root_bridge(acpi_handle handle)
> +{
> +	struct acpi_root_bridge *bridge;
> +	acpi_handle dummy_handle;
> +	acpi_status status;
> +
> +	/* if the bridge doesn't have _STA, we assume it is always there */
> +	status = acpi_get_handle(handle, "_STA",&dummy_handle);
> +	if (ACPI_SUCCESS(status)) {
> +		unsigned long long tmp;
> +
> +		status = acpi_evaluate_integer(handle, "_STA", NULL,&tmp);
> +		if (ACPI_FAILURE(status)) {
> +			printk(KERN_DEBUG "%s: _STA evaluation failure\n",
> +						 __func__);
> +			return;
> +		}
> +		if ((tmp&  ACPI_STA_FUNCTIONING) == 0)
> +			/* don't register this object */
> +			return;
> +	}
> +
> +	bridge = kzalloc(sizeof(struct acpi_root_bridge), GFP_KERNEL);
> +	if (!bridge)
> +		return;
> +
> +	bridge->handle = handle;
> +
> +	if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0",&dummy_handle)))
> +		bridge->flags |= ROOT_BRIDGE_HAS_EJ0;
> +	if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3",&dummy_handle)))
> +		bridge->flags |= ROOT_BRIDGE_HAS_PS3;
> +
> +	list_add(&bridge->list,&acpi_root_bridge_list);
> +}
> +
> +struct acpi_root_hp_work {
> +	struct work_struct work;
> +	acpi_handle handle;
> +	u32 type;
> +	void *context;
> +};
> +
> +static void alloc_acpi_root_hp_work(acpi_handle handle, u32 type,
> +					void *context,
> +					void (*func)(struct work_struct *work))
> +{
> +	struct acpi_root_hp_work *hp_work;
> +	int ret;
> +
> +	hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
> +	if (!hp_work)
> +		return;
> +
> +	hp_work->handle = handle;
> +	hp_work->type = type;
> +	hp_work->context = context;
> +
> +	INIT_WORK(&hp_work->work, func);
> +	ret = queue_work(kacpi_hotplug_wq,&hp_work->work);
> +	if (!ret)
> +		kfree(hp_work);
> +}
> +
> +/* Program resources in newly inserted bridge */
> +static void acpi_root_configure_bridge(acpi_handle handle)
> +{
> +	struct acpi_pci_root *root = acpi_pci_find_root(handle);
> +
> +	pcibios_resource_survey_bus(root->bus);
> +	pci_assign_unassigned_bus_resources(root->bus);
> +}
> +
> +static void handle_root_bridge_insertion(acpi_handle handle)
> +{
> +	struct acpi_device *device, *pdevice;
> +	acpi_handle phandle;
> +	int ret_val;
> +
> +	acpi_get_parent(handle,&phandle);
> +	if (acpi_bus_get_device(phandle,&pdevice)) {
> +		printk(KERN_DEBUG "no parent device, assuming NULL\n");
> +		pdevice = NULL;
> +	}
> +	if (!acpi_bus_get_device(handle,&device)) {
> +		/* check if  pci root_bus is removed */
> +		struct acpi_pci_root *root = acpi_driver_data(device);
> +		if (pci_find_bus(root->segment, root->secondary.start))
> +			return;
> +
> +		printk(KERN_DEBUG "bus exists... trim\n");
> +		/* this shouldn't be in here, so remove
> +		 * the bus then re-add it...
> +		 */
> +		ret_val = acpi_bus_trim(device, 1);
> +		printk(KERN_DEBUG "acpi_bus_trim return %x\n", ret_val);
> +	}
> +	if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {
> +		printk(KERN_ERR "cannot add bridge to acpi list\n");
> +		return;
> +	}
> +	acpi_root_configure_bridge(handle);
> +	if (acpi_bus_start(device))
> +		printk(KERN_ERR "cannot start bridge\n");
> +}
> +
> +static void _handle_hotplug_event_root(struct work_struct *work)
> +{
> +	struct acpi_root_bridge *bridge;
> +	char objname[64];
> +	struct acpi_buffer buffer = { .length = sizeof(objname),
> +				      .pointer = objname };
> +	struct acpi_root_hp_work *hp_work;
> +	acpi_handle handle;
> +	u32 type;
> +
> +	hp_work = container_of(work, struct acpi_root_hp_work, work);
> +	handle = hp_work->handle;
> +	type = hp_work->type;
> +
> +	bridge = acpi_root_handle_to_bridge(handle);
> +
> +	acpi_get_name(handle, ACPI_FULL_PATHNAME,&buffer);
> +
> +	switch (type) {
> +	case ACPI_NOTIFY_BUS_CHECK:
> +		/* bus enumerate */
> +		printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
> +				 objname);
> +		if (!bridge) {
> +			handle_root_bridge_insertion(handle);
> +			add_acpi_root_bridge(handle);
> +		}
> +
> +		break;
> +
> +	case ACPI_NOTIFY_DEVICE_CHECK:
> +		/* device check */
> +		printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
> +				 objname);
> +		if (!bridge) {
> +			handle_root_bridge_insertion(handle);
> +			add_acpi_root_bridge(handle);
> +		}
> +		break;
> +
> +	default:
> +		printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
> +				 type, objname);
> +		break;
> +	}
> +
> +	kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
> +}
> +
> +static void handle_hotplug_event_root(acpi_handle handle, u32 type,
> +					void *context)
> +{
> +	alloc_acpi_root_hp_work(handle, type, context,
> +				_handle_hotplug_event_root);
> +}
> +
> +static acpi_status __init
> +find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
> +{
> +	char objname[64];
> +	struct acpi_buffer buffer = { .length = sizeof(objname),
> +				      .pointer = objname };
> +	int *count = (int *)context;
> +
> +	if (!acpi_is_root_bridge(handle))
> +		return AE_OK;
> +
> +	(*count)++;
> +
> +	acpi_get_name(handle, ACPI_FULL_PATHNAME,&buffer);
> +
> +	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> +				handle_hotplug_event_root, NULL);
> +	printk(KERN_DEBUG "acpi root: %s notify handler installed\n", objname);
> +
> +	add_acpi_root_bridge(handle);
> +
> +	return AE_OK;
> +}
> +
> +static int __init acpi_pci_root_hp_init(void)
> +{
> +	int num = 0;
> +
> +	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
> +		ACPI_UINT32_MAX, find_root_bridges, NULL,&num, NULL);
> +
> +	printk(KERN_DEBUG "Found %d acpi root devices\n", num);
> +
> +	return 0;
> +}
> +
> +subsys_initcall(acpi_pci_root_hp_init);
> diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
> index 6cb1923..00fa414 100644
> --- a/drivers/pci/hotplug/acpiphp_glue.c
> +++ b/drivers/pci/hotplug/acpiphp_glue.c
> @@ -521,10 +521,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
>   	acpi_status status;
>   	acpi_handle handle = bridge->handle;
>
> -	status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> +	if (bridge->type != BRIDGE_TYPE_HOST) {
> +		status = acpi_remove_notify_handler(handle,
> +					    ACPI_SYSTEM_NOTIFY,
>   					    handle_hotplug_event_bridge);
> -	if (ACPI_FAILURE(status))
> -		err("failed to remove notify handler\n");
> +		if (ACPI_FAILURE(status))
> +			err("failed to remove notify handler\n");
> +	}
>
>   	if ((bridge->type != BRIDGE_TYPE_HOST)&&
>   	((bridge->flags&  BRIDGE_HAS_EJ0)&&  bridge->func)) {
> @@ -607,9 +610,6 @@ static void remove_bridge(acpi_handle handle)
>   	bridge = acpiphp_handle_to_bridge(handle);
>   	if (bridge)
>   		cleanup_bridge(bridge);
> -	else
> -		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> -					   handle_hotplug_event_bridge);
>   }
>
>   static int power_on_slot(struct acpiphp_slot *slot)
> @@ -1110,18 +1110,12 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
>   }
>
>   /* Program resources in newly inserted bridge */
> -static int acpiphp_configure_bridge (acpi_handle handle)
> +static int acpiphp_configure_p2p_bridge(acpi_handle handle)
>   {
> -	struct pci_bus *bus;
> +	struct pci_dev *pdev = acpi_get_pci_dev(handle);
> +	struct pci_bus *bus = pdev->subordinate;
>
> -	if (acpi_is_root_bridge(handle)) {
> -		struct acpi_pci_root *root = acpi_pci_find_root(handle);
> -		bus = root->bus;
> -	} else {
> -		struct pci_dev *pdev = acpi_get_pci_dev(handle);
> -		bus = pdev->subordinate;
> -		pci_dev_put(pdev);
> -	}
> +	pci_dev_put(pdev);
>
>   	pci_bus_size_bridges(bus);
>   	pci_bus_assign_resources(bus);
> @@ -1131,7 +1125,7 @@ static int acpiphp_configure_bridge (acpi_handle handle)
>   	return 0;
>   }
>
> -static void handle_bridge_insertion(acpi_handle handle, u32 type)
> +static void handle_p2p_bridge_insertion(acpi_handle handle, u32 type)
>   {
>   	struct acpi_device *device, *pdevice;
>   	acpi_handle phandle;
> @@ -1151,9 +1145,9 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
>   		err("cannot add bridge to acpi list\n");
>   		return;
>   	}
> -	if (!acpiphp_configure_bridge(handle)&&
> +	if (!acpiphp_configure_p2p_bridge(handle)&&
>   		!acpi_bus_start(device))
> -		add_bridge(handle);
> +		add_p2p_bridge(handle);
>   	else
>   		err("cannot configure and start bridge\n");
>
> @@ -1239,7 +1233,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
>
>   	if (acpi_bus_get_device(handle,&device)) {
>   		/* This bridge must have just been physically inserted */
> -		handle_bridge_insertion(handle, type);
> +		handle_p2p_bridge_insertion(handle, type);
>   		goto out;
>   	}
>
> @@ -1416,21 +1410,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
>   			      _handle_hotplug_event_func);
>   }
>
> -static acpi_status
> -find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
> -{
> -	int *count = (int *)context;
> -
> -	if (!acpi_is_root_bridge(handle))
> -		return AE_OK;
> -
> -	(*count)++;
> -	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> -				    handle_hotplug_event_bridge, NULL);
> -
> -	return AE_OK ;
> -}
> -
>   static struct acpi_pci_driver acpi_pci_hp_driver = {
>   	.add =		add_bridge,
>   	.remove =	remove_bridge,
> @@ -1441,15 +1420,7 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
>    */
>   int __init acpiphp_glue_init(void)
>   {
> -	int num = 0;
> -
> -	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
> -			ACPI_UINT32_MAX, find_root_bridges, NULL,&num, NULL);
> -
> -	if (num<= 0)
> -		return -1;
> -	else
> -		acpi_pci_register_driver(&acpi_pci_hp_driver);
> +	acpi_pci_register_driver(&acpi_pci_hp_driver);
>
>   	return 0;
>   }


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

* Re: [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support
  2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
                             ` (39 preceding siblings ...)
  2012-09-19 18:54           ` [PATCH 40/40] ACPI: Enable SCI_EMULATE to manually simulate physical hotplug testing Yinghai Lu
@ 2012-10-17  7:50           ` Yijing Wang
  2012-10-17 16:19             ` Yinghai Lu
  40 siblings, 1 reply; 60+ messages in thread
From: Yijing Wang @ 2012-10-17  7:50 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi

On 2012/9/20 2:54, Yinghai Lu wrote:

Hi Yinghai,
   I applied this series patches to the latest pci-next, but git am fail occured.
When I try to pull from for-pci-root-bus-hotplug branch, I found some patches missed(eg. SCI_EMULATE).
Where can I get the newest pci root bus hotplug patches?

Thanks!
Yijing

> It supports pci root bus removal with
> 	echo "PCI0 3" > /sys/kernel/debug/acpi/sci_notify
> 
> add with
> 	echo "PCI0 0" > /sys/kernel/debug/acpi/sci_notify
> 
> based on pci/next
> 
> We need to separate pci root bus add from acpiphp. so user could only root bus
> hotplug and pciehp that will make system fw simple.
> Also later CONFIG_HOTPLUG will be removed, so pci root bus hotplug will be
> enabled by default and user still need select acpiphp and pciehp for normal
> pci device hotplug support.
> 
> could get from
>         git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-root-bus-hotplug
> 
> -v6: do not depend on busn-alloc anymore.
> 
> part1: cleanup for pci/next
> [PATCH 01/40] PCI: fix default vga ref_count
> [PATCH 02/40] PCI, x86: clear initial value for root info resources
> [PATCH 03/40] PCI, ia64: clear initial value for root info resources
> [PATCH 04/40] PCI, acpiphp: Add is_hotplug_bridge detection
> [PATCH 05/40] PCI: Add root bus children dev's res to fail list
> [PATCH 06/40] PCI: Split out stop_bus_device and remove_bus_dev
> 
> part2: reserve BIOS allocated resource for hotadd root bus
> [PATCH 07/40] x86, PCI: Separate pcibios_allocate_bridge_resources()
> [PATCH 08/40] x86, PCI: Separate pcibios_allocate_dev_resources()
> [PATCH 09/40] x86, PCI: Let pcibios_allocate_bus_resources() take us instead
> [PATCH 10/40] x86, PCI: Separate rom resource claim out
> [PATCH 11/40] PCI, x86: Add pcibios_fw_addr_done
> [PATCH 12/40] PCI, x86: Remove __init for hw/fw allocated functions
> [PATCH 13/40] PCI: Claim hw/fw allocated resources in hot add path.
> 
> part3: pci_assign_unsissigned_bus_resources() for root bus add.
> [PATCH 14/40] PCI: Separate out pci_assign_unassigned_bus_resources()
> [PATCH 15/40] PCI: Move back pci_rescan_bus() to probe.c
> [PATCH 16/40] PCI: pci_bus_size_bridges() should not size own bridge
> [PATCH 17/40] PCI: Use __pci_bus_size_bridges() directly in pci_assign_unassigned_bus_resources()
> [PATCH 18/40] PCI: Rescan bus using callback method too
> [PATCH 19/40] PCI, sysfs: Clean up rescan/remove with schedule_callback
> 
> part4: Separate root bus add from acpiphp and add removal support.
> [PATCH 20/40] PCI: Fix a device reference count leakage issue in
> [PATCH 21/40] PCI: Add pci_stop_and_remove_root_bus()
> [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host
> [PATCH 23/40] PCI, ACPI: Pass device instead of handle when config
> [PATCH 24/40] PCI, acpi: Update acpi_pci_driver add/remove interface
> [PATCH 25/40] PCI, ACPI: Make acpi_pci_root_remove remove pci root
> [PATCH 26/40] PCI, ACPI: del root bus prt
> [PATCH 27/40] ACPI: acpi_bus_trim to support two steps.
> [PATCH 28/40] PCI, ACPI: Add pci_root_hp hot removal notification
> [PATCH 29/40] PCI, ACPI: Add alloc_acpi_hp_work()
> [PATCH 30/40] PCI, acpiphp: Use acpi_hp_work
> [PATCH 31/40] PCI, pci_root_hp: Use acpi_hp_work
> [PATCH 32/40] PCI, ACPI: Make kacpi_hotplug_wq static
> 
> part5: add/remove calling for acpi_pci_drivers.
> [PATCH 33/40] ACPI, PCI: Use normal list for struct acpi_pci_driver
> [PATCH 34/40] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging
> [PATCH 35/40] ACPI, PCI: Protect global lists in
> [PATCH 36/40] PCI: Set dev_node early for pci_dev
> [PATCH 37/40] PCI, x86: Move pci_enable_bridges() down
> [PATCH 38/40] ACPI, PCI: Skip extra pci_enable_bridges for non
> [PATCH 39/40] PCI, acpiphp: Don't ailout even no slots found yet.
> 
> part6: acpi add/remove simulation
> [PATCH 40/40] ACPI: Enable SCI_EMULATE to manually simulate physical
> 
>  arch/ia64/pci/pci.c                |    3 +-
>  arch/x86/pci/acpi.c                |    3 +-
>  arch/x86/pci/i386.c                |  185 ++++++++++++++++--------
>  drivers/acpi/Kconfig               |   10 ++
>  drivers/acpi/Makefile              |    2 +
>  drivers/acpi/osl.c                 |   24 +++-
>  drivers/acpi/pci_root.c            |  123 ++++++++++------
>  drivers/acpi/pci_root_hp.c         |  278 ++++++++++++++++++++++++++++++++++++
>  drivers/acpi/pci_slot.c            |   12 +-
>  drivers/acpi/scan.c                |    5 +-
>  drivers/acpi/sci_emu.c             |  145 +++++++++++++++++++
>  drivers/gpu/vga/vgaarb.c           |   14 ++-
>  drivers/pci/bus.c                  |    2 +
>  drivers/pci/hotplug/acpiphp.h      |    1 -
>  drivers/pci/hotplug/acpiphp_core.c |   23 +---
>  drivers/pci/hotplug/acpiphp_glue.c |  165 +++++++--------------
>  drivers/pci/pci-sysfs.c            |   41 ++++--
>  drivers/pci/probe.c                |   26 ++++-
>  drivers/pci/remove.c               |   87 +++++++++--
>  drivers/pci/search.c               |   10 +-
>  drivers/pci/setup-bus.c            |   54 +++-----
>  include/acpi/acpi_bus.h            |    1 +
>  include/acpi/acpiosxf.h            |    9 +-
>  include/linux/acpi.h               |    6 +-
>  include/linux/pci.h                |    5 +
>  25 files changed, 899 insertions(+), 335 deletions(-)
>  create mode 100644 drivers/acpi/pci_root_hp.c
>  create mode 100644 drivers/acpi/sci_emu.c
> 


-- 
Thanks!
Yijing


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

* Re: [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support
  2012-10-17  7:50           ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yijing Wang
@ 2012-10-17 16:19             ` Yinghai Lu
  2012-10-18  0:51               ` Yijing Wang
  0 siblings, 1 reply; 60+ messages in thread
From: Yinghai Lu @ 2012-10-17 16:19 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi

On Wed, Oct 17, 2012 at 12:50 AM, Yijing Wang <wangyijing@huawei.com> wrote:
> On 2012/9/20 2:54, Yinghai Lu wrote:
>
> Hi Yinghai,
>    I applied this series patches to the latest pci-next, but git am fail occured.
> When I try to pull from for-pci-root-bus-hotplug branch, I found some patches missed(eg. SCI_EMULATE).
> Where can I get the newest pci root bus hotplug patches?

should be
for-pci-split-pci-root-hp-2
or
for-pci-next-2
branch.

but
>> part6: acpi add/remove simulation
>> [PATCH 40/40] ACPI: Enable SCI_EMULATE to manually simulate physical

is not in. you need to apply that separately.

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

* Re: [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support
  2012-10-17 16:19             ` Yinghai Lu
@ 2012-10-18  0:51               ` Yijing Wang
  0 siblings, 0 replies; 60+ messages in thread
From: Yijing Wang @ 2012-10-18  0:51 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, x86,
	Andrew Morton, Linus Torvalds, Greg Kroah-Hartman, linux-pci,
	linux-kernel, linux-acpi

On 2012/10/18 0:19, Yinghai Lu wrote:
> On Wed, Oct 17, 2012 at 12:50 AM, Yijing Wang <wangyijing@huawei.com> wrote:
>> On 2012/9/20 2:54, Yinghai Lu wrote:
>>
>> Hi Yinghai,
>>    I applied this series patches to the latest pci-next, but git am fail occured.
>> When I try to pull from for-pci-root-bus-hotplug branch, I found some patches missed(eg. SCI_EMULATE).
>> Where can I get the newest pci root bus hotplug patches?
> 
> should be
> for-pci-split-pci-root-hp-2
> or
> for-pci-next-2
> branch.
> 
> but
>>> part6: acpi add/remove simulation
>>> [PATCH 40/40] ACPI: Enable SCI_EMULATE to manually simulate physical
> 
> is not in. you need to apply that separately.
> 

OK, Thanks!

> .
> 


-- 
Thanks!
Yijing


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

end of thread, other threads:[~2012-10-18  0:53 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-02 21:50 [PATCH part2 0/6] PCI, x86: pci root bus hotplug support - part2 Yinghai Lu
2012-09-02 21:50 ` [PATCH part2 1/6] x86, PCI: Separate pcibios_allocate_bridge_resources() Yinghai Lu
2012-09-02 21:50 ` [PATCH part2 2/6] x86, PCI: Separate pcibios_allocate_dev_resources() Yinghai Lu
2012-09-02 21:50 ` [PATCH part2 3/6] x86, PCI: Let pcibios_allocate_bus_resources() take bus instead Yinghai Lu
2012-09-02 21:50 ` [PATCH part2 4/6] x86, PCI: Separate rom resource claim out Yinghai Lu
2012-09-17 23:38   ` Bjorn Helgaas
2012-09-18  3:18     ` Yinghai Lu
2012-09-02 21:50 ` [PATCH part2 5/6] PCI, x86: Add pcibios_fw_addr_done Yinghai Lu
2012-09-02 21:50 ` [PATCH part2 6/6] PCI: Claim hw/fw allocated resources in hot add path Yinghai Lu
2012-09-18  0:12   ` Bjorn Helgaas
2012-09-18  4:44     ` Yinghai Lu
2012-09-18  5:36       ` Yinghai Lu
2012-09-19 18:54         ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yinghai Lu
2012-09-19 18:54           ` [PATCH 01/40] PCI: fix default vga ref_count Yinghai Lu
2012-09-21 20:52             ` Bjorn Helgaas
2012-09-21 21:18               ` Yinghai Lu
2012-09-23 15:25             ` Jiang Liu
2012-09-19 18:54           ` [PATCH 02/40] PCI, x86: clear initial value for root info resources Yinghai Lu
2012-09-19 18:54           ` [PATCH 03/40] PCI, ia64: " Yinghai Lu
2012-09-19 18:54           ` [PATCH 04/40] PCI, acpiphp: Add is_hotplug_bridge detection Yinghai Lu
2012-09-19 18:54           ` [PATCH 05/40] PCI: Add root bus children dev's res to fail list Yinghai Lu
2012-09-19 18:54           ` [PATCH 06/40] PCI: Split out stop_bus_device and remove_bus_dev again Yinghai Lu
2012-09-19 18:54           ` [PATCH 07/40] x86, PCI: Separate pcibios_allocate_bridge_resources() Yinghai Lu
2012-09-19 18:54           ` [PATCH 08/40] x86, PCI: Separate pcibios_allocate_dev_resources() Yinghai Lu
2012-09-19 18:54           ` [PATCH 09/40] x86, PCI: Let pcibios_allocate_bus_resources() take bus instead Yinghai Lu
2012-09-19 18:54           ` [PATCH 10/40] x86, PCI: Separate rom resource claim out Yinghai Lu
2012-09-19 18:54           ` [PATCH 11/40] PCI, x86: Add pcibios_fw_addr_done Yinghai Lu
2012-09-19 18:54           ` [PATCH 12/40] PCI, x86: Remove __init for hw/fw allocated functions Yinghai Lu
2012-09-19 18:54           ` [PATCH 13/40] PCI: Claim hw/fw allocated resources in hot add path Yinghai Lu
2012-09-19 18:54           ` [PATCH 14/40] PCI: Separate out pci_assign_unassigned_bus_resources() Yinghai Lu
2012-09-19 18:54           ` [PATCH 15/40] PCI: Move back pci_rescan_bus() to probe.c Yinghai Lu
2012-09-19 18:54           ` [PATCH 16/40] PCI: pci_bus_size_bridges() should not size own bridge Yinghai Lu
2012-09-19 18:54           ` [PATCH 17/40] PCI: Use __pci_bus_size_bridges() directly in pci_assign_unassigned_bus_resources() Yinghai Lu
2012-09-19 18:54           ` [PATCH 18/40] PCI: Rescan bus using callback method too Yinghai Lu
2012-09-19 18:54           ` [PATCH 19/40] PCI, sysfs: Clean up rescan/remove with schedule_callback Yinghai Lu
2012-09-19 18:54           ` [PATCH 20/40] PCI: Fix a device reference count leakage issue in pci_dev_present() Yinghai Lu
2012-09-19 18:54           ` [PATCH 21/40] PCI: Add pci_stop_and_remove_root_bus() Yinghai Lu
2012-09-19 18:54           ` [PATCH 22/40] PCI, acpiphp: Separate out hot-add support of pci host bridge Yinghai Lu
2012-10-12 10:36             ` Tang Chen
2012-09-19 18:54           ` [PATCH 23/40] PCI, ACPI: Pass device instead of handle when config root bridge Yinghai Lu
2012-09-19 18:54           ` [PATCH 24/40] PCI, acpi: Update acpi_pci_driver add/remove interface Yinghai Lu
2012-09-19 18:54           ` [PATCH 25/40] PCI, ACPI: Make acpi_pci_root_remove remove pci root bus too Yinghai Lu
2012-09-19 18:54           ` [PATCH 26/40] PCI, ACPI: del root bus prt Yinghai Lu
2012-09-19 18:54           ` [PATCH 27/40] ACPI: acpi_bus_trim to support two steps Yinghai Lu
2012-09-19 18:54           ` [PATCH 28/40] PCI, ACPI: Add pci_root_hp hot removal notification support Yinghai Lu
2012-09-19 18:54           ` [PATCH 29/40] PCI, ACPI: Add alloc_acpi_hp_work() Yinghai Lu
2012-09-19 18:54           ` [PATCH 30/40] PCI, acpiphp: Use acpi_hp_work Yinghai Lu
2012-09-19 18:54           ` [PATCH 31/40] PCI, pci_root_hp: " Yinghai Lu
2012-09-19 18:54           ` [PATCH 32/40] PCI, ACPI: Make kacpi_hotplug_wq static Yinghai Lu
2012-09-19 18:54           ` [PATCH 33/40] ACPI, PCI: Use normal list for struct acpi_pci_driver Yinghai Lu
2012-09-19 18:54           ` [PATCH 34/40] ACPI, PCI: Notify acpi_pci_drivers when hot-plugging PCI root bridges Yinghai Lu
2012-09-19 18:54           ` [PATCH 35/40] ACPI, PCI: Protect global lists in drivers/acpi/pci_root.c Yinghai Lu
2012-09-19 18:54           ` [PATCH 36/40] PCI: Set dev_node early for pci_dev Yinghai Lu
2012-09-19 18:54           ` [PATCH 37/40] PCI, x86: Move pci_enable_bridges() down Yinghai Lu
2012-09-19 18:54           ` [PATCH 38/40] ACPI, PCI: Skip extra pci_enable_bridges for non hot-add root Yinghai Lu
2012-09-19 18:54           ` [PATCH 39/40] PCI, acpiphp: Don't ailout even no slots found yet Yinghai Lu
2012-09-19 18:54           ` [PATCH 40/40] ACPI: Enable SCI_EMULATE to manually simulate physical hotplug testing Yinghai Lu
2012-10-17  7:50           ` [PATCH 00/40] PCI, ACPI, x86: pci root bus hotplug support Yijing Wang
2012-10-17 16:19             ` Yinghai Lu
2012-10-18  0:51               ` Yijing Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).