linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering
@ 2012-12-09 22:58 Rafael J. Wysocki
  2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
                   ` (7 more replies)
  0 siblings, 8 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-09 22:58 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

Hi,

The following patches change the ordering of the ACPI namespace scanning code
so that all struct acpi_device objects in the given scope are registered before
ACPI drivers are probed against them.  They also do some simplifications and
clarifications of the code made possible by this main change.

This is done for three basic reasons.  First, we need the boot ACPI namespace
scanning code to be as similar as reasonably possible to the hot-plug ACPI
namespace scanning code.  Second, the ordering of PCI devices enumeration
versus ACPI-backed platform devices registration needs to be such that the PCI
devices in the given scope are all registered first.  Finally, when we start to
actually manage ACPI device resources as appropriate (e.g. resolve resource
conflicts properly) we'll need all struct acpi_device nodes to be registered
before any "companion" physical nodes or ACPI drivers are bound to them.

The patches have been tested on Toshiba Portege R500 without breaking stuff
(I used some additional debug code to verify that the ordering of device
discovery had not been modified by them), but if you see any problems with
them regarding hot-plug, please let me know.

[1/6] - Separate adding ACPI device objects from probing ACPI drivers.
[2/6] - Change the ordering of PCI root bridge driver registration.
[3/6] - Make acpi_bus_add() and acpi_bus_start() visibly different.
[4/6] - Reduce the usage of struct acpi_bus_ops
[5/6] - Replace struct acpi_bus_ops with an enum type
[6/6] - Change the ordering of acpi_bus_check_add() to avoid unnecessary checks.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
@ 2012-12-09 23:00 ` Rafael J. Wysocki
  2012-12-12 15:50   ` Jiang Liu
                     ` (2 more replies)
  2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
                   ` (6 subsequent siblings)
  7 siblings, 3 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-09 23:00 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Currently, as soon as an ACPI device node object (struct acpi_device)
is created, the driver core attempts to probe ACPI drivers against
it.  That leads to some unpleasant side effects, like the fact that
the boot code path for ACPI namespace scanning is different from the
analogous hot-plug code path (during boot ACPI drivers are not
present when ACPI device node objects are registered, so they are
guaranteed not to be probed, which is not the case during hot-plug).
That, in turn, leads to unnecessary complications in the PCI
enumeration algorithm.

Reduce the differences between the boot and hot-plug cases by
splitting the ACPI namespace scanning for devices into two passes,
such that struct acpi_device objects are registerd in the first
patch without probing ACPI drivers and the drivers are probed
against them directly in the second pass.  This way ACPI drivers
can assume that all of the ACPI device node objects in the given
scope will be registered when their .add() routines run and the
hot-plug case becomes the same as the boot case from their
perspective.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c     |   96 +++++++++++++++++++++++++++++++++---------------
 include/acpi/acpi_bus.h |    1 
 2 files changed, 68 insertions(+), 29 deletions(-)

Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
 struct acpi_bus_ops {
 	u32 acpi_op_add:1;
 	u32 acpi_op_start:1;
+	u32 acpi_op_match:1;
 };
 
 struct acpi_device_ops {
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+	return acpi_dev->bus_ops.acpi_op_match
+		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
 static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
 	return 0;
 }
 
+/*
+ * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
+ * @device: ACPI device node to bind.
+ */
+static void acpi_hot_add_bind(struct acpi_device *device)
+{
+	if (device->flags.bus_address
+	    && device->parent && device->parent->ops.bind)
+		device->parent->ops.bind(device);
+}
+
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
 				  unsigned long long sta,
@@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
 
 	result = acpi_device_register(device);
 
-	/*
-	 * Bind _ADR-Based Devices when hot add
-	 */
-	if (device->flags.bus_address) {
-		if (device->parent && device->parent->ops.bind)
-			device->parent->ops.bind(device);
-	}
+	if (device->bus_ops.acpi_op_match)
+		acpi_hot_add_bind(device);
 
 end:
 	if (!result) {
@@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
 	struct acpi_bus_ops ops = {
 		.acpi_op_add = 1,
 		.acpi_op_start = 1,
+		.acpi_op_match = 1,
 	};
 	struct acpi_device *device = NULL;
 
@@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
 				      void *context, void **return_value)
 {
 	struct acpi_bus_ops *ops = context;
+	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
-	struct acpi_device *device;
 	acpi_status status;
 	int result;
 
@@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac
 	 * We may already have an acpi_device from a previous enumeration.  If
 	 * so, we needn't add it again, but we may still have to start it.
 	 */
-	device = NULL;
 	acpi_bus_get_device(handle, &device);
 	if (ops->acpi_op_add && !device) {
-		acpi_add_single_object(&device, handle, type, sta, ops);
-		/* Is the device a known good platform device? */
-		if (device
-		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
-			acpi_create_platform_device(device);
-	}
+		struct acpi_bus_ops add_ops = *ops;
 
-	if (!device)
-		return AE_CTRL_DEPTH;
-
-	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
-		status = acpi_start_single_object(device);
-		if (ACPI_FAILURE(status))
+		add_ops.acpi_op_match = 0;
+		acpi_add_single_object(&device, handle, type, sta, &add_ops);
+		if (!device)
 			return AE_CTRL_DEPTH;
+
+		device->bus_ops.acpi_op_match = 1;
 	}
 
 	if (!*return_value)
 		*return_value = device;
+
 	return AE_OK;
 }
 
+static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
+					void *context, void **not_used)
+{
+	struct acpi_bus_ops *ops = context;
+	struct acpi_device *device;
+	acpi_status status = AE_OK;
+
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
+
+	if (ops->acpi_op_add) {
+		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+			/* This is a known good platform device. */
+			acpi_create_platform_device(device);
+		} else {
+			int ret = device_attach(&device->dev);
+			acpi_hot_add_bind(device);
+			if (ret)
+				status = AE_CTRL_DEPTH;
+		}
+	} else if (ops->acpi_op_start) {
+		if (ACPI_FAILURE(acpi_start_single_object(device)))
+			status = AE_CTRL_DEPTH;
+	}
+	return status;
+}
+
 static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
 			 struct acpi_device **child)
 {
-	acpi_status status;
 	void *device = NULL;
+	acpi_status status;
+	int ret = 0;
 
 	status = acpi_bus_check_add(handle, 0, ops, &device);
-	if (ACPI_SUCCESS(status))
+	if (ACPI_FAILURE(status)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+			    acpi_bus_check_add, NULL, ops, &device);
+	if (device)
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_check_add, NULL, ops, &device);
+				    acpi_bus_probe_start, NULL, ops, NULL);
+	else
+		ret = -ENODEV;
 
+ out:
 	if (child)
 		*child = device;
 
-	if (device)
-		return 0;
-	else
-		return -ENODEV;
+	return ret;
 }
 
 /*
@@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void)
 	memset(&ops, 0, sizeof(ops));
 	ops.acpi_op_add = 1;
 	ops.acpi_op_start = 1;
+	ops.acpi_op_match = 1;
 
 	/*
 	 * Enumerate all fixed-feature devices.


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

* [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion
  2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
  2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
@ 2012-12-09 23:00 ` Rafael J. Wysocki
  2012-12-13  1:00   ` Bjorn Helgaas
  2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-09 23:00 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Devices created by acpi_create_platform_device() sometimes may need
to be added to the device hierarchy as children of PCI bridges.  For
this purpose, however, the struct pci_dev objects representing those
bridges need to exist before the platform devices in question are
added, but this is only possible if the PCI root bridge driver is
registered before the initial scanning of the ACPI namespace
(that driver's .add() routine creates the required struct pci_dev
objects).

For this reason, call acpi_pci_root_init() from acpi_scan_init()
before scanning the ACPI namespace for the first time instead of
running it from a separate subsys initcall.  Since the previous patch
has changed the ACPI namespace scanning algorithm, this change does
not affect the PCI root bridge driver's functionality during boot.
It also makes the situation during boot more similar to the situation
during hot-plug (in which the PCI root bridge driver is always
present) and so it helps to reduce arbitary differences between
the hot-plug and boot PCI root bridge code.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/internal.h |    1 +
 drivers/acpi/pci_root.c |    4 +---
 drivers/acpi/scan.c     |    1 +
 3 files changed, 3 insertions(+), 3 deletions(-)

Index: linux/drivers/acpi/internal.h
===================================================================
--- linux.orig/drivers/acpi/internal.h
+++ linux/drivers/acpi/internal.h
@@ -67,6 +67,7 @@ struct acpi_ec {
 
 extern struct acpi_ec *first_ec;
 
+int acpi_pci_root_init(void);
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
 int acpi_boot_ec_enable(void);
Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c
+++ linux/drivers/acpi/pci_root.c
@@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a
 	return 0;
 }
 
-static int __init acpi_pci_root_init(void)
+int __init acpi_pci_root_init(void)
 {
 	acpi_hest_init();
 
@@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi
 
 	return 0;
 }
-
-subsys_initcall(acpi_pci_root_init);
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1828,6 +1828,7 @@ int __init acpi_scan_init(void)
 	}
 
 	acpi_power_init();
+	acpi_pci_root_init();
 
 	/*
 	 * Enumerate devices in the ACPI namespace.


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

* [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different
  2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
  2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
  2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
@ 2012-12-09 23:01 ` Rafael J. Wysocki
  2012-12-13  0:11   ` [Update][PATCH " Rafael J. Wysocki
  2012-12-09 23:02 ` [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-09 23:01 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The current ACPI namespace scanning code suggests that acpi_bus_add()
and acpi_bus_start() share some code.  In fact, however, they are
completely different code paths, so refactor the code to make that
distinction visibly clear.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   57 ++++++++++++++++++++++++----------------------------
 1 file changed, 27 insertions(+), 30 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1626,28 +1626,22 @@ static acpi_status acpi_bus_check_add(ac
 	return AE_OK;
 }
 
-static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
-					void *context, void **not_used)
+static acpi_status acpi_bus_match_device(acpi_handle handle, u32 lvl,
+					 void *not_used, void **ret_not_used)
 {
-	struct acpi_bus_ops *ops = context;
 	struct acpi_device *device;
 	acpi_status status = AE_OK;
 
 	if (acpi_bus_get_device(handle, &device))
 		return AE_CTRL_DEPTH;
 
-	if (ops->acpi_op_add) {
-		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
-			/* This is a known good platform device. */
-			acpi_create_platform_device(device);
-		} else {
-			int ret = device_attach(&device->dev);
-			acpi_hot_add_bind(device);
-			if (ret)
-				status = AE_CTRL_DEPTH;
-		}
-	} else if (ops->acpi_op_start) {
-		if (ACPI_FAILURE(acpi_start_single_object(device)))
+	if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+		/* This is a known good platform device. */
+		acpi_create_platform_device(device);
+	} else {
+		int ret = device_attach(&device->dev);
+		acpi_hot_add_bind(device);
+		if (ret)
 			status = AE_CTRL_DEPTH;
 	}
 	return status;
@@ -1670,7 +1664,7 @@ static int acpi_bus_scan(acpi_handle han
 			    acpi_bus_check_add, NULL, ops, &device);
 	if (device)
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_probe_start, NULL, ops, NULL);
+				    acpi_bus_match_device, NULL, NULL, NULL);
 	else
 		ret = -ENODEV;
 
@@ -1697,31 +1691,34 @@ int
 acpi_bus_add(struct acpi_device **child,
 	     struct acpi_device *parent, acpi_handle handle, int type)
 {
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
+	struct acpi_bus_ops ops = { .acpi_op_add = 1, };
 
 	return acpi_bus_scan(handle, &ops, child);
 }
 EXPORT_SYMBOL(acpi_bus_add);
 
-int acpi_bus_start(struct acpi_device *device)
+static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl,
+					 void *not_used, void **ret_not_used)
 {
-	struct acpi_bus_ops ops;
-	int result;
+	struct acpi_device *device;
+	acpi_status status;
 
-	if (!device)
-		return -EINVAL;
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
 
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_start = 1;
+	status = acpi_start_single_object(device);
+	return ACPI_SUCCESS(status) ? status : AE_CTRL_DEPTH;
+}
 
-	result = acpi_bus_scan(device->handle, &ops, NULL);
+int acpi_bus_start(struct acpi_device *device)
+{
+	if (!device)
+		return -EINVAL;
 
+	acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, ACPI_UINT32_MAX,
+			    acpi_bus_start_device, NULL, NULL, NULL);
 	acpi_update_all_gpes();
-
-	return result;
+	return 0;
 }
 EXPORT_SYMBOL(acpi_bus_start);
 


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

* [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops
  2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
                   ` (2 preceding siblings ...)
  2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
@ 2012-12-09 23:02 ` Rafael J. Wysocki
  2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-09 23:02 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Objects of type struct acpi_bus_ops are currently used to pass
information between different parts of the ACPI namespace scanning
code, sometimes in quite convoluted ways.  It turns out that that
is not necessary in some cases, so simplify the code by reducing
the utilization of struct acpi_bus_ops objects where clearly
possible.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   39 +++++++++++++++------------------------
 1 file changed, 15 insertions(+), 24 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1527,7 +1527,6 @@ end:
 static void acpi_bus_add_power_resource(acpi_handle handle)
 {
 	struct acpi_bus_ops ops = {
-		.acpi_op_add = 1,
 		.acpi_op_start = 1,
 		.acpi_op_match = 1,
 	};
@@ -1581,7 +1580,6 @@ static int acpi_bus_type_and_status(acpi
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
 				      void *context, void **return_value)
 {
-	struct acpi_bus_ops *ops = context;
 	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
@@ -1609,11 +1607,13 @@ static acpi_status acpi_bus_check_add(ac
 	 * so, we needn't add it again, but we may still have to start it.
 	 */
 	acpi_bus_get_device(handle, &device);
-	if (ops->acpi_op_add && !device) {
-		struct acpi_bus_ops add_ops = *ops;
+	if (!device) {
+		struct acpi_bus_ops ops = {
+			.acpi_op_start = !!context,
+			.acpi_op_match = 0,
+		};
 
-		add_ops.acpi_op_match = 0;
-		acpi_add_single_object(&device, handle, type, sta, &add_ops);
+		acpi_add_single_object(&device, handle, type, sta, &ops);
 		if (!device)
 			return AE_CTRL_DEPTH;
 
@@ -1647,21 +1647,21 @@ static acpi_status acpi_bus_match_device
 	return status;
 }
 
-static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
+static int acpi_bus_scan(acpi_handle handle, bool start,
 			 struct acpi_device **child)
 {
 	void *device = NULL;
 	acpi_status status;
 	int ret = 0;
 
-	status = acpi_bus_check_add(handle, 0, ops, &device);
+	status = acpi_bus_check_add(handle, 0, (void *)start, &device);
 	if (ACPI_FAILURE(status)) {
 		ret = -ENODEV;
 		goto out;
 	}
 
 	acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-			    acpi_bus_check_add, NULL, ops, &device);
+			    acpi_bus_check_add, NULL, (void *)start, &device);
 	if (device)
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
 				    acpi_bus_match_device, NULL, NULL, NULL);
@@ -1691,9 +1691,7 @@ int
 acpi_bus_add(struct acpi_device **child,
 	     struct acpi_device *parent, acpi_handle handle, int type)
 {
-	struct acpi_bus_ops ops = { .acpi_op_add = 1, };
-
-	return acpi_bus_scan(handle, &ops, child);
+	return acpi_bus_scan(handle, false, child);
 }
 EXPORT_SYMBOL(acpi_bus_add);
 
@@ -1781,12 +1779,10 @@ static int acpi_bus_scan_fixed(void)
 {
 	int result = 0;
 	struct acpi_device *device = NULL;
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
-	ops.acpi_op_start = 1;
-	ops.acpi_op_match = 1;
+	struct acpi_bus_ops ops = {
+		.acpi_op_start = 1,
+		.acpi_op_match = 1,
+	};
 
 	/*
 	 * Enumerate all fixed-feature devices.
@@ -1812,11 +1808,6 @@ static int acpi_bus_scan_fixed(void)
 int __init acpi_scan_init(void)
 {
 	int result;
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
-	ops.acpi_op_start = 1;
 
 	result = bus_register(&acpi_bus_type);
 	if (result) {
@@ -1830,7 +1821,7 @@ int __init acpi_scan_init(void)
 	/*
 	 * Enumerate devices in the ACPI namespace.
 	 */
-	result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
+	result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root);
 
 	if (!result)
 		result = acpi_bus_scan_fixed();


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

* [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
                   ` (3 preceding siblings ...)
  2012-12-09 23:02 ` [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
@ 2012-12-09 23:03 ` Rafael J. Wysocki
  2012-12-10  5:34   ` Yinghai Lu
  2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-09 23:03 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Notice that one member of struct acpi_bus_ops, acpi_op_add, is not
used anywhere any more and the relationship between its remaining
members, acpi_op_match and acpi_op_start, is such that it doesn't
make sense to set the latter without setting the former at the same
time.  Therefore, replace struct acpi_bus_ops with new a enum type,
enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC,
ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to
both acpi_op_match and acpi_op_start unset, acpi_op_match set and
acpi_op_start unset, and both acpi_op_match and acpi_op_start set,
respectively.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c     |   35 ++++++++++++-----------------------
 include/acpi/acpi_bus.h |   15 ++++++++-------
 2 files changed, 20 insertions(+), 30 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -494,7 +494,7 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return acpi_dev->bus_ops.acpi_op_match
+	return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH
 		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
@@ -580,7 +580,7 @@ static int acpi_device_probe(struct devi
 
 	ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
 	if (!ret) {
-		if (acpi_dev->bus_ops.acpi_op_start)
+		if (acpi_dev->add_type == ACPI_BUS_ADD_START)
 			acpi_start_single_object(acpi_dev);
 
 		if (acpi_drv->ops.notify) {
@@ -1433,7 +1433,7 @@ static void acpi_hot_add_bind(struct acp
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
 				  unsigned long long sta,
-				  struct acpi_bus_ops *ops)
+				  enum acpi_bus_add_type add_type)
 {
 	int result;
 	struct acpi_device *device;
@@ -1449,7 +1449,7 @@ static int acpi_add_single_object(struct
 	device->device_type = type;
 	device->handle = handle;
 	device->parent = acpi_bus_get_parent(handle);
-	device->bus_ops = *ops; /* workround for not call .start */
+	device->add_type = add_type;
 	STRUCT_TO_INT(device->status) = sta;
 
 	acpi_device_get_busid(device);
@@ -1502,7 +1502,7 @@ static int acpi_add_single_object(struct
 
 	result = acpi_device_register(device);
 
-	if (device->bus_ops.acpi_op_match)
+	if (device->add_type >= ACPI_BUS_ADD_MATCH)
 		acpi_hot_add_bind(device);
 
 end:
@@ -1526,16 +1526,12 @@ end:
 
 static void acpi_bus_add_power_resource(acpi_handle handle)
 {
-	struct acpi_bus_ops ops = {
-		.acpi_op_start = 1,
-		.acpi_op_match = 1,
-	};
 	struct acpi_device *device = NULL;
 
 	acpi_bus_get_device(handle, &device);
 	if (!device)
 		acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
-					ACPI_STA_DEFAULT, &ops);
+					ACPI_STA_DEFAULT, ACPI_BUS_ADD_START);
 }
 
 static int acpi_bus_type_and_status(acpi_handle handle, int *type,
@@ -1608,16 +1604,13 @@ static acpi_status acpi_bus_check_add(ac
 	 */
 	acpi_bus_get_device(handle, &device);
 	if (!device) {
-		struct acpi_bus_ops ops = {
-			.acpi_op_start = !!context,
-			.acpi_op_match = 0,
-		};
-
-		acpi_add_single_object(&device, handle, type, sta, &ops);
+		acpi_add_single_object(&device, handle, type, sta,
+				       ACPI_BUS_ADD_BASIC);
 		if (!device)
 			return AE_CTRL_DEPTH;
 
-		device->bus_ops.acpi_op_match = 1;
+		device->add_type = context ?
+					ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
 	}
 
 	if (!*return_value)
@@ -1779,10 +1772,6 @@ static int acpi_bus_scan_fixed(void)
 {
 	int result = 0;
 	struct acpi_device *device = NULL;
-	struct acpi_bus_ops ops = {
-		.acpi_op_start = 1,
-		.acpi_op_match = 1,
-	};
 
 	/*
 	 * Enumerate all fixed-feature devices.
@@ -1791,7 +1780,7 @@ static int acpi_bus_scan_fixed(void)
 		result = acpi_add_single_object(&device, NULL,
 						ACPI_BUS_TYPE_POWER_BUTTON,
 						ACPI_STA_DEFAULT,
-						&ops);
+						ACPI_BUS_ADD_START);
 		device_init_wakeup(&device->dev, true);
 	}
 
@@ -1799,7 +1788,7 @@ static int acpi_bus_scan_fixed(void)
 		result = acpi_add_single_object(&device, NULL,
 						ACPI_BUS_TYPE_SLEEP_BUTTON,
 						ACPI_STA_DEFAULT,
-						&ops);
+						ACPI_BUS_ADD_START);
 	}
 
 	return result;
Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -63,6 +63,13 @@ acpi_get_physical_device_location(acpi_h
 #define ACPI_BUS_FILE_ROOT	"acpi"
 extern struct proc_dir_entry *acpi_root_dir;
 
+enum acpi_bus_add_type {
+	ACPI_BUS_ADD_BASIC = 0,
+	ACPI_BUS_ADD_MATCH,
+	ACPI_BUS_ADD_START,
+	ACPI_BUS_ADD_TYPE_COUNT
+};
+
 enum acpi_bus_removal_type {
 	ACPI_BUS_REMOVAL_NORMAL = 0,
 	ACPI_BUS_REMOVAL_EJECT,
@@ -95,12 +102,6 @@ typedef int (*acpi_op_bind) (struct acpi
 typedef int (*acpi_op_unbind) (struct acpi_device * device);
 typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
 
-struct acpi_bus_ops {
-	u32 acpi_op_add:1;
-	u32 acpi_op_start:1;
-	u32 acpi_op_match:1;
-};
-
 struct acpi_device_ops {
 	acpi_op_add add;
 	acpi_op_remove remove;
@@ -284,7 +285,7 @@ struct acpi_device {
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
-	struct acpi_bus_ops bus_ops;	/* workaround for different code path for hotplug */
+	enum acpi_bus_add_type add_type;	/* how to handle adding */
 	enum acpi_bus_removal_type removal_type;	/* indicate for different removal type */
 	u8 physical_node_count;
 	struct list_head physical_node_list;


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

* [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add()
  2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
                   ` (4 preceding siblings ...)
  2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
@ 2012-12-09 23:04 ` Rafael J. Wysocki
  2012-12-13  1:00   ` Bjorn Helgaas
  2012-12-13 11:45 ` [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
  7 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-09 23:04 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

If acpi_bus_check_add() is called for a handle already having an
existing struct acpi_device object attached, it is not necessary to
check the type and status of the device correspondig to it, so
change the ordering of acpi_bus_check_add() to avoid that.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac
 	acpi_status status;
 	int result;
 
+	acpi_bus_get_device(handle, &device);
+	if (device)
+		goto out;
+
 	result = acpi_bus_type_and_status(handle, &type, &sta);
 	if (result)
 		return AE_OK;
@@ -1602,17 +1606,13 @@ static acpi_status acpi_bus_check_add(ac
 	 * We may already have an acpi_device from a previous enumeration.  If
 	 * so, we needn't add it again, but we may still have to start it.
 	 */
-	acpi_bus_get_device(handle, &device);
-	if (!device) {
-		acpi_add_single_object(&device, handle, type, sta,
-				       ACPI_BUS_ADD_BASIC);
-		if (!device)
-			return AE_CTRL_DEPTH;
+	acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC);
+	if (!device)
+		return AE_CTRL_DEPTH;
 
-		device->add_type = context ?
-					ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
-	}
+	device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
 
+ out:
 	if (!*return_value)
 		*return_value = device;
 


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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
@ 2012-12-10  5:34   ` Yinghai Lu
  2012-12-10 14:46     ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Yinghai Lu @ 2012-12-10  5:34 UTC (permalink / raw)
  To: Rafael J. Wysocki, Greg Kroah-Hartman
  Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Toshi Kani, Myron Stowe

On Sun, Dec 9, 2012 at 3:03 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Notice that one member of struct acpi_bus_ops, acpi_op_add, is not
> used anywhere any more and the relationship between its remaining
> members, acpi_op_match and acpi_op_start, is such that it doesn't
> make sense to set the latter without setting the former at the same
> time.  Therefore, replace struct acpi_bus_ops with new a enum type,
> enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC,
> ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to
> both acpi_op_match and acpi_op_start unset, acpi_op_match set and
> acpi_op_start unset, and both acpi_op_match and acpi_op_start set,
> respectively.
>

Can we expand the BUS_ADD_* concept to other devices instead of just
acpi_device?

aka we should let struct device has this add_type field.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-10  5:34   ` Yinghai Lu
@ 2012-12-10 14:46     ` Rafael J. Wysocki
  2012-12-10 17:07       ` Yinghai Lu
  0 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-10 14:46 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
> On Sun, Dec 9, 2012 at 3:03 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Notice that one member of struct acpi_bus_ops, acpi_op_add, is not
> > used anywhere any more and the relationship between its remaining
> > members, acpi_op_match and acpi_op_start, is such that it doesn't
> > make sense to set the latter without setting the former at the same
> > time.  Therefore, replace struct acpi_bus_ops with new a enum type,
> > enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC,
> > ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to
> > both acpi_op_match and acpi_op_start unset, acpi_op_match set and
> > acpi_op_start unset, and both acpi_op_match and acpi_op_start set,
> > respectively.
> >
> 
> Can we expand the BUS_ADD_* concept to other devices instead of just
> acpi_device?
> 
> aka we should let struct device has this add_type field.

Having done that in ACPI to cover our use case here, we can try to move it
into struct device if there are use cases beyond ACPI that can't be covered
by using deferred driver probing.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-10 14:46     ` Rafael J. Wysocki
@ 2012-12-10 17:07       ` Yinghai Lu
  2012-12-10 22:47         ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Yinghai Lu @ 2012-12-10 17:07 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
>>
>> Can we expand the BUS_ADD_* concept to other devices instead of just
>> acpi_device?
>>
>> aka we should let struct device has this add_type field.
>
> Having done that in ACPI to cover our use case here, we can try to move it
> into struct device if there are use cases beyond ACPI that can't be covered
> by using deferred driver probing.

pci device for hotplug have same problem. need to delay driver attach
for them too.

also BUS_ADD_MATCH and BUS_ADD_START are duplicated.

old add are separated to adding all devices to tree and then matching
work to load the drivers.

so _START is not needed anymore, only user.start in pci_root driver
should be removed.
code in .start could be moved .add without problem.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-10 17:07       ` Yinghai Lu
@ 2012-12-10 22:47         ` Rafael J. Wysocki
  2012-12-10 23:09           ` Rafael J. Wysocki
  2012-12-10 23:22           ` Yinghai Lu
  0 siblings, 2 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-10 22:47 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote:
> On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
> >>
> >> Can we expand the BUS_ADD_* concept to other devices instead of just
> >> acpi_device?
> >>
> >> aka we should let struct device has this add_type field.
> >
> > Having done that in ACPI to cover our use case here, we can try to move it
> > into struct device if there are use cases beyond ACPI that can't be covered
> > by using deferred driver probing.
> 
> pci device for hotplug have same problem. need to delay driver attach
> for them too.

OK, I'll take a look.  Any pointers to speed that up?

> also BUS_ADD_MATCH and BUS_ADD_START are duplicated.

Not at the moment, they do different things as code goes.

> old add are separated to adding all devices to tree and then matching
> work to load the drivers.
> 
> so _START is not needed anymore, only user.start in pci_root driver
> should be removed.
> code in .start could be moved .add without problem.

Yes, I'm going to do that as the next step.  I didn't want this particular
patchset to grow too big.  I'll post another one on top of it if people
don't have problems with this one.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-10 22:47         ` Rafael J. Wysocki
@ 2012-12-10 23:09           ` Rafael J. Wysocki
  2012-12-10 23:14             ` Yinghai Lu
  2012-12-10 23:22           ` Yinghai Lu
  1 sibling, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-10 23:09 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Monday, December 10, 2012 11:47:27 PM Rafael J. Wysocki wrote:
> On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote:
> > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
> > >>
> > >> Can we expand the BUS_ADD_* concept to other devices instead of just
> > >> acpi_device?
> > >>
> > >> aka we should let struct device has this add_type field.
> > >
> > > Having done that in ACPI to cover our use case here, we can try to move it
> > > into struct device if there are use cases beyond ACPI that can't be covered
> > > by using deferred driver probing.
> > 
> > pci device for hotplug have same problem. need to delay driver attach
> > for them too.
> 
> OK, I'll take a look.  Any pointers to speed that up?
> 
> > also BUS_ADD_MATCH and BUS_ADD_START are duplicated.
> 
> Not at the moment, they do different things as code goes.
> 
> > old add are separated to adding all devices to tree and then matching
> > work to load the drivers.
> > 
> > so _START is not needed anymore, only user.start in pci_root driver
> > should be removed.
> > code in .start could be moved .add without problem.
> 
> Yes, I'm going to do that as the next step.  I didn't want this particular
> patchset to grow too big.  I'll post another one on top of it if people
> don't have problems with this one.

By the way, can you please remind me where you wanted to put the
pci_bus_add_devices() and why?

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-10 23:09           ` Rafael J. Wysocki
@ 2012-12-10 23:14             ` Yinghai Lu
  2012-12-11  1:02               ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Yinghai Lu @ 2012-12-10 23:14 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Mon, Dec 10, 2012 at 3:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Monday, December 10, 2012 11:47:27 PM Rafael J. Wysocki wrote:
>> On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote:
>> > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
>> > >>
>> > >> Can we expand the BUS_ADD_* concept to other devices instead of just
>> > >> acpi_device?
>> > >>
>> > >> aka we should let struct device has this add_type field.
>> > >
>> > > Having done that in ACPI to cover our use case here, we can try to move it
>> > > into struct device if there are use cases beyond ACPI that can't be covered
>> > > by using deferred driver probing.
>> >
>> > pci device for hotplug have same problem. need to delay driver attach
>> > for them too.
>>
>> OK, I'll take a look.  Any pointers to speed that up?
>>
>> > also BUS_ADD_MATCH and BUS_ADD_START are duplicated.
>>
>> Not at the moment, they do different things as code goes.
>>
>> > old add are separated to adding all devices to tree and then matching
>> > work to load the drivers.
>> >
>> > so _START is not needed anymore, only user.start in pci_root driver
>> > should be removed.
>> > code in .start could be moved .add without problem.
>>
>> Yes, I'm going to do that as the next step.  I didn't want this particular
>> patchset to grow too big.  I'll post another one on top of it if people
>> don't have problems with this one.
>
> By the way, can you please remind me where you wanted to put the
> pci_bus_add_devices() and why?
>

please check my for-pci-next branch at
http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-next

that includes delay loading acpi driver and pci driver.

http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8c031eabbdc83dd4d93933b82d96b55d038bcb64
 PCI: prepare to use device drivers_autoprobe to delay attach drivers

http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=40a12dc8942a8ed02bfbf75ee1ffbfbdf1511b45
PCI: Use device_add for device and bus early

http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8af9b4c250091c30afedeb2e7f14fca06997c811
ACPI: add drivers_autoprobe in struct acpi_device

http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=ae498e157e9dc8794932562b2f885ddc3a1a229a
 ACPI: use device drivers_autoprobe to delay loading acpi drivers

http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=6bee785b563a0b0e311e188321b1160593d5e6ee
 PCI, ACPI: Remove not used acpi_pci_root_start()

http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=f467a1cd18a07a250be8527b94612fd4a654fbd1
ACPI: remove acpi_op_start workaround

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-10 22:47         ` Rafael J. Wysocki
  2012-12-10 23:09           ` Rafael J. Wysocki
@ 2012-12-10 23:22           ` Yinghai Lu
  2012-12-11  0:48             ` Rafael J. Wysocki
  1 sibling, 1 reply; 88+ messages in thread
From: Yinghai Lu @ 2012-12-10 23:22 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Mon, Dec 10, 2012 at 2:47 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote:
>> On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
>> >>
>> >> Can we expand the BUS_ADD_* concept to other devices instead of just
>> >> acpi_device?
>> >>
>> >> aka we should let struct device has this add_type field.
>> >
>> > Having done that in ACPI to cover our use case here, we can try to move it
>> > into struct device if there are use cases beyond ACPI that can't be covered
>> > by using deferred driver probing.
>>
>> pci device for hotplug have same problem. need to delay driver attach
>> for them too.
>
> OK, I'll take a look.  Any pointers to speed that up?
>
>> also BUS_ADD_MATCH and BUS_ADD_START are duplicated.
>
> Not at the moment, they do different things as code goes.

I do think that is same problem which is in the driver/base core.

it should support delay loading driver for the hotplug case at the first point.
that is reason that .start is introduced for acpi driver..to workround
the problem
in driver core.

>
>> old add are separated to adding all devices to tree and then matching
>> work to load the drivers.
>>
>> so _START is not needed anymore, only user.start in pci_root driver
>> should be removed.
>> code in .start could be moved .add without problem.
>
> Yes, I'm going to do that as the next step.  I didn't want this particular

after you remove that .start, that will the same as my two patches.
except that you patches toggle that per-device add_type for every device.

and my patches is only toggle that per device drivers_autoprobe for
hot-add devices.

> patchset to grow too big.  I'll post another one on top of it if people
> don't have problems with this one.

yesterday, I replace my two acpi driver delay loading patches with your patches.

during pci root bus hot remove/add test, got the panic...

did not have time to look at it yet.

Yinghai

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-10 23:22           ` Yinghai Lu
@ 2012-12-11  0:48             ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-11  0:48 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Monday, December 10, 2012 03:22:48 PM Yinghai Lu wrote:
> On Mon, Dec 10, 2012 at 2:47 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote:
> >> On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >> > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
> >> >>
> >> >> Can we expand the BUS_ADD_* concept to other devices instead of just
> >> >> acpi_device?
> >> >>
> >> >> aka we should let struct device has this add_type field.
> >> >
> >> > Having done that in ACPI to cover our use case here, we can try to move it
> >> > into struct device if there are use cases beyond ACPI that can't be covered
> >> > by using deferred driver probing.
> >>
> >> pci device for hotplug have same problem. need to delay driver attach
> >> for them too.
> >
> > OK, I'll take a look.  Any pointers to speed that up?
> >
> >> also BUS_ADD_MATCH and BUS_ADD_START are duplicated.
> >
> > Not at the moment, they do different things as code goes.
> 
> I do think that is same problem which is in the driver/base core.
> 
> it should support delay loading driver for the hotplug case at the first point.
> that is reason that .start is introduced for acpi driver..to workround
> the problem
> in driver core.

OK, but let's eliminate .start() first and then go make changes to the
driver core.  That is, let's take one step at a time. :-)

> >> old add are separated to adding all devices to tree and then matching
> >> work to load the drivers.
> >>
> >> so _START is not needed anymore, only user.start in pci_root driver
> >> should be removed.
> >> code in .start could be moved .add without problem.
> >
> > Yes, I'm going to do that as the next step.  I didn't want this particular
> 
> after you remove that .start, that will the same as my two patches.
> except that you patches toggle that per-device add_type for every device.
> 
> and my patches is only toggle that per device drivers_autoprobe for
> hot-add devices.

I'm not 100% sure of that, but quite likely that's the case.  I'd like to avoid
special-casing hotplug in any way, if possible.  Also, I have other reasons to
do it for all devices (like the resources management for one example).

> > patchset to grow too big.  I'll post another one on top of it if people
> > don't have problems with this one.
> 
> yesterday, I replace my two acpi driver delay loading patches with your patches.
> 
> during pci root bus hot remove/add test, got the panic...

I don't see what the reason may be at the moment, it would be good to get more
info (like a screenshot of the panic).

> did not have time to look at it yet.

OK

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-10 23:14             ` Yinghai Lu
@ 2012-12-11  1:02               ` Rafael J. Wysocki
  2012-12-11  1:28                 ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-11  1:02 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Monday, December 10, 2012 03:14:32 PM Yinghai Lu wrote:
> On Mon, Dec 10, 2012 at 3:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Monday, December 10, 2012 11:47:27 PM Rafael J. Wysocki wrote:
> >> On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote:
> >> > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >> > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
> >> > >>
> >> > >> Can we expand the BUS_ADD_* concept to other devices instead of just
> >> > >> acpi_device?
> >> > >>
> >> > >> aka we should let struct device has this add_type field.
> >> > >
> >> > > Having done that in ACPI to cover our use case here, we can try to move it
> >> > > into struct device if there are use cases beyond ACPI that can't be covered
> >> > > by using deferred driver probing.
> >> >
> >> > pci device for hotplug have same problem. need to delay driver attach
> >> > for them too.
> >>
> >> OK, I'll take a look.  Any pointers to speed that up?
> >>
> >> > also BUS_ADD_MATCH and BUS_ADD_START are duplicated.
> >>
> >> Not at the moment, they do different things as code goes.
> >>
> >> > old add are separated to adding all devices to tree and then matching
> >> > work to load the drivers.
> >> >
> >> > so _START is not needed anymore, only user.start in pci_root driver
> >> > should be removed.
> >> > code in .start could be moved .add without problem.
> >>
> >> Yes, I'm going to do that as the next step.  I didn't want this particular
> >> patchset to grow too big.  I'll post another one on top of it if people
> >> don't have problems with this one.
> >
> > By the way, can you please remind me where you wanted to put the
> > pci_bus_add_devices() and why?
> >
> 
> please check my for-pci-next branch at
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-next
> 
> that includes delay loading acpi driver and pci driver.
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8c031eabbdc83dd4d93933b82d96b55d038bcb64
>  PCI: prepare to use device drivers_autoprobe to delay attach drivers
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=40a12dc8942a8ed02bfbf75ee1ffbfbdf1511b45
> PCI: Use device_add for device and bus early
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8af9b4c250091c30afedeb2e7f14fca06997c811
> ACPI: add drivers_autoprobe in struct acpi_device
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=ae498e157e9dc8794932562b2f885ddc3a1a229a
>  ACPI: use device drivers_autoprobe to delay loading acpi drivers
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=6bee785b563a0b0e311e188321b1160593d5e6ee
>  PCI, ACPI: Remove not used acpi_pci_root_start()
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=f467a1cd18a07a250be8527b94612fd4a654fbd1
> ACPI: remove acpi_op_start workaround

OK, thanks for the pointers.  I actually see more differences between our
patchsets.  For one example, you seem to have left the parent->ops.bind()
stuff in acpi_add_single_object() which calls it even drivers_autoprobe is
set.  Is that the case, or am I missing anything?

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-11  1:02               ` Rafael J. Wysocki
@ 2012-12-11  1:28                 ` Rafael J. Wysocki
  2012-12-11  2:26                   ` Yinghai Lu
  0 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-11  1:28 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Tuesday, December 11, 2012 02:02:14 AM Rafael J. Wysocki wrote:
> On Monday, December 10, 2012 03:14:32 PM Yinghai Lu wrote:
> > On Mon, Dec 10, 2012 at 3:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > > On Monday, December 10, 2012 11:47:27 PM Rafael J. Wysocki wrote:
> > >> On Monday, December 10, 2012 09:07:06 AM Yinghai Lu wrote:
> > >> > On Mon, Dec 10, 2012 at 6:46 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > >> > > On Sunday, December 09, 2012 09:34:42 PM Yinghai Lu wrote:
> > >> > >>
> > >> > >> Can we expand the BUS_ADD_* concept to other devices instead of just
> > >> > >> acpi_device?
> > >> > >>
> > >> > >> aka we should let struct device has this add_type field.
> > >> > >
> > >> > > Having done that in ACPI to cover our use case here, we can try to move it
> > >> > > into struct device if there are use cases beyond ACPI that can't be covered
> > >> > > by using deferred driver probing.
> > >> >
> > >> > pci device for hotplug have same problem. need to delay driver attach
> > >> > for them too.
> > >>
> > >> OK, I'll take a look.  Any pointers to speed that up?
> > >>
> > >> > also BUS_ADD_MATCH and BUS_ADD_START are duplicated.
> > >>
> > >> Not at the moment, they do different things as code goes.
> > >>
> > >> > old add are separated to adding all devices to tree and then matching
> > >> > work to load the drivers.
> > >> >
> > >> > so _START is not needed anymore, only user.start in pci_root driver
> > >> > should be removed.
> > >> > code in .start could be moved .add without problem.
> > >>
> > >> Yes, I'm going to do that as the next step.  I didn't want this particular
> > >> patchset to grow too big.  I'll post another one on top of it if people
> > >> don't have problems with this one.
> > >
> > > By the way, can you please remind me where you wanted to put the
> > > pci_bus_add_devices() and why?
> > >
> > 
> > please check my for-pci-next branch at
> > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-next
> > 
> > that includes delay loading acpi driver and pci driver.
> > 
> > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8c031eabbdc83dd4d93933b82d96b55d038bcb64
> >  PCI: prepare to use device drivers_autoprobe to delay attach drivers
> > 
> > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=40a12dc8942a8ed02bfbf75ee1ffbfbdf1511b45
> > PCI: Use device_add for device and bus early
> > 
> > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8af9b4c250091c30afedeb2e7f14fca06997c811
> > ACPI: add drivers_autoprobe in struct acpi_device
> > 
> > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=ae498e157e9dc8794932562b2f885ddc3a1a229a
> >  ACPI: use device drivers_autoprobe to delay loading acpi drivers
> > 
> > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=6bee785b563a0b0e311e188321b1160593d5e6ee
> >  PCI, ACPI: Remove not used acpi_pci_root_start()
> > 
> > http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=f467a1cd18a07a250be8527b94612fd4a654fbd1
> > ACPI: remove acpi_op_start workaround
> 
> OK, thanks for the pointers.  I actually see more differences between our
> patchsets.  For one example, you seem to have left the parent->ops.bind()
> stuff in acpi_add_single_object() which calls it even drivers_autoprobe is
> set.

Sorry, that should have been "which calls it even when drivers_autoprobe is
not set".  I need to be more careful.


> Is that the case, or am I missing anything?

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-11  1:28                 ` Rafael J. Wysocki
@ 2012-12-11  2:26                   ` Yinghai Lu
  2012-12-11 12:45                     ` Rafael J. Wysocki
  2012-12-11 15:09                     ` Jiang Liu
  0 siblings, 2 replies; 88+ messages in thread
From: Yinghai Lu @ 2012-12-11  2:26 UTC (permalink / raw)
  To: Rafael J. Wysocki, Jiang Liu
  Cc: Greg Kroah-Hartman, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Mon, Dec 10, 2012 at 5:28 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>>
>> OK, thanks for the pointers.  I actually see more differences between our
>> patchsets.  For one example, you seem to have left the parent->ops.bind()
>> stuff in acpi_add_single_object() which calls it even drivers_autoprobe is
>> set.
>
> Sorry, that should have been "which calls it even when drivers_autoprobe is
> not set".  I need to be more careful.
>

oh,  Jiang Liu had one patch to remove that workaround.

http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=b40dba80c2b8395570d8357e6b3f417c27c84504

ACPI/pci-bind: remove bind/unbind callbacks from acpi_device_ops

Maybe you can review that patches in my for-pci-next2...
those are ACPI related anyway.

those patches have been there for a while, and Bjorn did not have time
to digest them.

or you prefer I resend updated version as huge whole patchset?

Thanks

Yinghai

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-11  2:26                   ` Yinghai Lu
@ 2012-12-11 12:45                     ` Rafael J. Wysocki
  2012-12-11 15:09                     ` Jiang Liu
  1 sibling, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-11 12:45 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas, LKML,
	ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe

On Monday, December 10, 2012 06:26:08 PM Yinghai Lu wrote:
> On Mon, Dec 10, 2012 at 5:28 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >>
> >> OK, thanks for the pointers.  I actually see more differences between our
> >> patchsets.  For one example, you seem to have left the parent->ops.bind()
> >> stuff in acpi_add_single_object() which calls it even drivers_autoprobe is
> >> set.
> >
> > Sorry, that should have been "which calls it even when drivers_autoprobe is
> > not set".  I need to be more careful.
> >
> 
> oh,  Jiang Liu had one patch to remove that workaround.
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=b40dba80c2b8395570d8357e6b3f417c27c84504
> 
> ACPI/pci-bind: remove bind/unbind callbacks from acpi_device_ops

OK, so I'm looking at the current code, which for me is the master branch of
the linux-pm.git tree (the linux-next branch is the same ATM), and I'm not
seeing acpi_pci_unbind_cb() in there.  So surely this patch applies to
something different, right?  In which case I wonder what reason there is for
me to look at it at all?

Besides, I think it may be done differently and in a more straightforward
way.  Namely, on top of my current patchset, it is guaranteed that not only
struct pci_dev objects will always be registered after the companion struct
acpi_device ones, but also they always will be *created* after those
companion objects have been registered.  So in principle we can populate
a new struct pci_dev's ACPI handle as soon as in pci_scan_device(),
next to pci_set_of_node().  Then, we can do something like acpi_pci_bind(),
although without the whole acpi_get_pci_dev() nonsense, in pci_setup_device(),
in which case we won't need to do it anywhere else.

As an added benefit, acpi_platform_notify() would then see a populated ACPI
handle in that struct pci_dev when finally registering the PCI device, so it
wouldn't need to do the whole acpi_find_bridge_device() and type->find_device()
dance.

> Maybe you can review that patches in my for-pci-next2...
> those are ACPI related anyway.

I can, provided that (1) they are based on top of my tree or v3.7 and (2)
they don't conflict with patches we're currently discussing.

> those patches have been there for a while, and Bjorn did not have time
> to digest them.

Well, Bjorn's review bandwidth is limited and we need to take that into
account.

> or you prefer I resend updated version as huge whole patchset?

No, no huge patchsets, please.  Let's take one step at a time, so that
everyone involved/interested can understand what's going on, OK?

My review capacity also is not unlimited, mind you.  I can't promise I'll
have the time to review more than a few patches a day (where "a few" is
rather less than "several").

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-11  2:26                   ` Yinghai Lu
  2012-12-11 12:45                     ` Rafael J. Wysocki
@ 2012-12-11 15:09                     ` Jiang Liu
  2012-12-11 18:30                       ` Rafael J. Wysocki
  1 sibling, 1 reply; 88+ messages in thread
From: Jiang Liu @ 2012-12-11 15:09 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Rafael J. Wysocki, Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas,
	LKML, ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe

Hi Rafael,
	I have worked out a patch set to clean up ACPI/PCI related notifications,
please refer to
http://www.spinics.net/lists/linux-pci/msg17822.html
	The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will
help to rebase it if needed.
Regards!
Gerry

On 12/11/2012 10:26 AM, Yinghai Lu wrote:
> On Mon, Dec 10, 2012 at 5:28 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>>>
>>> OK, thanks for the pointers.  I actually see more differences between our
>>> patchsets.  For one example, you seem to have left the parent->ops.bind()
>>> stuff in acpi_add_single_object() which calls it even drivers_autoprobe is
>>> set.
>>
>> Sorry, that should have been "which calls it even when drivers_autoprobe is
>> not set".  I need to be more careful.
>>
> 
> oh,  Jiang Liu had one patch to remove that workaround.
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=b40dba80c2b8395570d8357e6b3f417c27c84504
> 
> ACPI/pci-bind: remove bind/unbind callbacks from acpi_device_ops
> 
> Maybe you can review that patches in my for-pci-next2...
> those are ACPI related anyway.
> 
> those patches have been there for a while, and Bjorn did not have time
> to digest them.
> 
> or you prefer I resend updated version as huge whole patchset?
> 
> Thanks
> 
> Yinghai
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-11 15:09                     ` Jiang Liu
@ 2012-12-11 18:30                       ` Rafael J. Wysocki
  2012-12-12 14:34                         ` Yijing Wang
  0 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-11 18:30 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Jiang Liu, Greg Kroah-Hartman, Bjorn Helgaas, LKML,
	ACPI Devel Maling List, linux-pci, Toshi Kani, Myron Stowe

Hi Gerry,

On Tuesday, December 11, 2012 11:09:06 PM Jiang Liu wrote:
> Hi Rafael,
> 	I have worked out a patch set to clean up ACPI/PCI related notifications,
> please refer to
> http://www.spinics.net/lists/linux-pci/msg17822.html
> 	The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will
> help to rebase it if needed.

I have reviewed the patches and I think they make sense overall.  However,
the statement that acpi_pci_bind()/acpi_pci_unbind() are used to maintain
PCI-ACPI binding relationships is quite inaccurate, because all what these
functions do is to (1) add/remove ACPI PM notifiers to/from PCI devices and
(2) retrieve the _PRT information for bridges from ACPI tables.  In fact,
the *binding* itself is managed by the code in drivers/acpi/glue.c.

Also, please have a look at my suggestion in the last reply to Yinghai:

http://marc.info/?l=linux-pci&m=135522965707752&w=2

In fact, I think we can go even further than that.  Namely, if we populate the
ACPI handle of the device in pci_scan_device(), then we can just move the PM
notifier and wakeup setup to platform_pci_wakeup_init(), where it should be
(we'll also need to add a corresponding _exit() function, then, but that'll be
much cleaner anyway).

Then, the remaining thing would be to ensure that _PRT entries are parsed
as appropriate somewhere around pci_init_capabilities().

Also, I wonder if you can help test the $subject patchset on a system with
hardware PCI hotplug (preferably on top of the linux-pm.git/master branch)?

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-11 18:30                       ` Rafael J. Wysocki
@ 2012-12-12 14:34                         ` Yijing Wang
  2012-12-12 15:05                           ` Jiang Liu
  0 siblings, 1 reply; 88+ messages in thread
From: Yijing Wang @ 2012-12-12 14:34 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Jiang Liu, Yinghai Lu, Jiang Liu, Greg Kroah-Hartman,
	Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Toshi Kani, Myron Stowe

于 2012-12-12 2:30, Rafael J. Wysocki 写道:
> Hi Gerry,
> 
> On Tuesday, December 11, 2012 11:09:06 PM Jiang Liu wrote:
>> Hi Rafael,
>> 	I have worked out a patch set to clean up ACPI/PCI related notifications,
>> please refer to
>> http://www.spinics.net/lists/linux-pci/msg17822.html
>> 	The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will
>> help to rebase it if needed.
> 
> I have reviewed the patches and I think they make sense overall.  However,
> the statement that acpi_pci_bind()/acpi_pci_unbind() are used to maintain
> PCI-ACPI binding relationships is quite inaccurate, because all what these
> functions do is to (1) add/remove ACPI PM notifiers to/from PCI devices and
> (2) retrieve the _PRT information for bridges from ACPI tables.  In fact,
> the *binding* itself is managed by the code in drivers/acpi/glue.c.
> 
> Also, please have a look at my suggestion in the last reply to Yinghai:
> 
> http://marc.info/?l=linux-pci&m=135522965707752&w=2
> 
> In fact, I think we can go even further than that.  Namely, if we populate the
> ACPI handle of the device in pci_scan_device(), then we can just move the PM
> notifier and wakeup setup to platform_pci_wakeup_init(), where it should be
> (we'll also need to add a corresponding _exit() function, then, but that'll be
> much cleaner anyway).
> 
> Then, the remaining thing would be to ensure that _PRT entries are parsed
> as appropriate somewhere around pci_init_capabilities().
> 
> Also, I wonder if you can help test the $subject patchset on a system with
> hardware PCI hotplug (preferably on top of the linux-pm.git/master branch)?
> 
Hi Rafael,
   We are doing test for this series patches, I will send out the test result as soon.

Thanks!
Yijing




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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-12 14:34                         ` Yijing Wang
@ 2012-12-12 15:05                           ` Jiang Liu
  2012-12-12 22:39                             ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Jiang Liu @ 2012-12-12 15:05 UTC (permalink / raw)
  To: Yijing Wang
  Cc: Rafael J. Wysocki, Yinghai Lu, Jiang Liu, Greg Kroah-Hartman,
	Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Toshi Kani, Myron Stowe

On 12/12/2012 10:34 PM, Yijing Wang wrote:
> 于 2012-12-12 2:30, Rafael J. Wysocki 写道:
>> Hi Gerry,
>>
>> On Tuesday, December 11, 2012 11:09:06 PM Jiang Liu wrote:
>>> Hi Rafael,
>>> 	I have worked out a patch set to clean up ACPI/PCI related notifications,
>>> please refer to
>>> http://www.spinics.net/lists/linux-pci/msg17822.html
>>> 	The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will
>>> help to rebase it if needed.
>>
>> I have reviewed the patches and I think they make sense overall.  However,
>> the statement that acpi_pci_bind()/acpi_pci_unbind() are used to maintain
>> PCI-ACPI binding relationships is quite inaccurate, because all what these
>> functions do is to (1) add/remove ACPI PM notifiers to/from PCI devices and
>> (2) retrieve the _PRT information for bridges from ACPI tables.  In fact,
>> the *binding* itself is managed by the code in drivers/acpi/glue.c.
>>
>> Also, please have a look at my suggestion in the last reply to Yinghai:
>>
>> http://marc.info/?l=linux-pci&m=135522965707752&w=2
>>
>> In fact, I think we can go even further than that.  Namely, if we populate the
>> ACPI handle of the device in pci_scan_device(), then we can just move the PM
>> notifier and wakeup setup to platform_pci_wakeup_init(), where it should be
>> (we'll also need to add a corresponding _exit() function, then, but that'll be
>> much cleaner anyway).
>>
>> Then, the remaining thing would be to ensure that _PRT entries are parsed
>> as appropriate somewhere around pci_init_capabilities().
>>
>> Also, I wonder if you can help test the $subject patchset on a system with
>> hardware PCI hotplug (preferably on top of the linux-pm.git/master branch)?
>>
> Hi Rafael,
>    We are doing test for this series patches, I will send out the test result as soon.
Hi Rafael,
	We have tried to merge your patchset with IOH hotplug patchsets from Yinghai,
and obviously it's not a ease task and we have run into panics. We will try to find
some ways to test your patchset only next step.
	Thanks!

> 
> Thanks!
> Yijing
> 
> 
> 


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

* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
@ 2012-12-12 15:50   ` Jiang Liu
  2012-12-12 22:34     ` Rafael J. Wysocki
  2012-12-12 16:38   ` Jiang Liu
  2012-12-13  1:00   ` Bjorn Helgaas
  2 siblings, 1 reply; 88+ messages in thread
From: Jiang Liu @ 2012-12-12 15:50 UTC (permalink / raw)
  To: Rafael J. Wysocki, Yinghai Lu
  Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Toshi Kani, Myron Stowe

On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Currently, as soon as an ACPI device node object (struct acpi_device)
> is created, the driver core attempts to probe ACPI drivers against
> it.  That leads to some unpleasant side effects, like the fact that
> the boot code path for ACPI namespace scanning is different from the
> analogous hot-plug code path (during boot ACPI drivers are not
> present when ACPI device node objects are registered, so they are
> guaranteed not to be probed, which is not the case during hot-plug).
> That, in turn, leads to unnecessary complications in the PCI
> enumeration algorithm.
> 
> Reduce the differences between the boot and hot-plug cases by
> splitting the ACPI namespace scanning for devices into two passes,
> such that struct acpi_device objects are registerd in the first
> patch without probing ACPI drivers and the drivers are probed
> against them directly in the second pass.  This way ACPI drivers
> can assume that all of the ACPI device node objects in the given
> scope will be registered when their .add() routines run and the
> hot-plug case becomes the same as the boot case from their
> perspective.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/scan.c     |   96 +++++++++++++++++++++++++++++++++---------------
>  include/acpi/acpi_bus.h |    1 
>  2 files changed, 68 insertions(+), 29 deletions(-)
> 
> Index: linux/include/acpi/acpi_bus.h
> ===================================================================
> --- linux.orig/include/acpi/acpi_bus.h
> +++ linux/include/acpi/acpi_bus.h
> @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
>  struct acpi_bus_ops {
>  	u32 acpi_op_add:1;
>  	u32 acpi_op_start:1;
> +	u32 acpi_op_match:1;
>  };
>  
>  struct acpi_device_ops {
> Index: linux/drivers/acpi/scan.c
> ===================================================================
> --- linux.orig/drivers/acpi/scan.c
> +++ linux/drivers/acpi/scan.c
> @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
>  	struct acpi_device *acpi_dev = to_acpi_device(dev);
>  	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
>  
> -	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> +	return acpi_dev->bus_ops.acpi_op_match
> +		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
>  }
Hi Rafael,
	PCI host bridge hotplug has the same requirement to separate device
enumeration from device driver binding. And VFIO has a similar requirement too.
Yinghai and I have implemented two different solutions for PCI host bridge
hotplug but all rejected by Greg. So it would be great if we could promote
a common mechanism to the device core to temporarily disable binding drivers
to devices, which could used to support ACPI hotplug, PCI hotplug and VFIO.
Regards!
Gerry


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

* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
  2012-12-12 15:50   ` Jiang Liu
@ 2012-12-12 16:38   ` Jiang Liu
  2012-12-12 22:32     ` Rafael J. Wysocki
  2012-12-13  1:00   ` Bjorn Helgaas
  2 siblings, 1 reply; 88+ messages in thread
From: Jiang Liu @ 2012-12-12 16:38 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Yinghai Lu, Toshi Kani, Myron Stowe

On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Currently, as soon as an ACPI device node object (struct acpi_device)
snip
  
> @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac
>  	 * We may already have an acpi_device from a previous enumeration.  If
>  	 * so, we needn't add it again, but we may still have to start it.
>  	 */
> -	device = NULL;
>  	acpi_bus_get_device(handle, &device);
>  	if (ops->acpi_op_add && !device) {
> -		acpi_add_single_object(&device, handle, type, sta, ops);
> -		/* Is the device a known good platform device? */
> -		if (device
> -		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
> -			acpi_create_platform_device(device);
> -	}
> +		struct acpi_bus_ops add_ops = *ops;
>  
> -	if (!device)
> -		return AE_CTRL_DEPTH;
> -
> -	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> -		status = acpi_start_single_object(device);
> -		if (ACPI_FAILURE(status))
> +		add_ops.acpi_op_match = 0;
> +		acpi_add_single_object(&device, handle, type, sta, &add_ops);
> +		if (!device)
>  			return AE_CTRL_DEPTH;
> +
> +		device->bus_ops.acpi_op_match = 1;
>  	}
>  
>  	if (!*return_value)
>  		*return_value = device;
> +
>  	return AE_OK;
>  }
>  
> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> +					void *context, void **not_used)
> +{
> +	struct acpi_bus_ops *ops = context;
> +	struct acpi_device *device;
> +	acpi_status status = AE_OK;
> +
> +	if (acpi_bus_get_device(handle, &device))
> +		return AE_CTRL_DEPTH;
> +
> +	if (ops->acpi_op_add) {
> +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> +			/* This is a known good platform device. */
> +			acpi_create_platform_device(device);
> +		} else {
> +			int ret = device_attach(&device->dev);
> +			acpi_hot_add_bind(device);
> +			if (ret)
> +				status = AE_CTRL_DEPTH;
> +		}
> +	} else if (ops->acpi_op_start) {
> +		if (ACPI_FAILURE(acpi_start_single_object(device)))
> +			status = AE_CTRL_DEPTH;
> +	}
> +	return status;
> +}
> +
>  static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
>  			 struct acpi_device **child)
>  {
> -	acpi_status status;
>  	void *device = NULL;
> +	acpi_status status;
> +	int ret = 0;
>  
>  	status = acpi_bus_check_add(handle, 0, ops, &device);
> -	if (ACPI_SUCCESS(status))
> +	if (ACPI_FAILURE(status)) {
> +		ret = -ENODEV;
> +		goto out;
> +	}
> +
> +	acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> +			    acpi_bus_check_add, NULL, ops, &device);
> +	if (device)
>  		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> -				    acpi_bus_check_add, NULL, ops, &device);
> +				    acpi_bus_probe_start, NULL, ops, NULL);
Hi Rafael,
	Should we call acpi_bus_probe_start for the top device corresponding to 
"handle" too here?

> +	else
> +		ret = -ENODEV;
>  
> + out:
>  	if (child)
>  		*child = device;
>  
> -	if (device)
> -		return 0;
> -	else
> -		return -ENODEV;
> +	return ret;
>  }
>  
>  /*
> @@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void)
>  	memset(&ops, 0, sizeof(ops));
>  	ops.acpi_op_add = 1;
>  	ops.acpi_op_start = 1;
> +	ops.acpi_op_match = 1;
>  
>  	/*
>  	 * Enumerate all fixed-feature devices.
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


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

* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-12 16:38   ` Jiang Liu
@ 2012-12-12 22:32     ` Rafael J. Wysocki
  2012-12-12 23:43       ` [update][PATCH " Rafael J. Wysocki
  2012-12-13 13:05       ` [PATCH " Jiang Liu
  0 siblings, 2 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-12 22:32 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Yinghai Lu, Toshi Kani, Myron Stowe

On Thursday, December 13, 2012 12:38:01 AM Jiang Liu wrote:
> On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > Currently, as soon as an ACPI device node object (struct acpi_device)
> snip
>   
> > @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac
> >  	 * We may already have an acpi_device from a previous enumeration.  If
> >  	 * so, we needn't add it again, but we may still have to start it.
> >  	 */
> > -	device = NULL;
> >  	acpi_bus_get_device(handle, &device);
> >  	if (ops->acpi_op_add && !device) {
> > -		acpi_add_single_object(&device, handle, type, sta, ops);
> > -		/* Is the device a known good platform device? */
> > -		if (device
> > -		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
> > -			acpi_create_platform_device(device);
> > -	}
> > +		struct acpi_bus_ops add_ops = *ops;
> >  
> > -	if (!device)
> > -		return AE_CTRL_DEPTH;
> > -
> > -	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> > -		status = acpi_start_single_object(device);
> > -		if (ACPI_FAILURE(status))
> > +		add_ops.acpi_op_match = 0;
> > +		acpi_add_single_object(&device, handle, type, sta, &add_ops);
> > +		if (!device)
> >  			return AE_CTRL_DEPTH;
> > +
> > +		device->bus_ops.acpi_op_match = 1;
> >  	}
> >  
> >  	if (!*return_value)
> >  		*return_value = device;
> > +
> >  	return AE_OK;
> >  }
> >  
> > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> > +					void *context, void **not_used)
> > +{
> > +	struct acpi_bus_ops *ops = context;
> > +	struct acpi_device *device;
> > +	acpi_status status = AE_OK;
> > +
> > +	if (acpi_bus_get_device(handle, &device))
> > +		return AE_CTRL_DEPTH;
> > +
> > +	if (ops->acpi_op_add) {
> > +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> > +			/* This is a known good platform device. */
> > +			acpi_create_platform_device(device);
> > +		} else {
> > +			int ret = device_attach(&device->dev);
> > +			acpi_hot_add_bind(device);
> > +			if (ret)
> > +				status = AE_CTRL_DEPTH;
> > +		}
> > +	} else if (ops->acpi_op_start) {
> > +		if (ACPI_FAILURE(acpi_start_single_object(device)))
> > +			status = AE_CTRL_DEPTH;
> > +	}
> > +	return status;
> > +}
> > +
> >  static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
> >  			 struct acpi_device **child)
> >  {
> > -	acpi_status status;
> >  	void *device = NULL;
> > +	acpi_status status;
> > +	int ret = 0;
> >  
> >  	status = acpi_bus_check_add(handle, 0, ops, &device);
> > -	if (ACPI_SUCCESS(status))
> > +	if (ACPI_FAILURE(status)) {
> > +		ret = -ENODEV;
> > +		goto out;
> > +	}
> > +
> > +	acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> > +			    acpi_bus_check_add, NULL, ops, &device);
> > +	if (device)
> >  		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> > -				    acpi_bus_check_add, NULL, ops, &device);
> > +				    acpi_bus_probe_start, NULL, ops, NULL);
> Hi Rafael,
> 	Should we call acpi_bus_probe_start for the top device corresponding to 
> "handle" too here?

Do you mean separately?  I don't think so.  It will be covered by the namespace
walking, won't it?

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-12 15:50   ` Jiang Liu
@ 2012-12-12 22:34     ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-12 22:34 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yinghai Lu, Bjorn Helgaas, LKML, ACPI Devel Maling List,
	linux-pci, Toshi Kani, Myron Stowe

On Wednesday, December 12, 2012 11:50:06 PM Jiang Liu wrote:
> On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > Currently, as soon as an ACPI device node object (struct acpi_device)
> > is created, the driver core attempts to probe ACPI drivers against
> > it.  That leads to some unpleasant side effects, like the fact that
> > the boot code path for ACPI namespace scanning is different from the
> > analogous hot-plug code path (during boot ACPI drivers are not
> > present when ACPI device node objects are registered, so they are
> > guaranteed not to be probed, which is not the case during hot-plug).
> > That, in turn, leads to unnecessary complications in the PCI
> > enumeration algorithm.
> > 
> > Reduce the differences between the boot and hot-plug cases by
> > splitting the ACPI namespace scanning for devices into two passes,
> > such that struct acpi_device objects are registerd in the first
> > patch without probing ACPI drivers and the drivers are probed
> > against them directly in the second pass.  This way ACPI drivers
> > can assume that all of the ACPI device node objects in the given
> > scope will be registered when their .add() routines run and the
> > hot-plug case becomes the same as the boot case from their
> > perspective.
> > 
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  drivers/acpi/scan.c     |   96 +++++++++++++++++++++++++++++++++---------------
> >  include/acpi/acpi_bus.h |    1 
> >  2 files changed, 68 insertions(+), 29 deletions(-)
> > 
> > Index: linux/include/acpi/acpi_bus.h
> > ===================================================================
> > --- linux.orig/include/acpi/acpi_bus.h
> > +++ linux/include/acpi/acpi_bus.h
> > @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
> >  struct acpi_bus_ops {
> >  	u32 acpi_op_add:1;
> >  	u32 acpi_op_start:1;
> > +	u32 acpi_op_match:1;
> >  };
> >  
> >  struct acpi_device_ops {
> > Index: linux/drivers/acpi/scan.c
> > ===================================================================
> > --- linux.orig/drivers/acpi/scan.c
> > +++ linux/drivers/acpi/scan.c
> > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
> >  	struct acpi_device *acpi_dev = to_acpi_device(dev);
> >  	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
> >  
> > -	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> > +	return acpi_dev->bus_ops.acpi_op_match
> > +		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> >  }
> Hi Rafael,
> 	PCI host bridge hotplug has the same requirement to separate device
> enumeration from device driver binding. And VFIO has a similar requirement too.
> Yinghai and I have implemented two different solutions for PCI host bridge
> hotplug but all rejected by Greg. So it would be great if we could promote
> a common mechanism to the device core to temporarily disable binding drivers
> to devices, which could used to support ACPI hotplug, PCI hotplug and VFIO.

OK, but let's first have a good common use case, I think.  I mean, let's
implement it in each of these subsystems separately and then show that it
leads to simpler code if we move it up to the driver core.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-12 15:05                           ` Jiang Liu
@ 2012-12-12 22:39                             ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-12 22:39 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Yijing Wang, Yinghai Lu, Jiang Liu, Greg Kroah-Hartman,
	Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Toshi Kani, Myron Stowe

On Wednesday, December 12, 2012 11:05:15 PM Jiang Liu wrote:
> On 12/12/2012 10:34 PM, Yijing Wang wrote:
> > 于 2012-12-12 2:30, Rafael J. Wysocki 写道:
> >> Hi Gerry,
> >>
> >> On Tuesday, December 11, 2012 11:09:06 PM Jiang Liu wrote:
> >>> Hi Rafael,
> >>> 	I have worked out a patch set to clean up ACPI/PCI related notifications,
> >>> please refer to
> >>> http://www.spinics.net/lists/linux-pci/msg17822.html
> >>> 	The patchset doesn't apply cleanly to Bjorn's latest pci-next tree. I will
> >>> help to rebase it if needed.
> >>
> >> I have reviewed the patches and I think they make sense overall.  However,
> >> the statement that acpi_pci_bind()/acpi_pci_unbind() are used to maintain
> >> PCI-ACPI binding relationships is quite inaccurate, because all what these
> >> functions do is to (1) add/remove ACPI PM notifiers to/from PCI devices and
> >> (2) retrieve the _PRT information for bridges from ACPI tables.  In fact,
> >> the *binding* itself is managed by the code in drivers/acpi/glue.c.
> >>
> >> Also, please have a look at my suggestion in the last reply to Yinghai:
> >>
> >> http://marc.info/?l=linux-pci&m=135522965707752&w=2
> >>
> >> In fact, I think we can go even further than that.  Namely, if we populate the
> >> ACPI handle of the device in pci_scan_device(), then we can just move the PM
> >> notifier and wakeup setup to platform_pci_wakeup_init(), where it should be
> >> (we'll also need to add a corresponding _exit() function, then, but that'll be
> >> much cleaner anyway).
> >>
> >> Then, the remaining thing would be to ensure that _PRT entries are parsed
> >> as appropriate somewhere around pci_init_capabilities().
> >>
> >> Also, I wonder if you can help test the $subject patchset on a system with
> >> hardware PCI hotplug (preferably on top of the linux-pm.git/master branch)?
> >>
> > Hi Rafael,
> >    We are doing test for this series patches, I will send out the test result as soon.
> Hi Rafael,
> 	We have tried to merge your patchset with IOH hotplug patchsets from Yinghai,
> and obviously it's not a ease task and we have run into panics. We will try to find
> some ways to test your patchset only next step.

Thanks a lot for doing this, really appreciated!

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* [update][PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-12 22:32     ` Rafael J. Wysocki
@ 2012-12-12 23:43       ` Rafael J. Wysocki
  2012-12-13 13:05       ` [PATCH " Jiang Liu
  1 sibling, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-12 23:43 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Yinghai Lu, Toshi Kani, Myron Stowe

On Wednesday, December 12, 2012 11:32:57 PM Rafael J. Wysocki wrote:
> On Thursday, December 13, 2012 12:38:01 AM Jiang Liu wrote:
> > On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
 
[...]

> > >  static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
> > >  			 struct acpi_device **child)
> > >  {
> > > -	acpi_status status;
> > >  	void *device = NULL;
> > > +	acpi_status status;
> > > +	int ret = 0;
> > >  
> > >  	status = acpi_bus_check_add(handle, 0, ops, &device);
> > > -	if (ACPI_SUCCESS(status))
> > > +	if (ACPI_FAILURE(status)) {
> > > +		ret = -ENODEV;
> > > +		goto out;
> > > +	}
> > > +
> > > +	acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> > > +			    acpi_bus_check_add, NULL, ops, &device);
> > > +	if (device)
> > >  		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> > > -				    acpi_bus_check_add, NULL, ops, &device);
> > > +				    acpi_bus_probe_start, NULL, ops, NULL);
> > Hi Rafael,
> > 	Should we call acpi_bus_probe_start for the top device corresponding to 
> > "handle" too here?
> 
> Do you mean separately?  I don't think so.  It will be covered by the namespace
> walking, won't it?

There is one pitfall I didn't notice here, though.  acpi_bus_probe_start() has
to ignore errors from acpi_bus_type_and_status(), like acpi_bus_check_add()
does, because otherwise the namespace walk may be terminated too early.

Updated patch is below and I'll need to change some other patches in the
series to take that into account.

Thanks,
Rafael


---
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Subject: ACPI: Separate adding ACPI device objects from probing ACPI drivers

Currently, as soon as an ACPI device node object (struct acpi_device)
is created, the driver core attempts to probe ACPI drivers against
it.  That leads to some unpleasant side effects, like the fact that
the boot code path for ACPI namespace scanning is different from the
analogous hot-plug code path (during boot ACPI drivers are not
present when ACPI device node objects are registered, so they are
guaranteed not to be probed, which is not the case during hot-plug).
That, in turn, leads to unnecessary complications in the PCI
enumeration algorithm.

Reduce the differences between the boot and hot-plug cases by
splitting the ACPI namespace scanning for devices into two passes,
such that struct acpi_device objects are registerd in the first
patch without probing ACPI drivers and the drivers are probed
against them directly in the second pass.  This way ACPI drivers
can assume that all of the ACPI device node objects in the given
scope will be registered when their .add() routines run and the
hot-plug case becomes the same as the boot case from their
perspective.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c     |  105 ++++++++++++++++++++++++++++++++++--------------
 include/acpi/acpi_bus.h |    1 
 2 files changed, 77 insertions(+), 29 deletions(-)

Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
 struct acpi_bus_ops {
 	u32 acpi_op_add:1;
 	u32 acpi_op_start:1;
+	u32 acpi_op_match:1;
 };
 
 struct acpi_device_ops {
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+	return acpi_dev->bus_ops.acpi_op_match
+		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
 static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
 	return 0;
 }
 
+/*
+ * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
+ * @device: ACPI device node to bind.
+ */
+static void acpi_hot_add_bind(struct acpi_device *device)
+{
+	if (device->flags.bus_address
+	    && device->parent && device->parent->ops.bind)
+		device->parent->ops.bind(device);
+}
+
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
 				  unsigned long long sta,
@@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
 
 	result = acpi_device_register(device);
 
-	/*
-	 * Bind _ADR-Based Devices when hot add
-	 */
-	if (device->flags.bus_address) {
-		if (device->parent && device->parent->ops.bind)
-			device->parent->ops.bind(device);
-	}
+	if (device->bus_ops.acpi_op_match)
+		acpi_hot_add_bind(device);
 
 end:
 	if (!result) {
@@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
 	struct acpi_bus_ops ops = {
 		.acpi_op_add = 1,
 		.acpi_op_start = 1,
+		.acpi_op_match = 1,
 	};
 	struct acpi_device *device = NULL;
 
@@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
 				      void *context, void **return_value)
 {
 	struct acpi_bus_ops *ops = context;
+	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
-	struct acpi_device *device;
 	acpi_status status;
 	int result;
 
@@ -1600,48 +1608,86 @@ static acpi_status acpi_bus_check_add(ac
 	 * We may already have an acpi_device from a previous enumeration.  If
 	 * so, we needn't add it again, but we may still have to start it.
 	 */
-	device = NULL;
 	acpi_bus_get_device(handle, &device);
 	if (ops->acpi_op_add && !device) {
-		acpi_add_single_object(&device, handle, type, sta, ops);
-		/* Is the device a known good platform device? */
-		if (device
-		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
-			acpi_create_platform_device(device);
-	}
+		struct acpi_bus_ops add_ops = *ops;
 
-	if (!device)
-		return AE_CTRL_DEPTH;
-
-	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
-		status = acpi_start_single_object(device);
-		if (ACPI_FAILURE(status))
+		add_ops.acpi_op_match = 0;
+		acpi_add_single_object(&device, handle, type, sta, &add_ops);
+		if (!device)
 			return AE_CTRL_DEPTH;
+
+		device->bus_ops.acpi_op_match = 1;
 	}
 
 	if (!*return_value)
 		*return_value = device;
+
 	return AE_OK;
 }
 
+static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
+					void *context, void **not_used)
+{
+	struct acpi_bus_ops *ops = context;
+	acpi_status status = AE_OK;
+	struct acpi_device *device;
+	unsigned long long sta_not_used;
+	int type_not_used;
+
+	/*
+	 * We need to ignore errors ignored by acpi_bus_check_add() to avoid
+	 * terminating namespace walks prematurely.
+	 */
+	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+		return AE_OK;
+
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
+
+	if (ops->acpi_op_add) {
+		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+			/* This is a known good platform device. */
+			acpi_create_platform_device(device);
+		} else {
+			int ret = device_attach(&device->dev);
+			acpi_hot_add_bind(device);
+			if (ret)
+				status = AE_CTRL_DEPTH;
+		}
+	} else if (ops->acpi_op_start) {
+		if (ACPI_FAILURE(acpi_start_single_object(device)))
+			status = AE_CTRL_DEPTH;
+	}
+	return status;
+}
+
 static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
 			 struct acpi_device **child)
 {
-	acpi_status status;
 	void *device = NULL;
+	acpi_status status;
+	int ret = 0;
 
 	status = acpi_bus_check_add(handle, 0, ops, &device);
-	if (ACPI_SUCCESS(status))
+	if (ACPI_FAILURE(status)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+			    acpi_bus_check_add, NULL, ops, &device);
+	if (device)
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_check_add, NULL, ops, &device);
+				    acpi_bus_probe_start, NULL, ops, NULL);
+	else
+		ret = -ENODEV;
 
+ out:
 	if (child)
 		*child = device;
 
-	if (device)
-		return 0;
-	else
-		return -ENODEV;
+	return ret;
 }
 
 /*
@@ -1752,6 +1798,7 @@ static int acpi_bus_scan_fixed(void)
 	memset(&ops, 0, sizeof(ops));
 	ops.acpi_op_add = 1;
 	ops.acpi_op_start = 1;
+	ops.acpi_op_match = 1;
 
 	/*
 	 * Enumerate all fixed-feature devices.



-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* [Update][PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different
  2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
@ 2012-12-13  0:11   ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13  0:11 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Subject: ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different

The current ACPI namespace scanning code suggests that acpi_bus_add()
and acpi_bus_start() share some code.  In fact, however, they are
completely different code paths (except for the initial checks), so
refactor the code to make that distinction visibly clear.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---

Update is needed, because of a potential bug found in [1/6], as described here:

https://lkml.org/lkml/2012/12/12/460

Thanks,
Rafael

---
 drivers/acpi/scan.c |   66 ++++++++++++++++++++++++++++------------------------
 1 file changed, 36 insertions(+), 30 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1626,10 +1626,9 @@ static acpi_status acpi_bus_check_add(ac
 	return AE_OK;
 }
 
-static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
-					void *context, void **not_used)
+static acpi_status acpi_bus_match_device(acpi_handle handle, u32 lvl,
+					 void *not_used, void **ret_not_used)
 {
-	struct acpi_bus_ops *ops = context;
 	acpi_status status = AE_OK;
 	struct acpi_device *device;
 	unsigned long long sta_not_used;
@@ -1645,18 +1644,13 @@ static acpi_status acpi_bus_probe_start(
 	if (acpi_bus_get_device(handle, &device))
 		return AE_CTRL_DEPTH;
 
-	if (ops->acpi_op_add) {
-		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
-			/* This is a known good platform device. */
-			acpi_create_platform_device(device);
-		} else {
-			int ret = device_attach(&device->dev);
-			acpi_hot_add_bind(device);
-			if (ret)
-				status = AE_CTRL_DEPTH;
-		}
-	} else if (ops->acpi_op_start) {
-		if (ACPI_FAILURE(acpi_start_single_object(device)))
+	if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+		/* This is a known good platform device. */
+		acpi_create_platform_device(device);
+	} else {
+		int ret = device_attach(&device->dev);
+		acpi_hot_add_bind(device);
+		if (ret)
 			status = AE_CTRL_DEPTH;
 	}
 	return status;
@@ -1679,7 +1673,7 @@ static int acpi_bus_scan(acpi_handle han
 			    acpi_bus_check_add, NULL, ops, &device);
 	if (device)
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_probe_start, NULL, ops, NULL);
+				    acpi_bus_match_device, NULL, NULL, NULL);
 	else
 		ret = -ENODEV;
 
@@ -1706,31 +1700,43 @@ int
 acpi_bus_add(struct acpi_device **child,
 	     struct acpi_device *parent, acpi_handle handle, int type)
 {
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
+	struct acpi_bus_ops ops = { .acpi_op_add = 1, };
 
 	return acpi_bus_scan(handle, &ops, child);
 }
 EXPORT_SYMBOL(acpi_bus_add);
 
-int acpi_bus_start(struct acpi_device *device)
+static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl,
+					 void *not_used, void **ret_not_used)
 {
-	struct acpi_bus_ops ops;
-	int result;
+	struct acpi_device *device;
+	unsigned long long sta_not_used;
+	int type_not_used;
+	acpi_status status;
 
-	if (!device)
-		return -EINVAL;
+	/*
+	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+	 * namespace walks prematurely.
+	 */
+	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+		return AE_OK;
 
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_start = 1;
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
 
-	result = acpi_bus_scan(device->handle, &ops, NULL);
+	status = acpi_start_single_object(device);
+	return ACPI_SUCCESS(status) ? status : AE_CTRL_DEPTH;
+}
 
-	acpi_update_all_gpes();
+int acpi_bus_start(struct acpi_device *device)
+{
+	if (!device)
+		return -EINVAL;
 
-	return result;
+	acpi_walk_namespace(ACPI_TYPE_ANY, device->handle, ACPI_UINT32_MAX,
+			    acpi_bus_start_device, NULL, NULL, NULL);
+	acpi_update_all_gpes();
+	return 0;
 }
 EXPORT_SYMBOL(acpi_bus_start);
 


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

* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
  2012-12-12 15:50   ` Jiang Liu
  2012-12-12 16:38   ` Jiang Liu
@ 2012-12-13  1:00   ` Bjorn Helgaas
  2012-12-13 11:41     ` Rafael J. Wysocki
  2 siblings, 1 reply; 88+ messages in thread
From: Bjorn Helgaas @ 2012-12-13  1:00 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Currently, as soon as an ACPI device node object (struct acpi_device)
> is created, the driver core attempts to probe ACPI drivers against
> it.  That leads to some unpleasant side effects, like the fact that
> the boot code path for ACPI namespace scanning is different from the
> analogous hot-plug code path (during boot ACPI drivers are not
> present when ACPI device node objects are registered, so they are
> guaranteed not to be probed, which is not the case during hot-plug).
> That, in turn, leads to unnecessary complications in the PCI
> enumeration algorithm.

Can you elaborate a bit on the complications in PCI enumeration?
Hopefully this will lead to some simplification in PCI enumeration,
but these patches don't go that far (yet).

> Reduce the differences between the boot and hot-plug cases by
> splitting the ACPI namespace scanning for devices into two passes,
> such that struct acpi_device objects are registerd in the first
> patch without probing ACPI drivers and the drivers are probed
> against them directly in the second pass.  This way ACPI drivers
> can assume that all of the ACPI device node objects in the given
> scope will be registered when their .add() routines run and the
> hot-plug case becomes the same as the boot case from their
> perspective.

If I understand correctly, you're talking about a hierarchical
topology where a device, e.g., a bridge, can have subordinate devices
below it.

In general terms, if a driver claims X, and the driver's add() method
can assume that every device below X has already been registered, I
guess that means any bridge drivers must be integrated into the core,
so the core can enumerate things below the bridge without the driver's
help.  The PCI core effectively has the P2P bridge driver integrated
into it, so that's the way it is already for PCI.  I can imagine
scenarios, e.g., NTBs, where it's not practical to integrate the
bridge driver, so I'm not 100% comfortable with this assumption.  But
I admit that's a totally hypothetical situation, and there are lots of
other obstacles to non-integrated bridge drivers, like the fact that
we can't do dynamic resource assignment.

s/registerd/registered/ above

> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/scan.c     |   96 +++++++++++++++++++++++++++++++++---------------
>  include/acpi/acpi_bus.h |    1
>  2 files changed, 68 insertions(+), 29 deletions(-)
>
> Index: linux/include/acpi/acpi_bus.h
> ===================================================================
> --- linux.orig/include/acpi/acpi_bus.h
> +++ linux/include/acpi/acpi_bus.h
> @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
>  struct acpi_bus_ops {
>         u32 acpi_op_add:1;
>         u32 acpi_op_start:1;
> +       u32 acpi_op_match:1;
>  };
>
>  struct acpi_device_ops {
> Index: linux/drivers/acpi/scan.c
> ===================================================================
> --- linux.orig/drivers/acpi/scan.c
> +++ linux/drivers/acpi/scan.c
> @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
>         struct acpi_device *acpi_dev = to_acpi_device(dev);
>         struct acpi_driver *acpi_drv = to_acpi_driver(drv);
>
> -       return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> +       return acpi_dev->bus_ops.acpi_op_match
> +               && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
>  }
>
>  static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
> @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
>         return 0;
>  }
>
> +/*
> + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
> + * @device: ACPI device node to bind.
> + */
> +static void acpi_hot_add_bind(struct acpi_device *device)
> +{
> +       if (device->flags.bus_address
> +           && device->parent && device->parent->ops.bind)
> +               device->parent->ops.bind(device);
> +}
> +
>  static int acpi_add_single_object(struct acpi_device **child,
>                                   acpi_handle handle, int type,
>                                   unsigned long long sta,
> @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
>
>         result = acpi_device_register(device);
>
> -       /*
> -        * Bind _ADR-Based Devices when hot add
> -        */
> -       if (device->flags.bus_address) {
> -               if (device->parent && device->parent->ops.bind)
> -                       device->parent->ops.bind(device);
> -       }
> +       if (device->bus_ops.acpi_op_match)
> +               acpi_hot_add_bind(device);
>
>  end:
>         if (!result) {
> @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
>         struct acpi_bus_ops ops = {
>                 .acpi_op_add = 1,
>                 .acpi_op_start = 1,
> +               .acpi_op_match = 1,
>         };
>         struct acpi_device *device = NULL;
>
> @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
>                                       void *context, void **return_value)
>  {
>         struct acpi_bus_ops *ops = context;
> +       struct acpi_device *device = NULL;
>         int type;
>         unsigned long long sta;
> -       struct acpi_device *device;
>         acpi_status status;
>         int result;
>
> @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac
>          * We may already have an acpi_device from a previous enumeration.  If
>          * so, we needn't add it again, but we may still have to start it.
>          */
> -       device = NULL;
>         acpi_bus_get_device(handle, &device);
>         if (ops->acpi_op_add && !device) {
> -               acpi_add_single_object(&device, handle, type, sta, ops);
> -               /* Is the device a known good platform device? */
> -               if (device
> -                   && !acpi_match_device_ids(device, acpi_platform_device_ids))
> -                       acpi_create_platform_device(device);
> -       }
> +               struct acpi_bus_ops add_ops = *ops;
>
> -       if (!device)
> -               return AE_CTRL_DEPTH;
> -
> -       if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> -               status = acpi_start_single_object(device);
> -               if (ACPI_FAILURE(status))
> +               add_ops.acpi_op_match = 0;
> +               acpi_add_single_object(&device, handle, type, sta, &add_ops);
> +               if (!device)
>                         return AE_CTRL_DEPTH;
> +
> +               device->bus_ops.acpi_op_match = 1;
>         }
>
>         if (!*return_value)
>                 *return_value = device;
> +
>         return AE_OK;
>  }
>
> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> +                                       void *context, void **not_used)
> +{
> +       struct acpi_bus_ops *ops = context;
> +       struct acpi_device *device;
> +       acpi_status status = AE_OK;
> +
> +       if (acpi_bus_get_device(handle, &device))
> +               return AE_CTRL_DEPTH;
> +
> +       if (ops->acpi_op_add) {
> +               if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> +                       /* This is a known good platform device. */
> +                       acpi_create_platform_device(device);
> +               } else {
> +                       int ret = device_attach(&device->dev);
> +                       acpi_hot_add_bind(device);
> +                       if (ret)
> +                               status = AE_CTRL_DEPTH;
> +               }
> +       } else if (ops->acpi_op_start) {
> +               if (ACPI_FAILURE(acpi_start_single_object(device)))
> +                       status = AE_CTRL_DEPTH;
> +       }
> +       return status;
> +}
> +
>  static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
>                          struct acpi_device **child)
>  {
> -       acpi_status status;
>         void *device = NULL;
> +       acpi_status status;
> +       int ret = 0;
>
>         status = acpi_bus_check_add(handle, 0, ops, &device);
> -       if (ACPI_SUCCESS(status))
> +       if (ACPI_FAILURE(status)) {
> +               ret = -ENODEV;
> +               goto out;
> +       }
> +
> +       acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> +                           acpi_bus_check_add, NULL, ops, &device);
> +       if (device)
>                 acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> -                                   acpi_bus_check_add, NULL, ops, &device);
> +                                   acpi_bus_probe_start, NULL, ops, NULL);
> +       else
> +               ret = -ENODEV;
>
> + out:
>         if (child)
>                 *child = device;
>
> -       if (device)
> -               return 0;
> -       else
> -               return -ENODEV;
> +       return ret;
>  }
>
>  /*
> @@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void)
>         memset(&ops, 0, sizeof(ops));
>         ops.acpi_op_add = 1;
>         ops.acpi_op_start = 1;
> +       ops.acpi_op_match = 1;
>
>         /*
>          * Enumerate all fixed-feature devices.
>

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

* Re: [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion
  2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
@ 2012-12-13  1:00   ` Bjorn Helgaas
  2012-12-13 12:19     ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Bjorn Helgaas @ 2012-12-13  1:00 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Devices created by acpi_create_platform_device() sometimes may need
> to be added to the device hierarchy as children of PCI bridges.

An example of this hierarchy would help to understand it.

> For
> this purpose, however, the struct pci_dev objects representing those
> bridges need to exist before the platform devices in question are
> added, but this is only possible if the PCI root bridge driver is
> registered before the initial scanning of the ACPI namespace
> (that driver's .add() routine creates the required struct pci_dev
> objects).

The previous patch (1/6) registers all acpi_device objects in the
first pass, then calls driver .add() methods in the second pass.  And
here you're saying the .add() method has to run before platform
devices are added.  So I guess the acpi_device objects are added
first, then the .add() methods called, then the platform devices
added?

I think the call sequence looks like this:

    acpi_bus_scan
      acpi_walk_namespace
        acpi_bus_check_add
          acpi_add_single_object
            device = kzalloc(sizeof(struct acpi_device, ...)    # (1)
acpi_devices created here
      acpi_walk_namespace
        acpi_bus_match_device
          if (acpi_match_device_ids(device, acpi_platform_device_ids))
            acpi_create_platform_device    # (3) platform device added here
          else
            device_attach    # (2) driver .add() called here
            acpi_hot_add_bind

(1) happens first because it's in the first acpi_walk_namespace().
(2) happens before (3) because acpi_walk_namespace() calls
acpi_bus_match_device() in preorder (node visited before its children)

It always seems like a bit of a hack when we have to call out a driver
specifically like this.  Are these special platform devices unique to
PCI?  What would happen with these platform devices that are children
of PCI bridges if we booted a kernel without a PCI host bridge driver?
 You would hope that the PCI host bridge and everything under it would
just be ignored, and I assume that in that case, these platform
devices should be ignored, too.

I know we can't build ACPI without PCI today, but AFAIK that's mostly
to reduce the configuration/testing matrix, not a design restriction.
So I guess I'm trying to figure out whether the ACPI core should be
made smart enough to deal with these PCI-related platform devices (as
you're doing in these patches), or whether there should be something
in the PCI host bridge driver that deals with them.

> For this reason, call acpi_pci_root_init() from acpi_scan_init()
> before scanning the ACPI namespace for the first time instead of
> running it from a separate subsys initcall.  Since the previous patch
> has changed the ACPI namespace scanning algorithm, this change does
> not affect the PCI root bridge driver's functionality during boot.
> It also makes the situation during boot more similar to the situation
> during hot-plug (in which the PCI root bridge driver is always
> present) and so it helps to reduce arbitary differences between
> the hot-plug and boot PCI root bridge code.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/internal.h |    1 +
>  drivers/acpi/pci_root.c |    4 +---
>  drivers/acpi/scan.c     |    1 +
>  3 files changed, 3 insertions(+), 3 deletions(-)
>
> Index: linux/drivers/acpi/internal.h
> ===================================================================
> --- linux.orig/drivers/acpi/internal.h
> +++ linux/drivers/acpi/internal.h
> @@ -67,6 +67,7 @@ struct acpi_ec {
>
>  extern struct acpi_ec *first_ec;
>
> +int acpi_pci_root_init(void);
>  int acpi_ec_init(void);
>  int acpi_ec_ecdt_probe(void);
>  int acpi_boot_ec_enable(void);
> Index: linux/drivers/acpi/pci_root.c
> ===================================================================
> --- linux.orig/drivers/acpi/pci_root.c
> +++ linux/drivers/acpi/pci_root.c
> @@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a
>         return 0;
>  }
>
> -static int __init acpi_pci_root_init(void)
> +int __init acpi_pci_root_init(void)
>  {
>         acpi_hest_init();
>
> @@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi
>
>         return 0;
>  }
> -
> -subsys_initcall(acpi_pci_root_init);
> Index: linux/drivers/acpi/scan.c
> ===================================================================
> --- linux.orig/drivers/acpi/scan.c
> +++ linux/drivers/acpi/scan.c
> @@ -1828,6 +1828,7 @@ int __init acpi_scan_init(void)
>         }
>
>         acpi_power_init();
> +       acpi_pci_root_init();
>
>         /*
>          * Enumerate devices in the ACPI namespace.
>

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

* Re: [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add()
  2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
@ 2012-12-13  1:00   ` Bjorn Helgaas
  2012-12-13 12:20     ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Bjorn Helgaas @ 2012-12-13  1:00 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

On Sun, Dec 9, 2012 at 4:04 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> If acpi_bus_check_add() is called for a handle already having an
> existing struct acpi_device object attached, it is not necessary to
> check the type and status of the device correspondig to it, so
> change the ordering of acpi_bus_check_add() to avoid that.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/scan.c |   18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
>
> Index: linux/drivers/acpi/scan.c
> ===================================================================
> --- linux.orig/drivers/acpi/scan.c
> +++ linux/drivers/acpi/scan.c
> @@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac
>         acpi_status status;
>         int result;
>
> +       acpi_bus_get_device(handle, &device);
> +       if (device)
> +               goto out;
> +
>         result = acpi_bus_type_and_status(handle, &type, &sta);
>         if (result)
>                 return AE_OK;
> @@ -1602,17 +1606,13 @@ static acpi_status acpi_bus_check_add(ac
>          * We may already have an acpi_device from a previous enumeration.  If
>          * so, we needn't add it again, but we may still have to start it.

It looks like this comment might need updating, since we no longer
even get here if we already have an acpi_device.  Presumably you take
care of the "start" it mentions elsewhere now.

>          */
> -       acpi_bus_get_device(handle, &device);
> -       if (!device) {
> -               acpi_add_single_object(&device, handle, type, sta,
> -                                      ACPI_BUS_ADD_BASIC);
> -               if (!device)
> -                       return AE_CTRL_DEPTH;
> +       acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC);
> +       if (!device)
> +               return AE_CTRL_DEPTH;
>
> -               device->add_type = context ?
> -                                       ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
> -       }
> +       device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
>
> + out:
>         if (!*return_value)
>                 *return_value = device;

I think all (both) callers of acpi_bus_check_add() supply a
return_value pointer, so you could just remove the test.

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

* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-13  1:00   ` Bjorn Helgaas
@ 2012-12-13 11:41     ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 11:41 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

On Wednesday, December 12, 2012 06:00:03 PM Bjorn Helgaas wrote:
> On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Currently, as soon as an ACPI device node object (struct acpi_device)
> > is created, the driver core attempts to probe ACPI drivers against
> > it.  That leads to some unpleasant side effects, like the fact that
> > the boot code path for ACPI namespace scanning is different from the
> > analogous hot-plug code path (during boot ACPI drivers are not
> > present when ACPI device node objects are registered, so they are
> > guaranteed not to be probed, which is not the case during hot-plug).
> > That, in turn, leads to unnecessary complications in the PCI
> > enumeration algorithm.
> 
> Can you elaborate a bit on the complications in PCI enumeration?
> Hopefully this will lead to some simplification in PCI enumeration,
> but these patches don't go that far (yet).

For example, in the hotplug case it is not guaranteed that companion
struct acpi_device objects have been created already when struct pci_dev
objects are created during acpi_pci_root_add().  This forces us to use
acpi_get_pci_dev() in acpi_pci_bind(), which we could avoid otherwise.

Moreover, if we knew that the companion struct acpi_device objects existed as
soon as in pci_scan_device(), we could just populate the ACPI handle of the
struct pci_dev in there and that would allow acpi_platform_notify() later on
to skip the bus browsing (due to recent changes just merged in).  I suppose
we could even get rid of acpi_pci_bind()/acpi_pci_unbind() by integrating
that code directly into the initialization/removal code paths.

> > Reduce the differences between the boot and hot-plug cases by
> > splitting the ACPI namespace scanning for devices into two passes,
> > such that struct acpi_device objects are registerd in the first
> > patch without probing ACPI drivers and the drivers are probed
> > against them directly in the second pass.  This way ACPI drivers
> > can assume that all of the ACPI device node objects in the given
> > scope will be registered when their .add() routines run and the
> > hot-plug case becomes the same as the boot case from their
> > perspective.
> 
> If I understand correctly, you're talking about a hierarchical
> topology where a device, e.g., a bridge, can have subordinate devices
> below it.
> 
> In general terms, if a driver claims X, and the driver's add() method
> can assume that every device below X has already been registered, I
> guess that means any bridge drivers must be integrated into the core,
> so the core can enumerate things below the bridge without the driver's
> help.

Well, I don't quite understand.  Do you have an example?

We're registering only struct acpi_device things kind of in advance here.
I would assume that device drivers would operate on device structures of
other types (like struct pci_dev) and those struct acpi_device objects
would only be companions of the "physical" device nodes.

IOW what we do here is to extract some information from ACPI tables and
put it into a number of objects in the device hierarchy (the fact that they
are in the device hierarchy allows us to export some of their properties via
sysfs easily), but that's about it.  How buses/drivers use that information
is up to them.

And by the way, I think that binding drivers to struct acpi_device objects
directly is too much of a shortcut and it leads to more problems than it
solves.  I'd like to get rid of that eventually.

> The PCI core effectively has the P2P bridge driver integrated
> into it, so that's the way it is already for PCI.  I can imagine
> scenarios, e.g., NTBs, where it's not practical to integrate the
> bridge driver, so I'm not 100% comfortable with this assumption.  But
> I admit that's a totally hypothetical situation, and there are lots of
> other obstacles to non-integrated bridge drivers, like the fact that
> we can't do dynamic resource assignment.

Well, precisely. :-)

> s/registerd/registered/ above

Yup, thanks!

Thanks a lot for having a look. :-)

Rafael


> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  drivers/acpi/scan.c     |   96 +++++++++++++++++++++++++++++++++---------------
> >  include/acpi/acpi_bus.h |    1
> >  2 files changed, 68 insertions(+), 29 deletions(-)
> >
> > Index: linux/include/acpi/acpi_bus.h
> > ===================================================================
> > --- linux.orig/include/acpi/acpi_bus.h
> > +++ linux/include/acpi/acpi_bus.h
> > @@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
> >  struct acpi_bus_ops {
> >         u32 acpi_op_add:1;
> >         u32 acpi_op_start:1;
> > +       u32 acpi_op_match:1;
> >  };
> >
> >  struct acpi_device_ops {
> > Index: linux/drivers/acpi/scan.c
> > ===================================================================
> > --- linux.orig/drivers/acpi/scan.c
> > +++ linux/drivers/acpi/scan.c
> > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
> >         struct acpi_device *acpi_dev = to_acpi_device(dev);
> >         struct acpi_driver *acpi_drv = to_acpi_driver(drv);
> >
> > -       return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> > +       return acpi_dev->bus_ops.acpi_op_match
> > +               && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> >  }
> >
> >  static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
> > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
> >         return 0;
> >  }
> >
> > +/*
> > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
> > + * @device: ACPI device node to bind.
> > + */
> > +static void acpi_hot_add_bind(struct acpi_device *device)
> > +{
> > +       if (device->flags.bus_address
> > +           && device->parent && device->parent->ops.bind)
> > +               device->parent->ops.bind(device);
> > +}
> > +
> >  static int acpi_add_single_object(struct acpi_device **child,
> >                                   acpi_handle handle, int type,
> >                                   unsigned long long sta,
> > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
> >
> >         result = acpi_device_register(device);
> >
> > -       /*
> > -        * Bind _ADR-Based Devices when hot add
> > -        */
> > -       if (device->flags.bus_address) {
> > -               if (device->parent && device->parent->ops.bind)
> > -                       device->parent->ops.bind(device);
> > -       }
> > +       if (device->bus_ops.acpi_op_match)
> > +               acpi_hot_add_bind(device);
> >
> >  end:
> >         if (!result) {
> > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
> >         struct acpi_bus_ops ops = {
> >                 .acpi_op_add = 1,
> >                 .acpi_op_start = 1,
> > +               .acpi_op_match = 1,
> >         };
> >         struct acpi_device *device = NULL;
> >
> > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
> >                                       void *context, void **return_value)
> >  {
> >         struct acpi_bus_ops *ops = context;
> > +       struct acpi_device *device = NULL;
> >         int type;
> >         unsigned long long sta;
> > -       struct acpi_device *device;
> >         acpi_status status;
> >         int result;
> >
> > @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac
> >          * We may already have an acpi_device from a previous enumeration.  If
> >          * so, we needn't add it again, but we may still have to start it.
> >          */
> > -       device = NULL;
> >         acpi_bus_get_device(handle, &device);
> >         if (ops->acpi_op_add && !device) {
> > -               acpi_add_single_object(&device, handle, type, sta, ops);
> > -               /* Is the device a known good platform device? */
> > -               if (device
> > -                   && !acpi_match_device_ids(device, acpi_platform_device_ids))
> > -                       acpi_create_platform_device(device);
> > -       }
> > +               struct acpi_bus_ops add_ops = *ops;
> >
> > -       if (!device)
> > -               return AE_CTRL_DEPTH;
> > -
> > -       if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> > -               status = acpi_start_single_object(device);
> > -               if (ACPI_FAILURE(status))
> > +               add_ops.acpi_op_match = 0;
> > +               acpi_add_single_object(&device, handle, type, sta, &add_ops);
> > +               if (!device)
> >                         return AE_CTRL_DEPTH;
> > +
> > +               device->bus_ops.acpi_op_match = 1;
> >         }
> >
> >         if (!*return_value)
> >                 *return_value = device;
> > +
> >         return AE_OK;
> >  }
> >
> > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> > +                                       void *context, void **not_used)
> > +{
> > +       struct acpi_bus_ops *ops = context;
> > +       struct acpi_device *device;
> > +       acpi_status status = AE_OK;
> > +
> > +       if (acpi_bus_get_device(handle, &device))
> > +               return AE_CTRL_DEPTH;
> > +
> > +       if (ops->acpi_op_add) {
> > +               if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> > +                       /* This is a known good platform device. */
> > +                       acpi_create_platform_device(device);
> > +               } else {
> > +                       int ret = device_attach(&device->dev);
> > +                       acpi_hot_add_bind(device);
> > +                       if (ret)
> > +                               status = AE_CTRL_DEPTH;
> > +               }
> > +       } else if (ops->acpi_op_start) {
> > +               if (ACPI_FAILURE(acpi_start_single_object(device)))
> > +                       status = AE_CTRL_DEPTH;
> > +       }
> > +       return status;
> > +}
> > +
> >  static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
> >                          struct acpi_device **child)
> >  {
> > -       acpi_status status;
> >         void *device = NULL;
> > +       acpi_status status;
> > +       int ret = 0;
> >
> >         status = acpi_bus_check_add(handle, 0, ops, &device);
> > -       if (ACPI_SUCCESS(status))
> > +       if (ACPI_FAILURE(status)) {
> > +               ret = -ENODEV;
> > +               goto out;
> > +       }
> > +
> > +       acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> > +                           acpi_bus_check_add, NULL, ops, &device);
> > +       if (device)
> >                 acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> > -                                   acpi_bus_check_add, NULL, ops, &device);
> > +                                   acpi_bus_probe_start, NULL, ops, NULL);
> > +       else
> > +               ret = -ENODEV;
> >
> > + out:
> >         if (child)
> >                 *child = device;
> >
> > -       if (device)
> > -               return 0;
> > -       else
> > -               return -ENODEV;
> > +       return ret;
> >  }
> >
> >  /*
> > @@ -1752,6 +1789,7 @@ static int acpi_bus_scan_fixed(void)
> >         memset(&ops, 0, sizeof(ops));
> >         ops.acpi_op_add = 1;
> >         ops.acpi_op_start = 1;
> > +       ops.acpi_op_match = 1;
> >
> >         /*
> >          * Enumerate all fixed-feature devices.
> >
-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering
  2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
                   ` (5 preceding siblings ...)
  2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
@ 2012-12-13 11:45 ` Yijing Wang
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
  7 siblings, 0 replies; 88+ messages in thread
From: Yijing Wang @ 2012-12-13 11:45 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Yinghai Lu, Toshi Kani, Myron Stowe

Hi rafael,
   I tested the pachset in our IA64 machine, system boot up log seems ok, but when do IOH hot plug, there are two small
problems that missing match and start acpi devices for the top acpi device(eg. pci host bridge), refer https://lkml.org/lkml/2012/12/12/268.

Test Machine: IA64,2 physical nodes;
PCI topology:
-+-[0000:40]-+-00.0-[0000:41]--
 |           +-01.0-[0000:42]--+-00.0  Intel Corporation 82576 Gigabit Network Connection
 |           |                 \-00.1  Intel Corporation 82576 Gigabit Network Connection
 |           +-03.0-[0000:43]----00.0  LSI Logic / Symbios Logic SAS1064ET PCI-Express Fusion-MPT SAS
 |           +-04.0-[0000:44]--
 |           +-05.0-[0000:45]--
 |           +-07.0-[0000:46]--
 |           +-0d.0  Intel Corporation Device 343a
 |           +-0d.1  Intel Corporation Device 343b
 |           +-0d.2  Intel Corporation Device 343c
 |           +-0d.3  Intel Corporation Device 343d
 |           +-0d.4  Intel Corporation 5520/5500/X58 Physical Layer Port 0
 |           +-0d.5  Intel Corporation 5520/5500 Physical Layer Port 1
 |           +-0d.6  Intel Corporation Device 341a
 |           +-0d.7  Intel Corporation Device 341b
 |           +-0e.0  Intel Corporation Device 341c
 |           +-0e.1  Intel Corporation Device 341d
 |           +-0e.2  Intel Corporation Device 341e
 |           +-0e.3  Intel Corporation Device 341f
 |           +-0e.4  Intel Corporation Device 3439
 |           +-0f.0  Intel Corporation Device 3424
 |           +-10.0  Intel Corporation 5520/5500/X58 Physical and Link Layer Registers Port 0
 |           +-10.1  Intel Corporation 5520/5500/X58 Routing and Protocol Layer Registers Port 0
 |           +-11.0  Intel Corporation 5520/5500 Physical and Link Layer Registers Port 1
 |           +-11.1  Intel Corporation 5520/5500 Routing & Protocol Layer Register Port 1
 |           +-13.0  Intel Corporation 5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller
 |           +-14.0  Intel Corporation 5520/5500/X58 I/O Hub System Management Registers
 |           +-14.1  Intel Corporation 5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers
 |           +-14.2  Intel Corporation 5520/5500/X58 I/O Hub Control Status and RAS Registers
 |           +-14.3  Intel Corporation 5520/5500/X58 I/O Hub Throttle Registers
 |           +-15.0  Intel Corporation 5520/5500/X58 Trusted Execution Technology Registers
 |           +-16.0  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
 |           +-16.1  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
 |           +-16.2  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
 |           +-16.3  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
 |           +-16.4  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
 |           +-16.5  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
 |           +-16.6  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
 |           \-16.7  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
 \-[0000:00]-+-00.0  Intel Corporation 5520/5500/X58 I/O Hub to ESI Port
             +-01.0-[0000:01]--+-00.0  Intel Corporation 82576 Gigabit Network Connection
             |                 \-00.1  Intel Corporation 82576 Gigabit Network Connection
             +-03.0-[0000:02]----00.0  LSI Logic / Symbios Logic SAS1064ET PCI-Express Fusion-MPT SAS
             +-04.0-[0000:03]--
             +-05.0-[0000:04]--
             +-07.0-[0000:05]--+-00.0  nVidia Corporation GT218 [GeForce G210]
             |                 \-00.1  nVidia Corporation High Definition Audio Controller
             +-0d.0  Intel Corporation Device 343a
             +-0d.1  Intel Corporation Device 343b
             +-0d.2  Intel Corporation Device 343c
             +-0d.3  Intel Corporation Device 343d
             +-0d.4  Intel Corporation 5520/5500/X58 Physical Layer Port 0
             +-0d.5  Intel Corporation 5520/5500 Physical Layer Port 1
             +-0d.6  Intel Corporation Device 341a
             +-0d.7  Intel Corporation Device 341b
             +-0e.0  Intel Corporation Device 341c
             +-0e.1  Intel Corporation Device 341d
             +-0e.2  Intel Corporation Device 341e
             +-0e.3  Intel Corporation Device 341f
             +-0e.4  Intel Corporation Device 3439
             +-0f.0  Intel Corporation Device 3424
             +-10.0  Intel Corporation 5520/5500/X58 Physical and Link Layer Registers Port 0
             +-10.1  Intel Corporation 5520/5500/X58 Routing and Protocol Layer Registers Port 0
             +-11.0  Intel Corporation 5520/5500 Physical and Link Layer Registers Port 1
             +-11.1  Intel Corporation 5520/5500 Routing & Protocol Layer Register Port 1
             +-13.0  Intel Corporation 5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller
             +-14.0  Intel Corporation 5520/5500/X58 I/O Hub System Management Registers
             +-14.1  Intel Corporation 5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers
             +-14.2  Intel Corporation 5520/5500/X58 I/O Hub Control Status and RAS Registers
             +-14.3  Intel Corporation 5520/5500/X58 I/O Hub Throttle Registers
             +-15.0  Intel Corporation 5520/5500/X58 Trusted Execution Technology Registers
             +-16.0  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
             +-16.1  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
             +-16.2  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
             +-16.3  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
             +-16.4  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
             +-16.5  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
             +-16.6  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
             +-16.7  Intel Corporation 5520/5500/X58 Chipset QuickData Technology Device
             +-1a.0  Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #4
             +-1a.1  Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #5
             +-1a.2  Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #6
             +-1a.7  Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #2
             +-1c.0-[0000:06]--
             +-1c.1-[0000:07]--
             +-1c.2-[0000:08]--
             +-1c.3-[0000:09]--
             +-1c.4-[0000:0a]----00.0  XGI Technology Inc. (eXtreme Graphics Innovation) Z11/Z11M
             +-1c.5-[0000:0b]--
             +-1d.0  Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #1
             +-1d.1  Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #2
             +-1d.2  Intel Corporation 82801JI (ICH10 Family) USB UHCI Controller #3
             +-1d.7  Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #1
             +-1e.0-[0000:0c]--
             +-1f.0  Intel Corporation 82801JIB (ICH10) LPC Interface Controller
             +-1f.2  Intel Corporation 82801JI (ICH10 Family) 4 port SATA IDE Controller #1
             +-1f.3  Intel Corporation 82801JI (ICH10 Family) SMBus Controller
             \-1f.5  Intel Corporation 82801JI (ICH10 Family) 2 port SATA IDE Controller #2

linux kernel version:
https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git + ACPI: Change the ACPI namespace scanning code ordering six patches +
IOH hotplug partial patches from https://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git/for-pci-next-2


IOH hotplug dmesg log at the end.

========================================================================system boot up dmesg log================================================
ACPI: bus type pci registered
bio: create slab <bio-0> at 0
ACPI: Added _OSI(Module Device)
ACPI: Added _OSI(Processor Device)
ACPI: Added _OSI(3.0 _SCP Extensions)
ACPI: Added _OSI(Processor Aggregator Device)
ACPI: EC: Look up EC in DSDT
ACPI: Interpreter enabled
ACPI: (supports S0 S5)
ACPI: Using IOSAPIC for interrupt routing
acpi_bus_scan: start 1
acpi_bus_check_add: acpi_device LNXSYSTM:00 added, add_type 2
acpi_bus_check_add: acpi_device device:00 added, add_type 2
acpi_bus_check_add: acpi_device ACPI0004:00 added, add_type 2
acpi_bus_check_add: acpi_device ACPI0004:01 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:00 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:01 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:02 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:03 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:04 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:05 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:06 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:07 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C80:00 added, add_type 2
acpi_bus_check_add: acpi_device ACPI0004:02 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:08 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:09 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:0a added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:0b added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:0c added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:0d added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:0e added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:0f added, add_type 2
acpi_bus_check_add: acpi_device PNP0C80:01 added, add_type 2
acpi_bus_check_add: acpi_device PNP0A08:00 added, add_type 2
acpi_bus_check_add: acpi_device ACPI0009:00 added, add_type 2
acpi_bus_check_add: acpi_device device:01 added, add_type 2
acpi_bus_check_add: acpi_device device:02 added, add_type 2
acpi_bus_check_add: acpi_device device:03 added, add_type 2
acpi_bus_check_add: acpi_device device:04 added, add_type 2
acpi_bus_check_add: acpi_device device:05 added, add_type 2
acpi_bus_check_add: acpi_device device:06 added, add_type 2
acpi_bus_check_add: acpi_device device:07 added, add_type 2
acpi_bus_check_add: acpi_device device:08 added, add_type 2
acpi_bus_check_add: acpi_device device:09 added, add_type 2
acpi_bus_check_add: acpi_device device:0a added, add_type 2
acpi_bus_check_add: acpi_device device:0b added, add_type 2
acpi_bus_check_add: acpi_device device:0c added, add_type 2
acpi_bus_check_add: acpi_device device:0d added, add_type 2
acpi_bus_check_add: acpi_device device:0e added, add_type 2
acpi_bus_check_add: acpi_device device:0f added, add_type 2
acpi_bus_check_add: acpi_device device:10 added, add_type 2
acpi_bus_check_add: acpi_device device:11 added, add_type 2
acpi_bus_check_add: acpi_device device:12 added, add_type 2
acpi_bus_check_add: acpi_device device:13 added, add_type 2
acpi_bus_check_add: acpi_device device:14 added, add_type 2
acpi_bus_check_add: acpi_device device:15 added, add_type 2
acpi_bus_check_add: acpi_device device:16 added, add_type 2
acpi_bus_check_add: acpi_device device:17 added, add_type 2
acpi_bus_check_add: acpi_device device:18 added, add_type 2
acpi_bus_check_add: acpi_device device:19 added, add_type 2
acpi_bus_check_add: acpi_device device:1a added, add_type 2
acpi_bus_check_add: acpi_device device:1b added, add_type 2
acpi_bus_check_add: acpi_device device:1c added, add_type 2
acpi_bus_check_add: acpi_device device:1d added, add_type 2
acpi_bus_check_add: acpi_device device:1e added, add_type 2
acpi_bus_check_add: acpi_device device:1f added, add_type 2
acpi_bus_check_add: acpi_device device:20 added, add_type 2
acpi_bus_check_add: acpi_device device:21 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0F:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0F:01 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0F:02 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0F:03 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0F:04 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0F:05 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0F:06 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0F:07 added, add_type 2
acpi_bus_check_add: acpi_device PNP0200:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0B00:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0000:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C04:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0100:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0800:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C02:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0700:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0400:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0F03:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0303:00 added, add_type 2
acpi_bus_check_add: acpi_device PNP0501:00 added, add_type 2
acpi_bus_check_add: acpi_device device:22 added, add_type 2
acpi_bus_check_add: acpi_device device:23 added, add_type 2
acpi_bus_check_add: acpi_device device:24 added, add_type 2
acpi_bus_check_add: acpi_device device:25 added, add_type 2
acpi_bus_check_add: acpi_device device:26 added, add_type 2
acpi_bus_check_add: acpi_device device:27 added, add_type 2
acpi_bus_check_add: acpi_device device:28 added, add_type 2
acpi_bus_check_add: acpi_device device:29 added, add_type 2
acpi_bus_check_add: acpi_device device:2a added, add_type 2
acpi_bus_check_add: acpi_device device:2b added, add_type 2
acpi_bus_check_add: acpi_device device:2c added, add_type 2
acpi_bus_check_add: acpi_device device:2d added, add_type 2
acpi_bus_check_add: acpi_device device:2e added, add_type 2
acpi_bus_check_add: acpi_device device:2f added, add_type 2
acpi_bus_check_add: acpi_device device:30 added, add_type 2
acpi_bus_check_add: acpi_device device:31 added, add_type 2
acpi_bus_check_add: acpi_device device:32 added, add_type 2
acpi_bus_check_add: acpi_device device:33 added, add_type 2
acpi_bus_check_add: acpi_device device:34 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C0E:00 added, add_type 2
acpi_bus_check_add: acpi_device ACPI0004:03 added, add_type 2
acpi_bus_check_add: acpi_device ACPI0004:04 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:10 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:11 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:12 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:13 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:14 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:15 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:16 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:17 added, add_type 2
acpi_bus_check_add: acpi_device PNP0C80:02 added, add_type 2
acpi_bus_check_add: acpi_device ACPI0004:05 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:18 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:19 added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:1a added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:1b added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:1c added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:1d added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:1e added, add_type 2
acpi_bus_check_add: acpi_device LNXCPU:1f added, add_type 2
acpi_bus_check_add: acpi_device PNP0C80:03 added, add_type 2
acpi_bus_check_add: acpi_device PNP0A08:01 added, add_type 2
acpi_bus_check_add: acpi_device ACPI0009:01 added, add_type 2
acpi_bus_check_add: acpi_device device:35 added, add_type 2
acpi_bus_check_add: acpi_device device:36 added, add_type 2
acpi_bus_check_add: acpi_device device:37 added, add_type 2
acpi_bus_check_add: acpi_device device:38 added, add_type 2
acpi_bus_check_add: acpi_device device:39 added, add_type 2
acpi_bus_check_add: acpi_device device:3a added, add_type 2
acpi_bus_check_add: acpi_device device:3b added, add_type 2
acpi_bus_check_add: acpi_device device:3c added, add_type 2
acpi_bus_check_add: acpi_device device:3d added, add_type 2
acpi_bus_check_add: acpi_device device:3e added, add_type 2
acpi_bus_check_add: acpi_device device:3f added, add_type 2
acpi_bus_check_add: acpi_device device:40 added, add_type 2
acpi_bus_check_add: acpi_device device:41 added, add_type 2
acpi_bus_check_add: acpi_device device:42 added, add_type 2
acpi_bus_check_add: acpi_device device:43 added, add_type 2
acpi_bus_check_add: acpi_device device:44 added, add_type 2
acpi_bus_check_add: acpi_device device:45 added, add_type 2
acpi_bus_check_add: acpi_device device:46 added, add_type 2
acpi_bus_check_add: acpi_device device:47 added, add_type 2
acpi_bus_check_add: acpi_device device:48 added, add_type 2
acpi_bus_check_add: acpi_device device:49 added, add_type 2
acpi_bus_check_add: acpi_device device:4a added, add_type 2
acpi_bus_check_add: acpi_device device:4b added, add_type 2
acpi_bus_check_add: acpi_device device:4c added, add_type 2
acpi_bus_check_add: acpi_device device:4d added, add_type 2
acpi_bus_check_add: acpi_device device:4e added, add_type 2
acpi_bus_check_add: acpi_device device:4f added, add_type 2
acpi_bus_check_add: acpi_device device:50 added, add_type 2
acpi_bus_match_device: attach driver for device device:00
acpi_bus_match_device: acpi_device device:00, attached driver is NULL
acpi_bus_match_device: attach driver for device ACPI0004:00
acpi_bus_match_device: acpi_device ACPI0004:00, attached driver is NULL
acpi_bus_match_device: attach driver for device ACPI0004:01
acpi_bus_match_device: acpi_device ACPI0004:01, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:00
acpi_bus_match_device: acpi_device LNXCPU:00, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:01
acpi_bus_match_device: acpi_device LNXCPU:01, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:02
acpi_bus_match_device: acpi_device LNXCPU:02, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:03
acpi_bus_match_device: acpi_device LNXCPU:03, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:04
acpi_bus_match_device: acpi_device LNXCPU:04, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:05
acpi_bus_match_device: acpi_device LNXCPU:05, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:06
acpi_bus_match_device: acpi_device LNXCPU:06, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:07
acpi_bus_match_device: acpi_device LNXCPU:07, attached driver is NULL
acpi_bus_match_device: attach driver for device PNP0C80:00
acpi_bus_match_device: acpi_device PNP0C80:00, attached driver is NULL
acpi_bus_match_device: attach driver for device ACPI0004:02
acpi_bus_match_device: acpi_device ACPI0004:02, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:08
acpi_bus_match_device: acpi_device LNXCPU:08, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:09
acpi_bus_match_device: acpi_device LNXCPU:09, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:0a
acpi_bus_match_device: acpi_device LNXCPU:0a, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:0b
acpi_bus_match_device: acpi_device LNXCPU:0b, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:0c
acpi_bus_match_device: acpi_device LNXCPU:0c, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:0d
acpi_bus_match_device: acpi_device LNXCPU:0d, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:0e
acpi_bus_match_device: acpi_device LNXCPU:0e, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:0f
acpi_bus_match_device: acpi_device LNXCPU:0f, attached driver is NULL
acpi_bus_match_device: attach driver for device PNP0C80:01
acpi_bus_match_device: acpi_device PNP0C80:01, attached driver is NULL
acpi_bus_match_device: attach driver for device PNP0A08:00
acpi_bus_match: device PNP0A08:00 find match driver pci_root
ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-3f])
pci_root PNP0A08:00: host bridge window [io  0x0000-0x0cf7]
pci_root PNP0A08:00: host bridge window [io  0x1000-0x8fff]
pci_root PNP0A08:00: host bridge window [mem 0x50000000-0x7fffffff]
PCI host bridge to bus 0000:00
pci_bus 0000:00: root bus resource [bus 00-3f]
pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7]
pci_bus 0000:00: root bus resource [io  0x1000-0x8fff]
pci_bus 0000:00: root bus resource [mem 0x50000000-0x7fffffff]
pci 0000:00:00.0: [8086:3407] type 00 class 0x060000
pci 0000:00:01.0: [8086:3408] type 01 class 0x060400
pci 0000:00:01.0: PME# supported from D0 D3hot D3cold
pci 0000:00:03.0: [8086:340a] type 01 class 0x060400
pci 0000:00:03.0: PME# supported from D0 D3hot D3cold
pci 0000:00:04.0: [8086:340b] type 01 class 0x060400
pci 0000:00:04.0: PME# supported from D0 D3hot D3cold
pci 0000:00:05.0: [8086:340c] type 01 class 0x060400
pci 0000:00:05.0: PME# supported from D0 D3hot D3cold
pci 0000:00:07.0: [8086:340e] type 01 class 0x060400
pci 0000:00:07.0: PME# supported from D0 D3hot D3cold
pci 0000:00:0d.0: [8086:343a] type 00 class 0x060000
pci 0000:00:0d.1: [8086:343b] type 00 class 0x060000
pci 0000:00:0d.2: [8086:343c] type 00 class 0x060000
pci 0000:00:0d.3: [8086:343d] type 00 class 0x060000
pci 0000:00:0d.4: [8086:3418] type 00 class 0x060000
pci 0000:00:0d.5: [8086:3419] type 00 class 0x060000
pci 0000:00:0d.6: [8086:341a] type 00 class 0x060000
pci 0000:00:0d.7: [8086:341b] type 00 class 0x060000
pci 0000:00:0e.0: [8086:341c] type 00 class 0x060000
pci 0000:00:0e.1: [8086:341d] type 00 class 0x060000
pci 0000:00:0e.2: [8086:341e] type 00 class 0x060000
pci 0000:00:0e.3: [8086:341f] type 00 class 0x060000
pci 0000:00:0e.4: [8086:3439] type 00 class 0x060000
pci 0000:00:0f.0: [8086:3424] type 00 class 0x110100
pci 0000:00:10.0: [8086:3425] type 00 class 0x080000
pci 0000:00:10.1: [8086:3426] type 00 class 0x080000
pci 0000:00:11.0: [8086:3427] type 00 class 0x080000
pci 0000:00:11.1: [8086:3428] type 00 class 0x080000
pci 0000:00:13.0: [8086:342d] type 00 class 0x080020
pci 0000:00:13.0: reg 10: [mem 0x68320000-0x68320fff]
pci 0000:00:13.0: PME# supported from D0 D3hot D3cold
pci 0000:00:14.0: [8086:342e] type 00 class 0x080000
pci 0000:00:14.1: [8086:3422] type 00 class 0x080000
pci 0000:00:14.2: [8086:3423] type 00 class 0x080000
pci 0000:00:14.3: [8086:3438] type 00 class 0x080000
pci 0000:00:15.0: [8086:342f] type 00 class 0x080020
pci 0000:00:16.0: [8086:3430] type 00 class 0x088000
pci 0000:00:16.0: reg 10: [mem 0x68300000-0x68303fff 64bit]
pci 0000:00:16.1: [8086:3431] type 00 class 0x088000
pci 0000:00:16.1: reg 10: [mem 0x68304000-0x68307fff 64bit]
pci 0000:00:16.2: [8086:3432] type 00 class 0x088000
pci 0000:00:16.2: reg 10: [mem 0x68308000-0x6830bfff 64bit]
pci 0000:00:16.3: [8086:3433] type 00 class 0x088000
pci 0000:00:16.3: reg 10: [mem 0x6830c000-0x6830ffff 64bit]
pci 0000:00:16.4: [8086:3429] type 00 class 0x088000
pci 0000:00:16.4: reg 10: [mem 0x68310000-0x68313fff 64bit]
pci 0000:00:16.5: [8086:342a] type 00 class 0x088000
pci 0000:00:16.5: reg 10: [mem 0x68314000-0x68317fff 64bit]
pci 0000:00:16.6: [8086:342b] type 00 class 0x088000
pci 0000:00:16.6: reg 10: [mem 0x68318000-0x6831bfff 64bit]
pci 0000:00:16.7: [8086:342c] type 00 class 0x088000
pci 0000:00:16.7: reg 10: [mem 0x6831c000-0x6831ffff 64bit]
pci 0000:00:1a.0: [8086:3a37] type 00 class 0x0c0300
pci 0000:00:1a.0: reg 20: [io  0x50c0-0x50df]
pci 0000:00:1a.1: [8086:3a38] type 00 class 0x0c0300
pci 0000:00:1a.1: reg 20: [io  0x50a0-0x50bf]
pci 0000:00:1a.2: [8086:3a39] type 00 class 0x0c0300
pci 0000:00:1a.2: reg 20: [io  0x5080-0x509f]
pci 0000:00:1a.7: [8086:3a3c] type 00 class 0x0c0320
pci 0000:00:1a.7: reg 10: [mem 0x68321400-0x683217ff]
pci 0000:00:1a.7: PME# supported from D0 D3hot D3cold
pci 0000:00:1c.0: [8086:3a40] type 01 class 0x060400
pci 0000:00:1c.0: PME# supported from D0 D3hot D3cold
pci 0000:00:1c.1: [8086:3a42] type 01 class 0x060400
pci 0000:00:1c.1: PME# supported from D0 D3hot D3cold
pci 0000:00:1c.2: [8086:3a44] type 01 class 0x060400
pci 0000:00:1c.2: PME# supported from D0 D3hot D3cold
pci 0000:00:1c.3: [8086:3a46] type 01 class 0x060400
pci 0000:00:1c.3: PME# supported from D0 D3hot D3cold
pci 0000:00:1c.4: [8086:3a48] type 01 class 0x060400
pci 0000:00:1c.4: PME# supported from D0 D3hot D3cold
pci 0000:00:1c.5: [8086:3a4a] type 01 class 0x060400
pci 0000:00:1c.5: PME# supported from D0 D3hot D3cold
pci 0000:00:1d.0: [8086:3a34] type 00 class 0x0c0300
pci 0000:00:1d.0: reg 20: [io  0x5060-0x507f]
pci 0000:00:1d.1: [8086:3a35] type 00 class 0x0c0300
pci 0000:00:1d.1: reg 20: [io  0x5040-0x505f]
pci 0000:00:1d.2: [8086:3a36] type 00 class 0x0c0300
pci 0000:00:1d.2: reg 20: [io  0x5020-0x503f]
pci 0000:00:1d.7: [8086:3a3a] type 00 class 0x0c0320
pci 0000:00:1d.7: reg 10: [mem 0x68321000-0x683213ff]
pci 0000:00:1d.7: PME# supported from D0 D3hot D3cold
pci 0000:00:1e.0: [8086:244e] type 01 class 0x060401
pci 0000:00:1f.0: [8086:3a18] type 00 class 0x060100
pci 0000:00:1f.2: [8086:3a20] type 00 class 0x01018f
pci 0000:00:1f.2: reg 10: [io  0x5138-0x513f]
pci 0000:00:1f.2: reg 14: [io  0x514c-0x514f]
pci 0000:00:1f.2: reg 18: [io  0x5130-0x5137]
pci 0000:00:1f.2: reg 1c: [io  0x5148-0x514b]
pci 0000:00:1f.2: reg 20: [io  0x5110-0x511f]
pci 0000:00:1f.2: reg 24: [io  0x5100-0x510f]
pci 0000:00:1f.3: [8086:3a30] type 00 class 0x0c0500
pci 0000:00:1f.3: reg 10: [mem 0x68321800-0x683218ff 64bit]
pci 0000:00:1f.3: reg 20: [io  0x5000-0x501f]
pci 0000:00:1f.5: [8086:3a26] type 00 class 0x010185
pci 0000:00:1f.5: reg 10: [io  0x5128-0x512f]
pci 0000:00:1f.5: reg 14: [io  0x5144-0x5147]
pci 0000:00:1f.5: reg 18: [io  0x5120-0x5127]
pci 0000:00:1f.5: reg 1c: [io  0x5140-0x5143]
pci 0000:00:1f.5: reg 20: [io  0x50f0-0x50ff]
pci 0000:00:1f.5: reg 24: [io  0x50e0-0x50ef]
pci 0000:01:00.0: [8086:10c9] type 00 class 0x020000
pci 0000:01:00.0: reg 10: [mem 0x68260000-0x6827ffff]
pci 0000:01:00.0: reg 14: [mem 0x68240000-0x6825ffff]
pci 0000:01:00.0: reg 18: [io  0x4020-0x403f]
pci 0000:01:00.0: reg 1c: [mem 0x68284000-0x68287fff]
pci 0000:01:00.0: reg 30: [mem 0xfffe0000-0xffffffff pref]
pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
pci 0000:01:00.1: [8086:10c9] type 00 class 0x020000
pci 0000:01:00.1: reg 10: [mem 0x68220000-0x6823ffff]
pci 0000:01:00.1: reg 14: [mem 0x68200000-0x6821ffff]
pci 0000:01:00.1: reg 18: [io  0x4000-0x401f]
pci 0000:01:00.1: reg 1c: [mem 0x68280000-0x68283fff]
pci 0000:01:00.1: reg 30: [mem 0xfffe0000-0xffffffff pref]
pci 0000:01:00.1: PME# supported from D0 D3hot D3cold
pci 0000:00:01.0: PCI bridge to [bus 01]
pci 0000:00:01.0:   bridge window [io  0x4000-0x4fff]
pci 0000:00:01.0:   bridge window [mem 0x68200000-0x682fffff]
pci 0000:02:00.0: [1000:0056] type 00 class 0x010000
pci 0000:02:00.0: reg 10: [io  0x3000-0x30ff]
pci 0000:02:00.0: reg 14: [mem 0x68110000-0x68113fff 64bit]
pci 0000:02:00.0: reg 1c: [mem 0x68100000-0x6810ffff 64bit]
pci 0000:02:00.0: reg 30: [mem 0xffe00000-0xffffffff pref]
pci 0000:02:00.0: supports D1 D2
pci 0000:02:00.0: disabling ASPM on pre-1.1 PCIe device.  You can enable it with 'pcie_aspm=force'
pci 0000:00:03.0: PCI bridge to [bus 02]
pci 0000:00:03.0:   bridge window [io  0x3000-0x3fff]
pci 0000:00:03.0:   bridge window [mem 0x68100000-0x681fffff]
pci 0000:00:04.0: PCI bridge to [bus 03]
pci 0000:00:05.0: PCI bridge to [bus 04]
pci 0000:05:00.0: [10de:0a60] type 00 class 0x030000
pci 0000:05:00.0: reg 10: [mem 0x62000000-0x62ffffff]
pci 0000:05:00.0: reg 14: [mem 0x50000000-0x5fffffff 64bit pref]
pci 0000:05:00.0: reg 1c: [mem 0x60000000-0x61ffffff 64bit pref]
pci 0000:05:00.0: reg 24: [io  0x2000-0x207f]
pci 0000:05:00.0: reg 30: [mem 0xfff80000-0xffffffff pref]
pci 0000:05:00.0: Boot video device
pci 0000:05:00.1: [10de:0be3] type 00 class 0x040300
pci 0000:05:00.1: reg 10: [mem 0x63000000-0x63003fff]
pci 0000:00:07.0: PCI bridge to [bus 05]
pci 0000:00:07.0:   bridge window [io  0x2000-0x2fff]
pci 0000:00:07.0:   bridge window [mem 0x50000000-0x630fffff]
pci 0000:00:1c.0: PCI bridge to [bus 06]
pci 0000:00:1c.1: PCI bridge to [bus 07]
pci 0000:00:1c.2: PCI bridge to [bus 08]
pci 0000:00:1c.3: PCI bridge to [bus 09]
pci 0000:0a:00.0: [18ca:0027] type 00 class 0x030000
pci 0000:0a:00.0: reg 10: [mem 0x64000000-0x67ffffff pref]
pci 0000:0a:00.0: reg 14: [mem 0x68000000-0x6803ffff]
pci 0000:0a:00.0: reg 18: [io  0x1000-0x107f]
pci 0000:0a:00.0: supports D1 D2
pci 0000:00:1c.4: PCI bridge to [bus 0a]
pci 0000:00:1c.4:   bridge window [io  0x1000-0x1fff]
pci 0000:00:1c.4:   bridge window [mem 0x64000000-0x680fffff]
pci 0000:00:1c.5: PCI bridge to [bus 0b]
pci 0000:00:1e.0: PCI bridge to [bus 0c] (subtractive decode)
pci 0000:00:1e.0:   bridge window [io  0x0000-0x0cf7] (subtractive decode)
pci 0000:00:1e.0:   bridge window [io  0x1000-0x8fff] (subtractive decode)
pci 0000:00:1e.0:   bridge window [mem 0x50000000-0x7fffffff] (subtractive decode)
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP1._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP3._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP4._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP5._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.MRP7._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX0._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX1._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX2._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX3._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX4._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.PEX5._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD0.PCI0.IP2P._PRT]
 pci0000:00: Requesting ACPI _OSC control (0x1d)
 pci0000:00: ACPI _OSC control (0x1d) granted
acpi_start_single_object: acpi_device PNP0A08:00, driver pci_root to start
acpi_bus_match_device: acpi_device PNP0A08:00, attached driver is pci_root
acpi_bus_match_device: attach driver for device PNP0C0E:00
acpi_bus_match_device: acpi_device PNP0C0E:00, attached driver is NULL
acpi_bus_match_device: attach driver for device ACPI0004:03
acpi_bus_match_device: acpi_device ACPI0004:03, attached driver is NULL
acpi_bus_match_device: attach driver for device ACPI0004:04
acpi_bus_match_device: acpi_device ACPI0004:04, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:10
acpi_bus_match_device: acpi_device LNXCPU:10, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:11
acpi_bus_match_device: acpi_device LNXCPU:11, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:12
acpi_bus_match_device: acpi_device LNXCPU:12, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:13
acpi_bus_match_device: acpi_device LNXCPU:13, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:14
acpi_bus_match_device: acpi_device LNXCPU:14, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:15
acpi_bus_match_device: acpi_device LNXCPU:15, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:16
acpi_bus_match_device: acpi_device LNXCPU:16, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:17
acpi_bus_match_device: acpi_device LNXCPU:17, attached driver is NULL
acpi_bus_match_device: attach driver for device PNP0C80:02
acpi_bus_match_device: acpi_device PNP0C80:02, attached driver is NULL
acpi_bus_match_device: attach driver for device ACPI0004:05
acpi_bus_match_device: acpi_device ACPI0004:05, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:18
acpi_bus_match_device: acpi_device LNXCPU:18, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:19
acpi_bus_match_device: acpi_device LNXCPU:19, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:1a
acpi_bus_match_device: acpi_device LNXCPU:1a, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:1b
acpi_bus_match_device: acpi_device LNXCPU:1b, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:1c
acpi_bus_match_device: acpi_device LNXCPU:1c, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:1d
acpi_bus_match_device: acpi_device LNXCPU:1d, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:1e
acpi_bus_match_device: acpi_device LNXCPU:1e, attached driver is NULL
acpi_bus_match_device: attach driver for device LNXCPU:1f
acpi_bus_match_device: acpi_device LNXCPU:1f, attached driver is NULL
acpi_bus_match_device: attach driver for device PNP0C80:03
acpi_bus_match_device: acpi_device PNP0C80:03, attached driver is NULL
acpi_bus_match_device: attach driver for device PNP0A08:01
acpi_bus_match: device PNP0A08:01 find match driver pci_root
ACPI: PCI Root Bridge [PCI1] (domain 0000 [bus 40-7f])
pci_root PNP0A08:01: host bridge window [io  0x9000-0xfffe]
pci_root PNP0A08:01: host bridge window [mem 0x80000000-0x9fffffff]
PCI host bridge to bus 0000:40
pci_bus 0000:40: root bus resource [bus 40-7f]
pci_bus 0000:40: root bus resource [io  0x9000-0xfffe]
pci_bus 0000:40: root bus resource [mem 0x80000000-0x9fffffff]
pci 0000:40:00.0: [8086:3420] type 01 class 0x060400
pci 0000:40:00.0: PME# supported from D0 D3hot D3cold
pci 0000:40:01.0: [8086:3408] type 01 class 0x060400
pci 0000:40:01.0: PME# supported from D0 D3hot D3cold
pci 0000:40:03.0: [8086:340a] type 01 class 0x060400
pci 0000:40:03.0: PME# supported from D0 D3hot D3cold
pci 0000:40:04.0: [8086:340b] type 01 class 0x060400
pci 0000:40:04.0: PME# supported from D0 D3hot D3cold
pci 0000:40:05.0: [8086:340c] type 01 class 0x060400
pci 0000:40:05.0: PME# supported from D0 D3hot D3cold
pci 0000:40:07.0: [8086:340e] type 01 class 0x060400
pci 0000:40:07.0: PME# supported from D0 D3hot D3cold
pci 0000:40:0d.0: [8086:343a] type 00 class 0x060000
pci 0000:40:0d.1: [8086:343b] type 00 class 0x060000
pci 0000:40:0d.2: [8086:343c] type 00 class 0x060000
pci 0000:40:0d.3: [8086:343d] type 00 class 0x060000
pci 0000:40:0d.4: [8086:3418] type 00 class 0x060000
pci 0000:40:0d.5: [8086:3419] type 00 class 0x060000
pci 0000:40:0d.6: [8086:341a] type 00 class 0x060000
pci 0000:40:0d.7: [8086:341b] type 00 class 0x060000
pci 0000:40:0e.0: [8086:341c] type 00 class 0x060000
pci 0000:40:0e.1: [8086:341d] type 00 class 0x060000
pci 0000:40:0e.2: [8086:341e] type 00 class 0x060000
pci 0000:40:0e.3: [8086:341f] type 00 class 0x060000
pci 0000:40:0e.4: [8086:3439] type 00 class 0x060000
pci 0000:40:0f.0: [8086:3424] type 00 class 0x110100
pci 0000:40:10.0: [8086:3425] type 00 class 0x080000
pci 0000:40:10.1: [8086:3426] type 00 class 0x080000
pci 0000:40:11.0: [8086:3427] type 00 class 0x080000
pci 0000:40:11.1: [8086:3428] type 00 class 0x080000
pci 0000:40:13.0: [8086:342d] type 00 class 0x080020
pci 0000:40:13.0: reg 10: [mem 0x80220000-0x80220fff]
pci 0000:40:13.0: PME# supported from D0 D3hot D3cold
pci 0000:40:14.0: [8086:342e] type 00 class 0x080000
pci 0000:40:14.1: [8086:3422] type 00 class 0x080000
pci 0000:40:14.2: [8086:3423] type 00 class 0x080000
pci 0000:40:14.3: [8086:3438] type 00 class 0x080000
pci 0000:40:15.0: [8086:342f] type 00 class 0x080020
pci 0000:40:16.0: [8086:3430] type 00 class 0x088000
pci 0000:40:16.0: reg 10: [mem 0x80200000-0x80203fff 64bit]
pci 0000:40:16.1: [8086:3431] type 00 class 0x088000
pci 0000:40:16.1: reg 10: [mem 0x80204000-0x80207fff 64bit]
pci 0000:40:16.2: [8086:3432] type 00 class 0x088000
pci 0000:40:16.2: reg 10: [mem 0x80208000-0x8020bfff 64bit]
pci 0000:40:16.3: [8086:3433] type 00 class 0x088000
pci 0000:40:16.3: reg 10: [mem 0x8020c000-0x8020ffff 64bit]
pci 0000:40:16.4: [8086:3429] type 00 class 0x088000
pci 0000:40:16.4: reg 10: [mem 0x80210000-0x80213fff 64bit]
pci 0000:40:16.5: [8086:342a] type 00 class 0x088000
pci 0000:40:16.5: reg 10: [mem 0x80214000-0x80217fff 64bit]
pci 0000:40:16.6: [8086:342b] type 00 class 0x088000
pci 0000:40:16.6: reg 10: [mem 0x80218000-0x8021bfff 64bit]
pci 0000:40:16.7: [8086:342c] type 00 class 0x088000
pci 0000:40:16.7: reg 10: [mem 0x8021c000-0x8021ffff 64bit]
pci 0000:40:00.0: PCI bridge to [bus 41]
pci 0000:42:00.0: [8086:10c9] type 00 class 0x020000
pci 0000:42:00.0: reg 10: [mem 0x80160000-0x8017ffff]
pci 0000:42:00.0: reg 14: [mem 0x80140000-0x8015ffff]
pci 0000:42:00.0: reg 18: [io  0xe020-0xe03f]
pci 0000:42:00.0: reg 1c: [mem 0x80184000-0x80187fff]
pci 0000:42:00.0: reg 30: [mem 0xfffe0000-0xffffffff pref]
pci 0000:42:00.0: PME# supported from D0 D3hot D3cold
pci 0000:42:00.1: [8086:10c9] type 00 class 0x020000
pci 0000:42:00.1: reg 10: [mem 0x80120000-0x8013ffff]
pci 0000:42:00.1: reg 14: [mem 0x80100000-0x8011ffff]
pci 0000:42:00.1: reg 18: [io  0xe000-0xe01f]
pci 0000:42:00.1: reg 1c: [mem 0x80180000-0x80183fff]
pci 0000:42:00.1: reg 30: [mem 0xfffe0000-0xffffffff pref]
pci 0000:42:00.1: PME# supported from D0 D3hot D3cold
pci 0000:40:01.0: PCI bridge to [bus 42]
pci 0000:40:01.0:   bridge window [io  0xe000-0xefff]
pci 0000:40:01.0:   bridge window [mem 0x80100000-0x801fffff]
pci 0000:43:00.0: [1000:0056] type 00 class 0x010000
pci 0000:43:00.0: reg 10: [io  0xc000-0xc0ff]
pci 0000:43:00.0: reg 14: [mem 0x80010000-0x80013fff 64bit]
pci 0000:43:00.0: reg 1c: [mem 0x80000000-0x8000ffff 64bit]
pci 0000:43:00.0: reg 30: [mem 0xffe00000-0xffffffff pref]
pci 0000:43:00.0: supports D1 D2
pci 0000:43:00.0: disabling ASPM on pre-1.1 PCIe device.  You can enable it with 'pcie_aspm=force'
pci 0000:40:03.0: PCI bridge to [bus 43]
pci 0000:40:03.0:   bridge window [io  0xc000-0xdfff]
pci 0000:40:03.0:   bridge window [mem 0x80000000-0x800fffff]
pci 0000:40:04.0: PCI bridge to [bus 44]
pci 0000:40:04.0:   bridge window [io  0xb000-0xbfff]
pci 0000:40:05.0: PCI bridge to [bus 45]
pci 0000:40:05.0:   bridge window [io  0xa000-0xafff]
pci 0000:40:07.0: PCI bridge to [bus 46]
pci 0000:40:07.0:   bridge window [io  0x9000-0x9fff]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP1._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP3._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP4._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP5._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.NOD1.PCI1.MRP7._PRT]
 pci0000:40: Requesting ACPI _OSC control (0x1d)
 pci0000:40: ACPI _OSC control (0x1d) granted
acpi_start_single_object: acpi_device PNP0A08:01, driver pci_root to start
acpi_bus_match_device: acpi_device PNP0A08:01, attached driver is pci_root
acpi_bus_match_device: attach driver for device device:50
acpi_bus_match_device: acpi_device device:50, attached driver is NULL
ACPI: No dock devices found.
acpi_bus_match: device PNP0C0F:00 find match driver pci_link
ACPI: PCI Interrupt Link [LNKA] (IRQs 3 4 5 *6 7 9 10 11 12 14 15)
acpi_bus_match: device PNP0C0F:01 find match driver pci_link
ACPI: PCI Interrupt Link [LNKB] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled.
acpi_bus_match: device PNP0C0F:02 find match driver pci_link
ACPI: PCI Interrupt Link [LNKC] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled.
acpi_bus_match: device PNP0C0F:03 find match driver pci_link
ACPI: PCI Interrupt Link [LNKD] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled.
acpi_bus_match: device PNP0C0F:04 find match driver pci_link
ACPI: PCI Interrupt Link [LNKE] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled.
acpi_bus_match: device PNP0C0F:05 find match driver pci_link
ACPI: PCI Interrupt Link [LNKF] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled.
acpi_bus_match: device PNP0C0F:06 find match driver pci_link
ACPI: PCI Interrupt Link [LNKG] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled.
acpi_bus_match: device PNP0C0F:07 find match driver pci_link
ACPI: PCI Interrupt Link [LNKH] (IRQs 3 4 5 6 7 9 10 11 12 14 15) *0, disabled.
acpi root: \_SB_.NOD0.PCI0 notify handler is installed
acpi root: \_SB_.NOD1.PCI1 notify handler is installed
acpi root: \_SB_.NOD2.PCI2 notify handler is installed
acpi root: \_SB_.NOD3.PCI3 notify handler is installed
Found 4 acpi root devices

================================================================================IOH hot-add dmesg log===================================
ACPI: ACPI device name is <\_SB_.NOD1.PCI1>, event code is <1>
ACPI: Notify event is queued
_handle_hotplug_event_root: Device check notify on \_SB_.NOD1.PCI1
handle_root_bridge_insertion: hot add acpi_device for acpi_handle 31655c8
acpi_bus_scan: start 0
acpi_bus_check_add: acpi_device PNP0A08:02 added, add_type 1
acpi_bus_check_add: acpi_device ACPI0009:02 added, add_type 1
acpi_bus_check_add: acpi_device device:51 added, add_type 1
acpi_bus_check_add: acpi_device device:52 added, add_type 1
acpi_bus_check_add: acpi_device device:53 added, add_type 1
acpi_bus_check_add: acpi_device device:54 added, add_type 1
acpi_bus_check_add: acpi_device device:55 added, add_type 1
acpi_bus_check_add: acpi_device device:56 added, add_type 1
acpi_bus_check_add: acpi_device device:57 added, add_type 1
acpi_bus_check_add: acpi_device device:58 added, add_type 1
acpi_bus_check_add: acpi_device device:59 added, add_type 1
acpi_bus_check_add: acpi_device device:5a added, add_type 1
acpi_bus_check_add: acpi_device device:5b added, add_type 1
acpi_bus_check_add: acpi_device device:5c added, add_type 1
acpi_bus_check_add: acpi_device device:5d added, add_type 1
acpi_bus_check_add: acpi_device device:5e added, add_type 1
acpi_bus_check_add: acpi_device device:5f added, add_type 1
acpi_bus_check_add: acpi_device device:60 added, add_type 1
acpi_bus_check_add: acpi_device device:61 added, add_type 1
acpi_bus_check_add: acpi_device device:62 added, add_type 1
acpi_bus_check_add: acpi_device device:63 added, add_type 1
acpi_bus_check_add: acpi_device device:64 added, add_type 1
acpi_bus_check_add: acpi_device device:65 added, add_type 1
acpi_bus_check_add: acpi_device device:66 added, add_type 1
acpi_bus_check_add: acpi_device device:67 added, add_type 1
acpi_bus_check_add: acpi_device device:68 added, add_type 1
acpi_bus_check_add: acpi_device device:69 added, add_type 1
acpi_bus_check_add: acpi_device device:6a added, add_type 1
acpi_bus_check_add: acpi_device device:6b added, add_type 1
acpi_bus_match_device: attach driver for device ACPI0009:02 <====================== bus match for PNP0A08:02 missing
acpi_bus_match_device: acpi_device ACPI0009:02, attached driver is NULL
acpi_bus_match_device: attach driver for device device:51
acpi_bus_match_device: acpi_device device:51, attached driver is NULL
acpi_bus_match_device: attach driver for device device:52
acpi_bus_match_device: acpi_device device:52, attached driver is NULL
acpi_bus_match_device: attach driver for device device:53
acpi_bus_match_device: acpi_device device:53, attached driver is NULL
acpi_bus_match_device: attach driver for device device:54
acpi_bus_match_device: acpi_device device:54, attached driver is NULL
acpi_bus_match_device: attach driver for device device:55
acpi_bus_match_device: acpi_device device:55, attached driver is NULL
acpi_bus_match_device: attach driver for device device:56
acpi_bus_match_device: acpi_device device:56, attached driver is NULL
acpi_bus_match_device: attach driver for device device:57
acpi_bus_match_device: acpi_device device:57, attached driver is NULL
acpi_bus_match_device: attach driver for device device:58
acpi_bus_match_device: acpi_device device:58, attached driver is NULL
acpi_bus_match_device: attach driver for device device:59
acpi_bus_match_device: acpi_device device:59, attached driver is NULL
acpi_bus_match_device: attach driver for device device:5a
acpi_bus_match_device: acpi_device device:5a, attached driver is NULL
acpi_bus_match_device: attach driver for device device:5b
acpi_bus_match_device: acpi_device device:5b, attached driver is NULL
acpi_bus_match_device: attach driver for device device:5c
acpi_bus_match_device: acpi_device device:5c, attached driver is NULL
acpi_bus_match_device: attach driver for device device:5d
acpi_bus_match_device: acpi_device device:5d, attached driver is NULL
acpi_bus_match_device: attach driver for device device:5e
acpi_bus_match_device: acpi_device device:5e, attached driver is NULL
acpi_bus_match_device: attach driver for device device:5f
acpi_bus_match_device: acpi_device device:5f, attached driver is NULL
acpi_bus_match_device: attach driver for device device:60
acpi_bus_match_device: acpi_device device:60, attached driver is NULL
acpi_bus_match_device: attach driver for device device:61
acpi_bus_match_device: acpi_device device:61, attached driver is NULL
acpi_bus_match_device: attach driver for device device:62
acpi_bus_match_device: acpi_device device:62, attached driver is NULL
acpi_bus_match_device: attach driver for device device:63
acpi_bus_match_device: acpi_device device:63, attached driver is NULL
acpi_bus_match_device: attach driver for device device:64
acpi_bus_match_device: acpi_device device:64, attached driver is NULL
acpi_bus_match_device: attach driver for device device:65
acpi_bus_match_device: acpi_device device:65, attached driver is NULL
acpi_bus_match_device: attach driver for device device:66
acpi_bus_match_device: acpi_device device:66, attached driver is NULL
acpi_bus_match_device: attach driver for device device:67
acpi_bus_match_device: acpi_device device:67, attached driver is NULL
acpi_bus_match_device: attach driver for device device:68
acpi_bus_match_device: acpi_device device:68, attached driver is NULL
acpi_bus_match_device: attach driver for device device:69
acpi_bus_match_device: acpi_device device:69, attached driver is NULL
acpi_bus_match_device: attach driver for device device:6a
acpi_bus_match_device: acpi_device device:6a, attached driver is NULL
acpi_bus_match_device: attach driver for device device:6b
acpi_bus_match_device: acpi_device device:6b, attached driver is NULL
acpi_bus_start: acpi_device PNP0A08:02
acpi_bus_start_device: acpi_device ACPI0009:02      <====================== bus start for PNP0A08:02 missing,so pci_root driver won't be called
acpi_bus_start_device: acpi_device device:51
acpi_bus_start_device: acpi_device device:52
acpi_bus_start_device: acpi_device device:53
acpi_bus_start_device: acpi_device device:54
acpi_bus_start_device: acpi_device device:55
acpi_bus_start_device: acpi_device device:56
acpi_bus_start_device: acpi_device device:57
acpi_bus_start_device: acpi_device device:58
acpi_bus_start_device: acpi_device device:59
acpi_bus_start_device: acpi_device device:5a
acpi_bus_start_device: acpi_device device:5b
acpi_bus_start_device: acpi_device device:5c
acpi_bus_start_device: acpi_device device:5d
acpi_bus_start_device: acpi_device device:5e
acpi_bus_start_device: acpi_device device:5f
acpi_bus_start_device: acpi_device device:60
acpi_bus_start_device: acpi_device device:61
acpi_bus_start_device: acpi_device device:62
acpi_bus_start_device: acpi_device device:63
acpi_bus_start_device: acpi_device device:64
acpi_bus_start_device: acpi_device device:65
acpi_bus_start_device: acpi_device device:66
acpi_bus_start_device: acpi_device device:67
acpi_bus_start_device: acpi_device device:68
acpi_bus_start_device: acpi_device device:69
acpi_bus_start_device: acpi_device device:6a
acpi_bus_start_device: acpi_device device:6b


-- 
Thanks!
Yijing


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

* Re: [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion
  2012-12-13  1:00   ` Bjorn Helgaas
@ 2012-12-13 12:19     ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 12:19 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

On Wednesday, December 12, 2012 06:00:19 PM Bjorn Helgaas wrote:
> On Sun, Dec 9, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Devices created by acpi_create_platform_device() sometimes may need
> > to be added to the device hierarchy as children of PCI bridges.
> 
> An example of this hierarchy would help to understand it.

Well, that's only hypothetical, but it goes like this.

There's a PCIe root complex with root ports.  Some devices are connected to
those root ports, but for whatever (the heck) the reason they are not visible
to the kernel as PCI devices (ie. their config spaces are unavailable by any
usual means).  They are, however, listed in the ACPI namespace and their
MMIO ranges can be extracted through _CRS.  Still, the root ports themselves
are visible to the kernel as normal PCIe devices (I know, that's silly).

So, in order to maintain (for example) the correct runtime suspend ordering,
we need to represent those "hidden" devices as device nodes being the children
of the PCIe root ports' device nodes.

> 
> > For this purpose, however, the struct pci_dev objects representing those
> > bridges need to exist before the platform devices in question are
> > added, but this is only possible if the PCI root bridge driver is
> > registered before the initial scanning of the ACPI namespace
> > (that driver's .add() routine creates the required struct pci_dev
> > objects).
> 
> The previous patch (1/6) registers all acpi_device objects in the
> first pass, then calls driver .add() methods in the second pass.  And
> here you're saying the .add() method has to run before platform
> devices are added.  So I guess the acpi_device objects are added
> first, then the .add() methods called, then the platform devices
> added?

No, the platform devices are added in the same pass in which the .add()
methods are called, because we know that we won't call an .add() method
for any struct acpi_device that we'll be creating a platform device for.
These things are mutually exclusive.

Of course, we could add a separate pass for adding the platform devices,
but then we'd need to teach ACPI PNP that it shouldn't create PNP device
objects for the ACPI devices we'll be creating platform devices for.

> I think the call sequence looks like this:
> 
>     acpi_bus_scan
>       acpi_walk_namespace
>         acpi_bus_check_add
>           acpi_add_single_object
>             device = kzalloc(sizeof(struct acpi_device, ...)    # (1)
> acpi_devices created here
>       acpi_walk_namespace
>         acpi_bus_match_device
>           if (acpi_match_device_ids(device, acpi_platform_device_ids))
>             acpi_create_platform_device    # (3) platform device added here
>           else
>             device_attach    # (2) driver .add() called here
>             acpi_hot_add_bind
> 
> (1) happens first because it's in the first acpi_walk_namespace().

Yes.

> (2) happens before (3) because acpi_walk_namespace() calls
> acpi_bus_match_device() in preorder (node visited before its children)

Yes.

> It always seems like a bit of a hack when we have to call out a driver
> specifically like this.  Are these special platform devices unique to
> PCI?

I believe so.

> What would happen with these platform devices that are children
> of PCI bridges if we booted a kernel without a PCI host bridge driver?
>  You would hope that the PCI host bridge and everything under it would
> just be ignored, and I assume that in that case, these platform
> devices should be ignored, too.

That's a good question and I believe the answer depends on what's there
in the ACPI namespace.  Namely, if the ACPI namespace lists the PCI parents
of those platform devices, we should at least enable them to decode resources
for the children (which we should be doing in general for any parents
listed in the ACPI namespace).

> I know we can't build ACPI without PCI today, but AFAIK that's mostly
> to reduce the configuration/testing matrix, not a design restriction.
> So I guess I'm trying to figure out whether the ACPI core should be
> made smart enough to deal with these PCI-related platform devices (as
> you're doing in these patches), or whether there should be something
> in the PCI host bridge driver that deals with them.

Well, I'm actually not making the ACPI core any smarter. :-)

What I'm really doing is just to say "let's register the PCI root bridge
driver before walking the namespace, because we may want it to kick in
before anything else".  And if it doesn't kick in at all, so be it.

That also makes the "boot" case be more similar to the "hotplug" case in which
the root bridge driver is always present, so I think this is worth doing
anyway.

And moreover, I think we should register _all_ ACPI drivers (except for modular
ones, but those are not really suitable for hotplug anyway) before walking the
namespace to make the "boot" and "hotplug" cases look the same.  This patch
just does this for the root bridge on the "one item at a time" basis, but I
don't see a reason why not to do that for other ACPI drivers.

Thanks,
Rafael


> > For this reason, call acpi_pci_root_init() from acpi_scan_init()
> > before scanning the ACPI namespace for the first time instead of
> > running it from a separate subsys initcall.  Since the previous patch
> > has changed the ACPI namespace scanning algorithm, this change does
> > not affect the PCI root bridge driver's functionality during boot.
> > It also makes the situation during boot more similar to the situation
> > during hot-plug (in which the PCI root bridge driver is always
> > present) and so it helps to reduce arbitary differences between
> > the hot-plug and boot PCI root bridge code.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  drivers/acpi/internal.h |    1 +
> >  drivers/acpi/pci_root.c |    4 +---
> >  drivers/acpi/scan.c     |    1 +
> >  3 files changed, 3 insertions(+), 3 deletions(-)
> >
> > Index: linux/drivers/acpi/internal.h
> > ===================================================================
> > --- linux.orig/drivers/acpi/internal.h
> > +++ linux/drivers/acpi/internal.h
> > @@ -67,6 +67,7 @@ struct acpi_ec {
> >
> >  extern struct acpi_ec *first_ec;
> >
> > +int acpi_pci_root_init(void);
> >  int acpi_ec_init(void);
> >  int acpi_ec_ecdt_probe(void);
> >  int acpi_boot_ec_enable(void);
> > Index: linux/drivers/acpi/pci_root.c
> > ===================================================================
> > --- linux.orig/drivers/acpi/pci_root.c
> > +++ linux/drivers/acpi/pci_root.c
> > @@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a
> >         return 0;
> >  }
> >
> > -static int __init acpi_pci_root_init(void)
> > +int __init acpi_pci_root_init(void)
> >  {
> >         acpi_hest_init();
> >
> > @@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi
> >
> >         return 0;
> >  }
> > -
> > -subsys_initcall(acpi_pci_root_init);
> > Index: linux/drivers/acpi/scan.c
> > ===================================================================
> > --- linux.orig/drivers/acpi/scan.c
> > +++ linux/drivers/acpi/scan.c
> > @@ -1828,6 +1828,7 @@ int __init acpi_scan_init(void)
> >         }
> >
> >         acpi_power_init();
> > +       acpi_pci_root_init();
> >
> >         /*
> >          * Enumerate devices in the ACPI namespace.
> >
-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add()
  2012-12-13  1:00   ` Bjorn Helgaas
@ 2012-12-13 12:20     ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 12:20 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: LKML, ACPI Devel Maling List, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe

On Wednesday, December 12, 2012 06:00:28 PM Bjorn Helgaas wrote:
> On Sun, Dec 9, 2012 at 4:04 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > If acpi_bus_check_add() is called for a handle already having an
> > existing struct acpi_device object attached, it is not necessary to
> > check the type and status of the device correspondig to it, so
> > change the ordering of acpi_bus_check_add() to avoid that.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  drivers/acpi/scan.c |   18 +++++++++---------
> >  1 file changed, 9 insertions(+), 9 deletions(-)
> >
> > Index: linux/drivers/acpi/scan.c
> > ===================================================================
> > --- linux.orig/drivers/acpi/scan.c
> > +++ linux/drivers/acpi/scan.c
> > @@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac
> >         acpi_status status;
> >         int result;
> >
> > +       acpi_bus_get_device(handle, &device);
> > +       if (device)
> > +               goto out;
> > +
> >         result = acpi_bus_type_and_status(handle, &type, &sta);
> >         if (result)
> >                 return AE_OK;
> > @@ -1602,17 +1606,13 @@ static acpi_status acpi_bus_check_add(ac
> >          * We may already have an acpi_device from a previous enumeration.  If
> >          * so, we needn't add it again, but we may still have to start it.
> 
> It looks like this comment might need updating, since we no longer
> even get here if we already have an acpi_device.  Presumably you take
> care of the "start" it mentions elsewhere now.

I think you're right, will update.

Thanks,
Rafael


> >          */
> > -       acpi_bus_get_device(handle, &device);
> > -       if (!device) {
> > -               acpi_add_single_object(&device, handle, type, sta,
> > -                                      ACPI_BUS_ADD_BASIC);
> > -               if (!device)
> > -                       return AE_CTRL_DEPTH;
> > +       acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC);
> > +       if (!device)
> > +               return AE_CTRL_DEPTH;
> >
> > -               device->add_type = context ?
> > -                                       ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
> > -       }
> > +       device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
> >
> > + out:
> >         if (!*return_value)
> >                 *return_value = device;
> 
> I think all (both) callers of acpi_bus_check_add() supply a
> return_value pointer, so you could just remove the test.
-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-12 22:32     ` Rafael J. Wysocki
  2012-12-12 23:43       ` [update][PATCH " Rafael J. Wysocki
@ 2012-12-13 13:05       ` Jiang Liu
  2012-12-13 19:40         ` Rafael J. Wysocki
  1 sibling, 1 reply; 88+ messages in thread
From: Jiang Liu @ 2012-12-13 13:05 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Yinghai Lu, Toshi Kani, Myron Stowe

On 12/13/2012 06:32 AM, Rafael J. Wysocki wrote:
> On Thursday, December 13, 2012 12:38:01 AM Jiang Liu wrote:
>> On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote:
>>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>>
>>> Currently, as soon as an ACPI device node object (struct acpi_device)
>> snip
>>   
>>> @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac
>>>  	 * We may already have an acpi_device from a previous enumeration.  If
>>>  	 * so, we needn't add it again, but we may still have to start it.
>>>  	 */
>>> -	device = NULL;
>>>  	acpi_bus_get_device(handle, &device);
>>>  	if (ops->acpi_op_add && !device) {
>>> -		acpi_add_single_object(&device, handle, type, sta, ops);
>>> -		/* Is the device a known good platform device? */
>>> -		if (device
>>> -		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
>>> -			acpi_create_platform_device(device);
>>> -	}
>>> +		struct acpi_bus_ops add_ops = *ops;
>>>  
>>> -	if (!device)
>>> -		return AE_CTRL_DEPTH;
>>> -
>>> -	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
>>> -		status = acpi_start_single_object(device);
>>> -		if (ACPI_FAILURE(status))
>>> +		add_ops.acpi_op_match = 0;
>>> +		acpi_add_single_object(&device, handle, type, sta, &add_ops);
>>> +		if (!device)
>>>  			return AE_CTRL_DEPTH;
>>> +
>>> +		device->bus_ops.acpi_op_match = 1;
>>>  	}
>>>  
>>>  	if (!*return_value)
>>>  		*return_value = device;
>>> +
>>>  	return AE_OK;
>>>  }
>>>  
>>> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
>>> +					void *context, void **not_used)
>>> +{
>>> +	struct acpi_bus_ops *ops = context;
>>> +	struct acpi_device *device;
>>> +	acpi_status status = AE_OK;
>>> +
>>> +	if (acpi_bus_get_device(handle, &device))
>>> +		return AE_CTRL_DEPTH;
>>> +
>>> +	if (ops->acpi_op_add) {
>>> +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
>>> +			/* This is a known good platform device. */
>>> +			acpi_create_platform_device(device);
>>> +		} else {
>>> +			int ret = device_attach(&device->dev);
>>> +			acpi_hot_add_bind(device);
>>> +			if (ret)
>>> +				status = AE_CTRL_DEPTH;
>>> +		}
>>> +	} else if (ops->acpi_op_start) {
>>> +		if (ACPI_FAILURE(acpi_start_single_object(device)))
>>> +			status = AE_CTRL_DEPTH;
>>> +	}
>>> +	return status;
>>> +}
>>> +
>>>  static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
>>>  			 struct acpi_device **child)
>>>  {
>>> -	acpi_status status;
>>>  	void *device = NULL;
>>> +	acpi_status status;
>>> +	int ret = 0;
>>>  
>>>  	status = acpi_bus_check_add(handle, 0, ops, &device);
>>> -	if (ACPI_SUCCESS(status))
>>> +	if (ACPI_FAILURE(status)) {
>>> +		ret = -ENODEV;
>>> +		goto out;
>>> +	}
>>> +
>>> +	acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
>>> +			    acpi_bus_check_add, NULL, ops, &device);
>>> +	if (device)
>>>  		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
>>> -				    acpi_bus_check_add, NULL, ops, &device);
>>> +				    acpi_bus_probe_start, NULL, ops, NULL);
>> Hi Rafael,
>> 	Should we call acpi_bus_probe_start for the top device corresponding to 
>> "handle" too here?
> 
> Do you mean separately?  I don't think so.  It will be covered by the namespace
> walking, won't it?
Hi Rafael,
	According to test results from Yijing, we do need to call acpi_bus_probe_start
for the top device corresponding to "handle".
	Comments for acpi_walk_namespace says:
/*******************************************************************************
 *
 * FUNCTION:    acpi_walk_namespace
 *
 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
 *              starting (and ending) at the object specified by start_handle.
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *              The callback function is called whenever an object that matches
 *              the type parameter is found. If the callback function returns
 *              a non-zero value, the search is terminated immediately and this
 *              value is returned to the caller.
 *
 *              The point of this procedure is to provide a generic namespace
 *              a non-zero value, the search is terminated immediately and this
 *              value is returned to the caller.
 *
 *              The point of this procedure is to provide a generic namespace
 *              walk routine that can be called from multiple places to
 *              provide multiple services; the callback function(s) can be
 *              tailored to each task, whether it is a print function,
 *              a compare function, etc.
 *
 ******************************************************************************/

But acpi_ns_walk_namespace() doesn't really call the pre_order_visit and post_order_visit
for the start_handle. That means acpi_walk_namespace won't call the callback for the top
handle.
acpi_ns_walk_namespace(acpi_object_type type,
                       acpi_handle start_node,
                       u32 max_depth,
                       u32 flags,
                       acpi_walk_callback pre_order_visit,
                       acpi_walk_callback post_order_visit,
                       void *context, void **return_value)
{
.........................................
        parent_node = start_node;
        child_node = acpi_ns_get_next_node(parent_node, NULL);
        child_type = ACPI_TYPE_ANY;
        level = 1;

        /*
         * Traverse the tree of nodes until we bubble back up to where we
         * started. When Level is zero, the loop is done because we have
         * bubbled up to (and passed) the original parent handle (start_entry)
         */
        while (level > 0 && child_node) {
 ...........................................
}

> 
> Rafael
> 
> 


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

* Re: [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-13 13:05       ` [PATCH " Jiang Liu
@ 2012-12-13 19:40         ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 19:40 UTC (permalink / raw)
  To: Jiang Liu
  Cc: Bjorn Helgaas, LKML, ACPI Devel Maling List, linux-pci,
	Yinghai Lu, Toshi Kani, Myron Stowe

On Thursday, December 13, 2012 09:05:35 PM Jiang Liu wrote:
> On 12/13/2012 06:32 AM, Rafael J. Wysocki wrote:
> > On Thursday, December 13, 2012 12:38:01 AM Jiang Liu wrote:
> >> On 12/10/2012 07:00 AM, Rafael J. Wysocki wrote:
> >>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >>>
> >>> Currently, as soon as an ACPI device node object (struct acpi_device)
> >> snip
> >>   
> >>> @@ -1600,48 +1608,77 @@ static acpi_status acpi_bus_check_add(ac
> >>>  	 * We may already have an acpi_device from a previous enumeration.  If
> >>>  	 * so, we needn't add it again, but we may still have to start it.
> >>>  	 */
> >>> -	device = NULL;
> >>>  	acpi_bus_get_device(handle, &device);
> >>>  	if (ops->acpi_op_add && !device) {
> >>> -		acpi_add_single_object(&device, handle, type, sta, ops);
> >>> -		/* Is the device a known good platform device? */
> >>> -		if (device
> >>> -		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
> >>> -			acpi_create_platform_device(device);
> >>> -	}
> >>> +		struct acpi_bus_ops add_ops = *ops;
> >>>  
> >>> -	if (!device)
> >>> -		return AE_CTRL_DEPTH;
> >>> -
> >>> -	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> >>> -		status = acpi_start_single_object(device);
> >>> -		if (ACPI_FAILURE(status))
> >>> +		add_ops.acpi_op_match = 0;
> >>> +		acpi_add_single_object(&device, handle, type, sta, &add_ops);
> >>> +		if (!device)
> >>>  			return AE_CTRL_DEPTH;
> >>> +
> >>> +		device->bus_ops.acpi_op_match = 1;
> >>>  	}
> >>>  
> >>>  	if (!*return_value)
> >>>  		*return_value = device;
> >>> +
> >>>  	return AE_OK;
> >>>  }
> >>>  
> >>> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> >>> +					void *context, void **not_used)
> >>> +{
> >>> +	struct acpi_bus_ops *ops = context;
> >>> +	struct acpi_device *device;
> >>> +	acpi_status status = AE_OK;
> >>> +
> >>> +	if (acpi_bus_get_device(handle, &device))
> >>> +		return AE_CTRL_DEPTH;
> >>> +
> >>> +	if (ops->acpi_op_add) {
> >>> +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> >>> +			/* This is a known good platform device. */
> >>> +			acpi_create_platform_device(device);
> >>> +		} else {
> >>> +			int ret = device_attach(&device->dev);
> >>> +			acpi_hot_add_bind(device);
> >>> +			if (ret)
> >>> +				status = AE_CTRL_DEPTH;
> >>> +		}
> >>> +	} else if (ops->acpi_op_start) {
> >>> +		if (ACPI_FAILURE(acpi_start_single_object(device)))
> >>> +			status = AE_CTRL_DEPTH;
> >>> +	}
> >>> +	return status;
> >>> +}
> >>> +
> >>>  static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
> >>>  			 struct acpi_device **child)
> >>>  {
> >>> -	acpi_status status;
> >>>  	void *device = NULL;
> >>> +	acpi_status status;
> >>> +	int ret = 0;
> >>>  
> >>>  	status = acpi_bus_check_add(handle, 0, ops, &device);
> >>> -	if (ACPI_SUCCESS(status))
> >>> +	if (ACPI_FAILURE(status)) {
> >>> +		ret = -ENODEV;
> >>> +		goto out;
> >>> +	}
> >>> +
> >>> +	acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> >>> +			    acpi_bus_check_add, NULL, ops, &device);
> >>> +	if (device)
> >>>  		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
> >>> -				    acpi_bus_check_add, NULL, ops, &device);
> >>> +				    acpi_bus_probe_start, NULL, ops, NULL);
> >> Hi Rafael,
> >> 	Should we call acpi_bus_probe_start for the top device corresponding to 
> >> "handle" too here?
> > 
> > Do you mean separately?  I don't think so.  It will be covered by the namespace
> > walking, won't it?
> Hi Rafael,
> 	According to test results from Yijing, we do need to call acpi_bus_probe_start
> for the top device corresponding to "handle".
> 	Comments for acpi_walk_namespace says:
> /*******************************************************************************
>  *
>  * FUNCTION:    acpi_walk_namespace
>  *
>  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
>  *              starting (and ending) at the object specified by start_handle.
>                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>  *              The callback function is called whenever an object that matches
>  *              the type parameter is found. If the callback function returns
>  *              a non-zero value, the search is terminated immediately and this
>  *              value is returned to the caller.
>  *
>  *              The point of this procedure is to provide a generic namespace
>  *              a non-zero value, the search is terminated immediately and this
>  *              value is returned to the caller.
>  *
>  *              The point of this procedure is to provide a generic namespace
>  *              walk routine that can be called from multiple places to
>  *              provide multiple services; the callback function(s) can be
>  *              tailored to each task, whether it is a print function,
>  *              a compare function, etc.
>  *
>  ******************************************************************************/
> 
> But acpi_ns_walk_namespace() doesn't really call the pre_order_visit and post_order_visit
> for the start_handle. That means acpi_walk_namespace won't call the callback for the top
> handle.

You are right.

I'll fix that and send updated series.  It looks like Bjorn wants me to rework
the changelogs anyway. :-)

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering
  2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
                   ` (6 preceding siblings ...)
  2012-12-13 11:45 ` [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
@ 2012-12-13 22:15 ` Rafael J. Wysocki
  2012-12-13 22:17   ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
                     ` (6 more replies)
  7 siblings, 7 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 22:15 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe, Yijing Wang, Jiang Liu

Hi All,

On Sunday, December 09, 2012 11:58:42 PM Rafael J. Wysocki wrote:
> Hi,
> 
> The following patches change the ordering of the ACPI namespace scanning code
> so that all struct acpi_device objects in the given scope are registered before
> ACPI drivers are probed against them.  They also do some simplifications and
> clarifications of the code made possible by this main change.
> 
> This is done for three basic reasons.  First, we need the boot ACPI namespace
> scanning code to be as similar as reasonably possible to the hot-plug ACPI
> namespace scanning code.  Second, the ordering of PCI devices enumeration
> versus ACPI-backed platform devices registration needs to be such that the PCI
> devices in the given scope are all registered first.  Finally, when we start to
> actually manage ACPI device resources as appropriate (e.g. resolve resource
> conflicts properly) we'll need all struct acpi_device nodes to be registered
> before any "companion" physical nodes or ACPI drivers are bound to them.
> 
> The patches have been tested on Toshiba Portege R500 without breaking stuff
> (I used some additional debug code to verify that the ordering of device
> discovery had not been modified by them), but if you see any problems with
> them regarding hot-plug, please let me know.
> 
> [1/6] - Separate adding ACPI device objects from probing ACPI drivers.
> [2/6] - Change the ordering of PCI root bridge driver registration.
> [3/6] - Make acpi_bus_add() and acpi_bus_start() visibly different.
> [4/6] - Reduce the usage of struct acpi_bus_ops
> [5/6] - Replace struct acpi_bus_ops with an enum type
> [6/6] - Change the ordering of acpi_bus_check_add() to avoid unnecessary checks.

The second revision is necessary to address problems found by Yijing Wang
during testing and explained by Jiang Liu (thanks guys!).

The problem is that acpi_walk_namespace() doesn't execute the pre_order_visit
callback for the starting handle, so the callback routine has the be executed
for it directly, if necessary.

I also modified a couple of changelogs to better explain the motivation of the
patches.

Boot sequence tested on Toshiba Portege R500, but testing on systems with
hotplug will be appreciated.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
@ 2012-12-13 22:17   ` Rafael J. Wysocki
  2012-12-18  0:08     ` Toshi Kani
  2012-12-13 22:18   ` [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
                     ` (5 subsequent siblings)
  6 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 22:17 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Split the ACPI namespace scanning for devices into two passes, such
that struct acpi_device objects are registerd in the first pass
without probing ACPI drivers and the drivers are probed against them
directly in the second pass.

There are two main reasons for doing that.

First, the ACPI PCI root bridge driver's .add() routine,
acpi_pci_root_add(), causes struct pci_dev objects to be created for
all PCI devices under the given root bridge.  Usually, there are
corresponding ACPI device nodes in the ACPI namespace for some of
those devices and therefore there should be "companion" struct
acpi_device objects to attach those struct pci_dev objects to.  These
struct acpi_device objects should exist when the corresponding
struct pci_dev objects are created, but that is only guaranteed
during boot and not during hotplug.  This leads to a number of
functional differences between the boot and the hotplug cases which
are not strictly necessary and make the code more complicated.

For example, this forces the ACPI PCI root bridge driver to defer the
registration of the just created struct pci_dev objects and to use a
special .start() callback routine, acpi_pci_root_start(), to make
sure that all of the "companion" struct acpi_device objects will be
present at PCI devices registration time during hotplug.

If those differences can be eliminated, we will be able to
consolidate the boot and hotplug code paths for the enumeration and
registration of PCI devices and to reduce the complexity of that
code quite a bit.

The second reason is that, in general, it should be possible to
resolve conflicts of resources assigned by the BIOS to different
devices represented by ACPI namespace nodes before any drivers bind
to them and before they are attached to "companion" objects
representing physical devices (such as struct pci_dev).  However, for
this purpose we first need to enumerate all ACPI device nodes in the
given namespace scope.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c     |  105 +++++++++++++++++++++++++++++++++---------------
 include/acpi/acpi_bus.h |    1 
 2 files changed, 75 insertions(+), 31 deletions(-)

Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
 struct acpi_bus_ops {
 	u32 acpi_op_add:1;
 	u32 acpi_op_start:1;
+	u32 acpi_op_match:1;
 };
 
 struct acpi_device_ops {
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+	return acpi_dev->bus_ops.acpi_op_match
+		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
 static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
 	return 0;
 }
 
+/*
+ * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
+ * @device: ACPI device node to bind.
+ */
+static void acpi_hot_add_bind(struct acpi_device *device)
+{
+	if (device->flags.bus_address
+	    && device->parent && device->parent->ops.bind)
+		device->parent->ops.bind(device);
+}
+
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
 				  unsigned long long sta,
@@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
 
 	result = acpi_device_register(device);
 
-	/*
-	 * Bind _ADR-Based Devices when hot add
-	 */
-	if (device->flags.bus_address) {
-		if (device->parent && device->parent->ops.bind)
-			device->parent->ops.bind(device);
-	}
+	if (device->bus_ops.acpi_op_match)
+		acpi_hot_add_bind(device);
 
 end:
 	if (!result) {
@@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
 	struct acpi_bus_ops ops = {
 		.acpi_op_add = 1,
 		.acpi_op_start = 1,
+		.acpi_op_match = 1,
 	};
 	struct acpi_device *device = NULL;
 
@@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
 				      void *context, void **return_value)
 {
 	struct acpi_bus_ops *ops = context;
+	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
-	struct acpi_device *device;
 	acpi_status status;
 	int result;
 
@@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_CTRL_DEPTH;
 	}
 
-	/*
-	 * We may already have an acpi_device from a previous enumeration.  If
-	 * so, we needn't add it again, but we may still have to start it.
-	 */
-	device = NULL;
 	acpi_bus_get_device(handle, &device);
 	if (ops->acpi_op_add && !device) {
-		acpi_add_single_object(&device, handle, type, sta, ops);
-		/* Is the device a known good platform device? */
-		if (device
-		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
-			acpi_create_platform_device(device);
-	}
-
-	if (!device)
-		return AE_CTRL_DEPTH;
+		struct acpi_bus_ops add_ops = *ops;
 
-	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
-		status = acpi_start_single_object(device);
-		if (ACPI_FAILURE(status))
+		add_ops.acpi_op_match = 0;
+		acpi_add_single_object(&device, handle, type, sta, &add_ops);
+		if (!device)
 			return AE_CTRL_DEPTH;
+
+		device->bus_ops.acpi_op_match = 1;
 	}
 
 	if (!*return_value)
 		*return_value = device;
+
 	return AE_OK;
 }
 
+static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
+					void *context, void **not_used)
+{
+	struct acpi_bus_ops *ops = context;
+	acpi_status status = AE_OK;
+	struct acpi_device *device;
+	unsigned long long sta_not_used;
+	int type_not_used;
+
+	/*
+	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+	 * namespace walks prematurely.
+	 */
+	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+		return AE_OK;
+
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
+
+	if (ops->acpi_op_add) {
+		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+			/* This is a known good platform device. */
+			acpi_create_platform_device(device);
+		} else {
+			int ret = device_attach(&device->dev);
+			acpi_hot_add_bind(device);
+			if (ret)
+				status = AE_CTRL_DEPTH;
+		}
+	} else if (ops->acpi_op_start) {
+		if (ACPI_FAILURE(acpi_start_single_object(device)))
+			status = AE_CTRL_DEPTH;
+	}
+	return status;
+}
+
 static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
 			 struct acpi_device **child)
 {
-	acpi_status status;
 	void *device = NULL;
+	acpi_status status;
+	int ret = -ENODEV;
 
 	status = acpi_bus_check_add(handle, 0, ops, &device);
 	if (ACPI_SUCCESS(status))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
 				    acpi_bus_check_add, NULL, ops, &device);
 
+	if (!device)
+		goto out;
+
+	ret = 0;
+	status = acpi_bus_probe_start(handle, 0, ops, NULL);
+	if (ACPI_SUCCESS(status))
+		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+				    acpi_bus_probe_start, NULL, ops, NULL);
+
+ out:
 	if (child)
 		*child = device;
 
-	if (device)
-		return 0;
-	else
-		return -ENODEV;
+	return ret;
 }
 
 /*
@@ -1752,6 +1794,7 @@ static int acpi_bus_scan_fixed(void)
 	memset(&ops, 0, sizeof(ops));
 	ops.acpi_op_add = 1;
 	ops.acpi_op_start = 1;
+	ops.acpi_op_match = 1;
 
 	/*
 	 * Enumerate all fixed-feature devices.


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

* [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
  2012-12-13 22:17   ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
@ 2012-12-13 22:18   ` Rafael J. Wysocki
  2012-12-13 22:21   ` [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 22:18 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Instead of running acpi_pci_root_init() from a separate subsys
initcall, call it directly from acpi_scan_init() before scanning the
ACPI namespace for the first time, so that the PCI root bridge
driver's .add() routine, acpi_pci_root_start(), is always run
before binding ACPI drivers or attaching "companion" device objects
to struct acpi_device objects below the root bridge's device node in
the ACPI namespace.

The first, simpler reason for doing this is that it makes the
situation during boot more similar to the situation during hotplug,
in which the ACPI PCI root bridge driver is always present.

The second reason is that acpi_pci_root_init() causes struct pci_dev
objects to be created for all PCI devices below the bridge and
these objects may be necessary for whatever is done with the other
ACPI device nodes in that namespace scope.  For example, devices
created by acpi_create_platform_device() sometimes may need to be
added to the device hierarchy as children of PCI bridges.  For this
purpose, however, the struct pci_dev objects representing those
bridges need to exist before the platform devices in question are
registered.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/internal.h |    1 +
 drivers/acpi/pci_root.c |    4 +---
 drivers/acpi/scan.c     |    1 +
 3 files changed, 3 insertions(+), 3 deletions(-)

Index: linux/drivers/acpi/internal.h
===================================================================
--- linux.orig/drivers/acpi/internal.h
+++ linux/drivers/acpi/internal.h
@@ -67,6 +67,7 @@ struct acpi_ec {
 
 extern struct acpi_ec *first_ec;
 
+int acpi_pci_root_init(void);
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
 int acpi_boot_ec_enable(void);
Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c
+++ linux/drivers/acpi/pci_root.c
@@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a
 	return 0;
 }
 
-static int __init acpi_pci_root_init(void)
+int __init acpi_pci_root_init(void)
 {
 	acpi_hest_init();
 
@@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi
 
 	return 0;
 }
-
-subsys_initcall(acpi_pci_root_init);
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1833,6 +1833,7 @@ int __init acpi_scan_init(void)
 	}
 
 	acpi_power_init();
+	acpi_pci_root_init();
 
 	/*
 	 * Enumerate devices in the ACPI namespace.


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

* [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
  2012-12-13 22:17   ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
  2012-12-13 22:18   ` [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
@ 2012-12-13 22:21   ` Rafael J. Wysocki
  2012-12-13 22:21   ` [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 22:21 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The current ACPI namespace scanning code suggests that acpi_bus_add()
and acpi_bus_start() share some code.  In fact, however, they are
completely different code paths (except for the initial checks), so
refactor the code to make that distinction visibly clear.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   68 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 30 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1622,10 +1622,9 @@ static acpi_status acpi_bus_check_add(ac
 	return AE_OK;
 }
 
-static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
-					void *context, void **not_used)
+static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
+					  void *not_used, void **ret_not_used)
 {
-	struct acpi_bus_ops *ops = context;
 	acpi_status status = AE_OK;
 	struct acpi_device *device;
 	unsigned long long sta_not_used;
@@ -1641,18 +1640,13 @@ static acpi_status acpi_bus_probe_start(
 	if (acpi_bus_get_device(handle, &device))
 		return AE_CTRL_DEPTH;
 
-	if (ops->acpi_op_add) {
-		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
-			/* This is a known good platform device. */
-			acpi_create_platform_device(device);
-		} else {
-			int ret = device_attach(&device->dev);
-			acpi_hot_add_bind(device);
-			if (ret)
-				status = AE_CTRL_DEPTH;
-		}
-	} else if (ops->acpi_op_start) {
-		if (ACPI_FAILURE(acpi_start_single_object(device)))
+	if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+		/* This is a known good platform device. */
+		acpi_create_platform_device(device);
+	} else {
+		int ret = device_attach(&device->dev);
+		acpi_hot_add_bind(device);
+		if (ret)
 			status = AE_CTRL_DEPTH;
 	}
 	return status;
@@ -1674,10 +1668,10 @@ static int acpi_bus_scan(acpi_handle han
 		goto out;
 
 	ret = 0;
-	status = acpi_bus_probe_start(handle, 0, ops, NULL);
+	status = acpi_bus_device_attach(handle, 0, NULL, NULL);
 	if (ACPI_SUCCESS(status))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_probe_start, NULL, ops, NULL);
+				    acpi_bus_device_attach, NULL, NULL, NULL);
 
  out:
 	if (child)
@@ -1702,31 +1696,45 @@ int
 acpi_bus_add(struct acpi_device **child,
 	     struct acpi_device *parent, acpi_handle handle, int type)
 {
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
+	struct acpi_bus_ops ops = { .acpi_op_add = 1, };
 
 	return acpi_bus_scan(handle, &ops, child);
 }
 EXPORT_SYMBOL(acpi_bus_add);
 
-int acpi_bus_start(struct acpi_device *device)
+static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl,
+					 void *not_used, void **ret_not_used)
 {
-	struct acpi_bus_ops ops;
-	int result;
+	struct acpi_device *device;
+	unsigned long long sta_not_used;
+	int type_not_used;
+	acpi_status status;
+
+	/*
+	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+	 * namespace walks prematurely.
+	 */
+	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+		return AE_OK;
+
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
 
+	return acpi_start_single_object(device);
+}
+
+int acpi_bus_start(struct acpi_device *device)
+{
 	if (!device)
 		return -EINVAL;
 
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_start = 1;
-
-	result = acpi_bus_scan(device->handle, &ops, NULL);
+	if (ACPI_SUCCESS(acpi_start_single_object(device)))
+		acpi_walk_namespace(ACPI_TYPE_ANY, device->handle,
+				    ACPI_UINT32_MAX, acpi_bus_start_device,
+				    NULL, NULL, NULL);
 
 	acpi_update_all_gpes();
-
-	return result;
+	return 0;
 }
 EXPORT_SYMBOL(acpi_bus_start);
 


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

* [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
                     ` (2 preceding siblings ...)
  2012-12-13 22:21   ` [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
@ 2012-12-13 22:21   ` Rafael J. Wysocki
  2012-12-13 22:22   ` [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 22:21 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Objects of type struct acpi_bus_ops are currently used to pass
information between different parts of the ACPI namespace scanning
code, sometimes in quite convoluted ways.  It turns out that that
is not necessary in some cases, so simplify the code by reducing
the utilization of struct acpi_bus_ops objects where clearly
possible.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   40 ++++++++++++++++------------------------
 1 file changed, 16 insertions(+), 24 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1527,7 +1527,6 @@ end:
 static void acpi_bus_add_power_resource(acpi_handle handle)
 {
 	struct acpi_bus_ops ops = {
-		.acpi_op_add = 1,
 		.acpi_op_start = 1,
 		.acpi_op_match = 1,
 	};
@@ -1581,7 +1580,6 @@ static int acpi_bus_type_and_status(acpi
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
 				      void *context, void **return_value)
 {
-	struct acpi_bus_ops *ops = context;
 	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
@@ -1605,11 +1603,13 @@ static acpi_status acpi_bus_check_add(ac
 	}
 
 	acpi_bus_get_device(handle, &device);
-	if (ops->acpi_op_add && !device) {
-		struct acpi_bus_ops add_ops = *ops;
+	if (!device) {
+		struct acpi_bus_ops ops = {
+			.acpi_op_start = !!context,
+			.acpi_op_match = 0,
+		};
 
-		add_ops.acpi_op_match = 0;
-		acpi_add_single_object(&device, handle, type, sta, &add_ops);
+		acpi_add_single_object(&device, handle, type, sta, &ops);
 		if (!device)
 			return AE_CTRL_DEPTH;
 
@@ -1652,17 +1652,18 @@ static acpi_status acpi_bus_device_attac
 	return status;
 }
 
-static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
+static int acpi_bus_scan(acpi_handle handle, bool start,
 			 struct acpi_device **child)
 {
 	void *device = NULL;
 	acpi_status status;
 	int ret = -ENODEV;
 
-	status = acpi_bus_check_add(handle, 0, ops, &device);
+	status = acpi_bus_check_add(handle, 0, (void *)start, &device);
 	if (ACPI_SUCCESS(status))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_check_add, NULL, ops, &device);
+				    acpi_bus_check_add, NULL, (void *)start,
+				    &device);
 
 	if (!device)
 		goto out;
@@ -1696,9 +1697,7 @@ int
 acpi_bus_add(struct acpi_device **child,
 	     struct acpi_device *parent, acpi_handle handle, int type)
 {
-	struct acpi_bus_ops ops = { .acpi_op_add = 1, };
-
-	return acpi_bus_scan(handle, &ops, child);
+	return acpi_bus_scan(handle, false, child);
 }
 EXPORT_SYMBOL(acpi_bus_add);
 
@@ -1796,12 +1795,10 @@ static int acpi_bus_scan_fixed(void)
 {
 	int result = 0;
 	struct acpi_device *device = NULL;
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
-	ops.acpi_op_start = 1;
-	ops.acpi_op_match = 1;
+	struct acpi_bus_ops ops = {
+		.acpi_op_start = 1,
+		.acpi_op_match = 1,
+	};
 
 	/*
 	 * Enumerate all fixed-feature devices.
@@ -1827,11 +1824,6 @@ static int acpi_bus_scan_fixed(void)
 int __init acpi_scan_init(void)
 {
 	int result;
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
-	ops.acpi_op_start = 1;
 
 	result = bus_register(&acpi_bus_type);
 	if (result) {
@@ -1845,7 +1837,7 @@ int __init acpi_scan_init(void)
 	/*
 	 * Enumerate devices in the ACPI namespace.
 	 */
-	result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
+	result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root);
 
 	if (!result)
 		result = acpi_bus_scan_fixed();


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

* [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
                     ` (3 preceding siblings ...)
  2012-12-13 22:21   ` [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
@ 2012-12-13 22:22   ` Rafael J. Wysocki
  2012-12-13 22:23   ` [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
  2012-12-14  9:56   ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
  6 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 22:22 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Notice that one member of struct acpi_bus_ops, acpi_op_add, is not
used anywhere any more and the relationship between its remaining
members, acpi_op_match and acpi_op_start, is such that it doesn't
make sense to set the latter without setting the former at the same
time.  Therefore, replace struct acpi_bus_ops with new a enum type,
enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC,
ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to
both acpi_op_match and acpi_op_start unset, acpi_op_match set and
acpi_op_start unset, and both acpi_op_match and acpi_op_start set,
respectively.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c     |   35 ++++++++++++-----------------------
 include/acpi/acpi_bus.h |   15 ++++++++-------
 2 files changed, 20 insertions(+), 30 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -494,7 +494,7 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return acpi_dev->bus_ops.acpi_op_match
+	return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH
 		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
@@ -580,7 +580,7 @@ static int acpi_device_probe(struct devi
 
 	ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
 	if (!ret) {
-		if (acpi_dev->bus_ops.acpi_op_start)
+		if (acpi_dev->add_type == ACPI_BUS_ADD_START)
 			acpi_start_single_object(acpi_dev);
 
 		if (acpi_drv->ops.notify) {
@@ -1433,7 +1433,7 @@ static void acpi_hot_add_bind(struct acp
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
 				  unsigned long long sta,
-				  struct acpi_bus_ops *ops)
+				  enum acpi_bus_add_type add_type)
 {
 	int result;
 	struct acpi_device *device;
@@ -1449,7 +1449,7 @@ static int acpi_add_single_object(struct
 	device->device_type = type;
 	device->handle = handle;
 	device->parent = acpi_bus_get_parent(handle);
-	device->bus_ops = *ops; /* workround for not call .start */
+	device->add_type = add_type;
 	STRUCT_TO_INT(device->status) = sta;
 
 	acpi_device_get_busid(device);
@@ -1502,7 +1502,7 @@ static int acpi_add_single_object(struct
 
 	result = acpi_device_register(device);
 
-	if (device->bus_ops.acpi_op_match)
+	if (device->add_type >= ACPI_BUS_ADD_MATCH)
 		acpi_hot_add_bind(device);
 
 end:
@@ -1526,16 +1526,12 @@ end:
 
 static void acpi_bus_add_power_resource(acpi_handle handle)
 {
-	struct acpi_bus_ops ops = {
-		.acpi_op_start = 1,
-		.acpi_op_match = 1,
-	};
 	struct acpi_device *device = NULL;
 
 	acpi_bus_get_device(handle, &device);
 	if (!device)
 		acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
-					ACPI_STA_DEFAULT, &ops);
+					ACPI_STA_DEFAULT, ACPI_BUS_ADD_START);
 }
 
 static int acpi_bus_type_and_status(acpi_handle handle, int *type,
@@ -1604,16 +1600,13 @@ static acpi_status acpi_bus_check_add(ac
 
 	acpi_bus_get_device(handle, &device);
 	if (!device) {
-		struct acpi_bus_ops ops = {
-			.acpi_op_start = !!context,
-			.acpi_op_match = 0,
-		};
-
-		acpi_add_single_object(&device, handle, type, sta, &ops);
+		acpi_add_single_object(&device, handle, type, sta,
+				       ACPI_BUS_ADD_BASIC);
 		if (!device)
 			return AE_CTRL_DEPTH;
 
-		device->bus_ops.acpi_op_match = 1;
+		device->add_type = context ?
+					ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
 	}
 
 	if (!*return_value)
@@ -1795,10 +1788,6 @@ static int acpi_bus_scan_fixed(void)
 {
 	int result = 0;
 	struct acpi_device *device = NULL;
-	struct acpi_bus_ops ops = {
-		.acpi_op_start = 1,
-		.acpi_op_match = 1,
-	};
 
 	/*
 	 * Enumerate all fixed-feature devices.
@@ -1807,7 +1796,7 @@ static int acpi_bus_scan_fixed(void)
 		result = acpi_add_single_object(&device, NULL,
 						ACPI_BUS_TYPE_POWER_BUTTON,
 						ACPI_STA_DEFAULT,
-						&ops);
+						ACPI_BUS_ADD_START);
 		device_init_wakeup(&device->dev, true);
 	}
 
@@ -1815,7 +1804,7 @@ static int acpi_bus_scan_fixed(void)
 		result = acpi_add_single_object(&device, NULL,
 						ACPI_BUS_TYPE_SLEEP_BUTTON,
 						ACPI_STA_DEFAULT,
-						&ops);
+						ACPI_BUS_ADD_START);
 	}
 
 	return result;
Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -63,6 +63,13 @@ acpi_get_physical_device_location(acpi_h
 #define ACPI_BUS_FILE_ROOT	"acpi"
 extern struct proc_dir_entry *acpi_root_dir;
 
+enum acpi_bus_add_type {
+	ACPI_BUS_ADD_BASIC = 0,
+	ACPI_BUS_ADD_MATCH,
+	ACPI_BUS_ADD_START,
+	ACPI_BUS_ADD_TYPE_COUNT
+};
+
 enum acpi_bus_removal_type {
 	ACPI_BUS_REMOVAL_NORMAL = 0,
 	ACPI_BUS_REMOVAL_EJECT,
@@ -95,12 +102,6 @@ typedef int (*acpi_op_bind) (struct acpi
 typedef int (*acpi_op_unbind) (struct acpi_device * device);
 typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
 
-struct acpi_bus_ops {
-	u32 acpi_op_add:1;
-	u32 acpi_op_start:1;
-	u32 acpi_op_match:1;
-};
-
 struct acpi_device_ops {
 	acpi_op_add add;
 	acpi_op_remove remove;
@@ -284,7 +285,7 @@ struct acpi_device {
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
-	struct acpi_bus_ops bus_ops;	/* workaround for different code path for hotplug */
+	enum acpi_bus_add_type add_type;	/* how to handle adding */
 	enum acpi_bus_removal_type removal_type;	/* indicate for different removal type */
 	u8 physical_node_count;
 	struct list_head physical_node_list;


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

* [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add()
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
                     ` (4 preceding siblings ...)
  2012-12-13 22:22   ` [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
@ 2012-12-13 22:23   ` Rafael J. Wysocki
  2012-12-14  9:56   ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
  6 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-13 22:23 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, LKML, linux-pci, Yinghai Lu, Toshi Kani,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

If acpi_bus_check_add() is called for a handle already having an
existing struct acpi_device object attached, it is not necessary to
check the type and status of the device correspondig to it, so
change the ordering of acpi_bus_check_add() to avoid that.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac
 	acpi_status status;
 	int result;
 
+	acpi_bus_get_device(handle, &device);
+	if (device)
+		goto out;
+
 	result = acpi_bus_type_and_status(handle, &type, &sta);
 	if (result)
 		return AE_OK;
@@ -1598,17 +1602,13 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_CTRL_DEPTH;
 	}
 
-	acpi_bus_get_device(handle, &device);
-	if (!device) {
-		acpi_add_single_object(&device, handle, type, sta,
-				       ACPI_BUS_ADD_BASIC);
-		if (!device)
-			return AE_CTRL_DEPTH;
+	acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC);
+	if (!device)
+		return AE_CTRL_DEPTH;
 
-		device->add_type = context ?
-					ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
-	}
+	device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
 
+ out:
 	if (!*return_value)
 		*return_value = device;
 


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

* Re: [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering
  2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
                     ` (5 preceding siblings ...)
  2012-12-13 22:23   ` [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
@ 2012-12-14  9:56   ` Yijing Wang
  2012-12-14 22:59     ` Rafael J. Wysocki
  6 siblings, 1 reply; 88+ messages in thread
From: Yijing Wang @ 2012-12-14  9:56 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu

On 2012/12/14 6:15, Rafael J. Wysocki wrote:
> Hi All,
> 
> On Sunday, December 09, 2012 11:58:42 PM Rafael J. Wysocki wrote:
>> Hi,
>>
>> The following patches change the ordering of the ACPI namespace scanning code
>> so that all struct acpi_device objects in the given scope are registered before
>> ACPI drivers are probed against them.  They also do some simplifications and
>> clarifications of the code made possible by this main change.
>>
>> This is done for three basic reasons.  First, we need the boot ACPI namespace
>> scanning code to be as similar as reasonably possible to the hot-plug ACPI
>> namespace scanning code.  Second, the ordering of PCI devices enumeration
>> versus ACPI-backed platform devices registration needs to be such that the PCI
>> devices in the given scope are all registered first.  Finally, when we start to
>> actually manage ACPI device resources as appropriate (e.g. resolve resource
>> conflicts properly) we'll need all struct acpi_device nodes to be registered
>> before any "companion" physical nodes or ACPI drivers are bound to them.
>>
>> The patches have been tested on Toshiba Portege R500 without breaking stuff
>> (I used some additional debug code to verify that the ordering of device
>> discovery had not been modified by them), but if you see any problems with
>> them regarding hot-plug, please let me know.
>>
>> [1/6] - Separate adding ACPI device objects from probing ACPI drivers.
>> [2/6] - Change the ordering of PCI root bridge driver registration.
>> [3/6] - Make acpi_bus_add() and acpi_bus_start() visibly different.
>> [4/6] - Reduce the usage of struct acpi_bus_ops
>> [5/6] - Replace struct acpi_bus_ops with an enum type
>> [6/6] - Change the ordering of acpi_bus_check_add() to avoid unnecessary checks.
> 
> The second revision is necessary to address problems found by Yijing Wang
> during testing and explained by Jiang Liu (thanks guys!).
> 
> The problem is that acpi_walk_namespace() doesn't execute the pre_order_visit
> callback for the starting handle, so the callback routine has the be executed
> for it directly, if necessary.
> 
> I also modified a couple of changelogs to better explain the motivation of the
> patches.
> 
> Boot sequence tested on Toshiba Portege R500, but testing on systems with
> hotplug will be appreciated.

Hi rafael,
   I tested this version patchset in my ia64 hotplug machine, and the result looks ok.

Thanks!
Yijing

> 
> Thanks,
> Rafael
> 
> 


-- 
Thanks!
Yijing


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

* Re: [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering
  2012-12-14  9:56   ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
@ 2012-12-14 22:59     ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-14 22:59 UTC (permalink / raw)
  To: Yijing Wang
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Toshi Kani, Myron Stowe, Yijing Wang, Jiang Liu

On Friday, December 14, 2012 05:56:46 PM Yijing Wang wrote:
> On 2012/12/14 6:15, Rafael J. Wysocki wrote:
> > Hi All,
> > 
> > On Sunday, December 09, 2012 11:58:42 PM Rafael J. Wysocki wrote:
> >> Hi,
> >>
> >> The following patches change the ordering of the ACPI namespace scanning code
> >> so that all struct acpi_device objects in the given scope are registered before
> >> ACPI drivers are probed against them.  They also do some simplifications and
> >> clarifications of the code made possible by this main change.
> >>
> >> This is done for three basic reasons.  First, we need the boot ACPI namespace
> >> scanning code to be as similar as reasonably possible to the hot-plug ACPI
> >> namespace scanning code.  Second, the ordering of PCI devices enumeration
> >> versus ACPI-backed platform devices registration needs to be such that the PCI
> >> devices in the given scope are all registered first.  Finally, when we start to
> >> actually manage ACPI device resources as appropriate (e.g. resolve resource
> >> conflicts properly) we'll need all struct acpi_device nodes to be registered
> >> before any "companion" physical nodes or ACPI drivers are bound to them.
> >>
> >> The patches have been tested on Toshiba Portege R500 without breaking stuff
> >> (I used some additional debug code to verify that the ordering of device
> >> discovery had not been modified by them), but if you see any problems with
> >> them regarding hot-plug, please let me know.
> >>
> >> [1/6] - Separate adding ACPI device objects from probing ACPI drivers.
> >> [2/6] - Change the ordering of PCI root bridge driver registration.
> >> [3/6] - Make acpi_bus_add() and acpi_bus_start() visibly different.
> >> [4/6] - Reduce the usage of struct acpi_bus_ops
> >> [5/6] - Replace struct acpi_bus_ops with an enum type
> >> [6/6] - Change the ordering of acpi_bus_check_add() to avoid unnecessary checks.
> > 
> > The second revision is necessary to address problems found by Yijing Wang
> > during testing and explained by Jiang Liu (thanks guys!).
> > 
> > The problem is that acpi_walk_namespace() doesn't execute the pre_order_visit
> > callback for the starting handle, so the callback routine has the be executed
> > for it directly, if necessary.
> > 
> > I also modified a couple of changelogs to better explain the motivation of the
> > patches.
> > 
> > Boot sequence tested on Toshiba Portege R500, but testing on systems with
> > hotplug will be appreciated.
> 
> Hi rafael,
>    I tested this version patchset in my ia64 hotplug machine, and the result looks ok.

Great, thanks a lot for testing!

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-13 22:17   ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
@ 2012-12-18  0:08     ` Toshi Kani
  2012-12-18  1:48       ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Toshi Kani @ 2012-12-18  0:08 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Thu, 2012-12-13 at 23:17 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 

(snip)

>  struct acpi_device_ops {
> Index: linux/drivers/acpi/scan.c
> ===================================================================
> --- linux.orig/drivers/acpi/scan.c
> +++ linux/drivers/acpi/scan.c
> @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
>  	struct acpi_device *acpi_dev = to_acpi_device(dev);
>  	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
>  
> -	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> +	return acpi_dev->bus_ops.acpi_op_match
> +		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
>  }
>  
>  static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
> @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
>  	return 0;
>  }
>  
> +/*
> + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
> + * @device: ACPI device node to bind.
> + */
> +static void acpi_hot_add_bind(struct acpi_device *device)
> +{
> +	if (device->flags.bus_address
> +	    && device->parent && device->parent->ops.bind)
> +		device->parent->ops.bind(device);
> +}
> +
>  static int acpi_add_single_object(struct acpi_device **child,
>  				  acpi_handle handle, int type,
>  				  unsigned long long sta,
> @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
>  
>  	result = acpi_device_register(device);
>  
> -	/*
> -	 * Bind _ADR-Based Devices when hot add
> -	 */
> -	if (device->flags.bus_address) {
> -		if (device->parent && device->parent->ops.bind)
> -			device->parent->ops.bind(device);
> -	}

I think the original code above is hot-add only because ops.bind is not
set at boot since the acpi_pci driver has not been registered yet.  It
seems that acpi_pci_bridge_scan() called from acpi_pci_root_add() takes
care of the binding.

This brings me a question for acpi_bus_probe_start() below...


> +	if (device->bus_ops.acpi_op_match)
> +		acpi_hot_add_bind(device);
>  
>  end:
>  	if (!result) {
> @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
>  	struct acpi_bus_ops ops = {
>  		.acpi_op_add = 1,
>  		.acpi_op_start = 1,
> +		.acpi_op_match = 1,
>  	};
>  	struct acpi_device *device = NULL;
>  
> @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
>  				      void *context, void **return_value)
>  {
>  	struct acpi_bus_ops *ops = context;
> +	struct acpi_device *device = NULL;
>  	int type;
>  	unsigned long long sta;
> -	struct acpi_device *device;
>  	acpi_status status;
>  	int result;
>  
> @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac
>  		return AE_CTRL_DEPTH;
>  	}
>  
> -	/*
> -	 * We may already have an acpi_device from a previous enumeration.  If
> -	 * so, we needn't add it again, but we may still have to start it.
> -	 */
> -	device = NULL;
>  	acpi_bus_get_device(handle, &device);
>  	if (ops->acpi_op_add && !device) {
> -		acpi_add_single_object(&device, handle, type, sta, ops);
> -		/* Is the device a known good platform device? */
> -		if (device
> -		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
> -			acpi_create_platform_device(device);
> -	}
> -
> -	if (!device)
> -		return AE_CTRL_DEPTH;
> +		struct acpi_bus_ops add_ops = *ops;
>  
> -	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> -		status = acpi_start_single_object(device);
> -		if (ACPI_FAILURE(status))
> +		add_ops.acpi_op_match = 0;
> +		acpi_add_single_object(&device, handle, type, sta, &add_ops);
> +		if (!device)
>  			return AE_CTRL_DEPTH;
> +
> +		device->bus_ops.acpi_op_match = 1;
>  	}
>  
>  	if (!*return_value)
>  		*return_value = device;
> +
>  	return AE_OK;
>  }
>  
> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> +					void *context, void **not_used)
> +{
> +	struct acpi_bus_ops *ops = context;
> +	acpi_status status = AE_OK;
> +	struct acpi_device *device;
> +	unsigned long long sta_not_used;
> +	int type_not_used;
> +
> +	/*
> +	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating

"ignore" seems duplicated. 

> +	 * namespace walks prematurely.
> +	 */
> +	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> +		return AE_OK;
> +
> +	if (acpi_bus_get_device(handle, &device))
> +		return AE_CTRL_DEPTH;
> +
> +	if (ops->acpi_op_add) {
> +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> +			/* This is a known good platform device. */
> +			acpi_create_platform_device(device);
> +		} else {
> +			int ret = device_attach(&device->dev);
> +			acpi_hot_add_bind(device);

Since acpi_pci_root_add() is called by device_attach(), I think this
acpi_hot_add_bind() calls .bind() of a device at boot since its .bind()
may be set.  Is that correct?  If so, how does it coordinate with the
bind procedure in acpi_pci_bridge_scan()?


Thanks,
-Toshi



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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18  0:08     ` Toshi Kani
@ 2012-12-18  1:48       ` Rafael J. Wysocki
  2012-12-18 16:10         ` Toshi Kani
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
  0 siblings, 2 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-18  1:48 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Monday, December 17, 2012 05:08:17 PM Toshi Kani wrote:
> On Thu, 2012-12-13 at 23:17 +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> 
> (snip)
> 
> >  struct acpi_device_ops {
> > Index: linux/drivers/acpi/scan.c
> > ===================================================================
> > --- linux.orig/drivers/acpi/scan.c
> > +++ linux/drivers/acpi/scan.c
> > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
> >  	struct acpi_device *acpi_dev = to_acpi_device(dev);
> >  	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
> >  
> > -	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> > +	return acpi_dev->bus_ops.acpi_op_match
> > +		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> >  }
> >  
> >  static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
> > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
> >  	return 0;
> >  }
> >  
> > +/*
> > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
> > + * @device: ACPI device node to bind.
> > + */
> > +static void acpi_hot_add_bind(struct acpi_device *device)
> > +{
> > +	if (device->flags.bus_address
> > +	    && device->parent && device->parent->ops.bind)
> > +		device->parent->ops.bind(device);
> > +}
> > +
> >  static int acpi_add_single_object(struct acpi_device **child,
> >  				  acpi_handle handle, int type,
> >  				  unsigned long long sta,
> > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
> >  
> >  	result = acpi_device_register(device);
> >  
> > -	/*
> > -	 * Bind _ADR-Based Devices when hot add
> > -	 */
> > -	if (device->flags.bus_address) {
> > -		if (device->parent && device->parent->ops.bind)
> > -			device->parent->ops.bind(device);
> > -	}
> 
> I think the original code above is hot-add only because ops.bind is not
> set at boot since the acpi_pci driver has not been registered yet.  It
> seems that acpi_pci_bridge_scan() called from acpi_pci_root_add() takes
> care of the binding.

Ah, I see the problem.  During boot the PCI root bridge driver is not present
yet when all struct acpi_device "devices" are registered, so their parents'
.bind() callbacks are all empty, so the code above has no effect.

But say we're doing a PCI root bridge hotplug, in which case the driver is
present, so acpi_pci_bind() will be executed both from acpi_pci_bridge_scan()
and from here, won't it?

OK, this needs to be addressed.

> This brings me a question for acpi_bus_probe_start() below...
> 
> 
> > +	if (device->bus_ops.acpi_op_match)
> > +		acpi_hot_add_bind(device);
> >  
> >  end:
> >  	if (!result) {
> > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
> >  	struct acpi_bus_ops ops = {
> >  		.acpi_op_add = 1,
> >  		.acpi_op_start = 1,
> > +		.acpi_op_match = 1,
> >  	};
> >  	struct acpi_device *device = NULL;
> >  
> > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
> >  				      void *context, void **return_value)
> >  {
> >  	struct acpi_bus_ops *ops = context;
> > +	struct acpi_device *device = NULL;
> >  	int type;
> >  	unsigned long long sta;
> > -	struct acpi_device *device;
> >  	acpi_status status;
> >  	int result;
> >  
> > @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac
> >  		return AE_CTRL_DEPTH;
> >  	}
> >  
> > -	/*
> > -	 * We may already have an acpi_device from a previous enumeration.  If
> > -	 * so, we needn't add it again, but we may still have to start it.
> > -	 */
> > -	device = NULL;
> >  	acpi_bus_get_device(handle, &device);
> >  	if (ops->acpi_op_add && !device) {
> > -		acpi_add_single_object(&device, handle, type, sta, ops);
> > -		/* Is the device a known good platform device? */
> > -		if (device
> > -		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
> > -			acpi_create_platform_device(device);
> > -	}
> > -
> > -	if (!device)
> > -		return AE_CTRL_DEPTH;
> > +		struct acpi_bus_ops add_ops = *ops;
> >  
> > -	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> > -		status = acpi_start_single_object(device);
> > -		if (ACPI_FAILURE(status))
> > +		add_ops.acpi_op_match = 0;
> > +		acpi_add_single_object(&device, handle, type, sta, &add_ops);
> > +		if (!device)
> >  			return AE_CTRL_DEPTH;
> > +
> > +		device->bus_ops.acpi_op_match = 1;
> >  	}
> >  
> >  	if (!*return_value)
> >  		*return_value = device;
> > +
> >  	return AE_OK;
> >  }
> >  
> > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> > +					void *context, void **not_used)
> > +{
> > +	struct acpi_bus_ops *ops = context;
> > +	acpi_status status = AE_OK;
> > +	struct acpi_device *device;
> > +	unsigned long long sta_not_used;
> > +	int type_not_used;
> > +
> > +	/*
> > +	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
> 
> "ignore" seems duplicated. 
 
It is not.  This is supposed to mean that the errors previously ignored by
acpi_bus_check_add() should be ignored here as well.

> > +	 * namespace walks prematurely.
> > +	 */
> > +	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> > +		return AE_OK;
> > +
> > +	if (acpi_bus_get_device(handle, &device))
> > +		return AE_CTRL_DEPTH;
> > +
> > +	if (ops->acpi_op_add) {
> > +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> > +			/* This is a known good platform device. */
> > +			acpi_create_platform_device(device);
> > +		} else {
> > +			int ret = device_attach(&device->dev);
> > +			acpi_hot_add_bind(device);
> 
> Since acpi_pci_root_add() is called by device_attach(), I think this
> acpi_hot_add_bind() calls .bind() of a device at boot since its .bind()
> may be set.  Is that correct?  If so, how does it coordinate with the
> bind procedure in acpi_pci_bridge_scan()?

It actually doesn't.

However, the $subject patch doesn't change this particular aspect of the
original behavior, because with it applied the PCI root bridge driver is still
not present when the device_attach() above is executed for all objects in the
given namespace scope, so the .bind() callbacks should all be empty.  In other
words, it doesn't change the boot case.

It also reproduces the original behavior in the hotplug case which may not be
correct.  Patch [2/6], however, kind of changes the boot case into the hotplug
case and things start to get ugly.

Well, what about calling acpi_hot_add_bind() from acpi_bus_check_add(),
right after doing the acpi_add_single_object()?  It would avoid calling
acpi_pci_bind() twice for the same device during root bridge hotplug too,
because in that case acpi_pci_root_add() will be called after all of these
acpi_hot_add_bind() calls.  At the same time if a single device is
hot-added and its parent happens to have .bind() set, it will be run
from acpi_bus_check_add().

Updated patch is appended.

Thanks,
Rafael


---
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Subject: ACPI: Separate adding ACPI device objects from probing ACPI drivers

Split the ACPI namespace scanning for devices into two passes, such
that struct acpi_device objects are registerd in the first pass
without probing ACPI drivers and the drivers are probed against them
directly in the second pass.

There are two main reasons for doing that.

First, the ACPI PCI root bridge driver's .add() routine,
acpi_pci_root_add(), causes struct pci_dev objects to be created for
all PCI devices under the given root bridge.  Usually, there are
corresponding ACPI device nodes in the ACPI namespace for some of
those devices and therefore there should be "companion" struct
acpi_device objects to attach those struct pci_dev objects to.  These
struct acpi_device objects should exist when the corresponding
struct pci_dev objects are created, but that is only guaranteed
during boot and not during hotplug.  This leads to a number of
functional differences between the boot and the hotplug cases which
are not strictly necessary and make the code more complicated.

For example, this forces the ACPI PCI root bridge driver to defer the
registration of the just created struct pci_dev objects and to use a
special .start() callback routine, acpi_pci_root_start(), to make
sure that all of the "companion" struct acpi_device objects will be
present at PCI devices registration time during hotplug.

If those differences can be eliminated, we will be able to
consolidate the boot and hotplug code paths for the enumeration and
registration of PCI devices and to reduce the complexity of that
code quite a bit.

The second reason is that, in general, it should be possible to
resolve conflicts of resources assigned by the BIOS to different
devices represented by ACPI namespace nodes before any drivers bind
to them and before they are attached to "companion" objects
representing physical devices (such as struct pci_dev).  However, for
this purpose we first need to enumerate all ACPI device nodes in the
given namespace scope.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c     |  103 +++++++++++++++++++++++++++++++++---------------
 include/acpi/acpi_bus.h |    1 
 2 files changed, 73 insertions(+), 31 deletions(-)

Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
 struct acpi_bus_ops {
 	u32 acpi_op_add:1;
 	u32 acpi_op_start:1;
+	u32 acpi_op_match:1;
 };
 
 struct acpi_device_ops {
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+	return acpi_dev->bus_ops.acpi_op_match
+		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
 static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
 	return 0;
 }
 
+/*
+ * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
+ * @device: ACPI device node to bind.
+ */
+static void acpi_hot_add_bind(struct acpi_device *device)
+{
+	if (device->flags.bus_address
+	    && device->parent && device->parent->ops.bind)
+		device->parent->ops.bind(device);
+}
+
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
 				  unsigned long long sta,
@@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
 
 	result = acpi_device_register(device);
 
-	/*
-	 * Bind _ADR-Based Devices when hot add
-	 */
-	if (device->flags.bus_address) {
-		if (device->parent && device->parent->ops.bind)
-			device->parent->ops.bind(device);
-	}
+	if (device->bus_ops.acpi_op_match)
+		acpi_hot_add_bind(device);
 
 end:
 	if (!result) {
@@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
 	struct acpi_bus_ops ops = {
 		.acpi_op_add = 1,
 		.acpi_op_start = 1,
+		.acpi_op_match = 1,
 	};
 	struct acpi_device *device = NULL;
 
@@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
 				      void *context, void **return_value)
 {
 	struct acpi_bus_ops *ops = context;
+	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
-	struct acpi_device *device;
 	acpi_status status;
 	int result;
 
@@ -1596,52 +1604,84 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_CTRL_DEPTH;
 	}
 
-	/*
-	 * We may already have an acpi_device from a previous enumeration.  If
-	 * so, we needn't add it again, but we may still have to start it.
-	 */
-	device = NULL;
 	acpi_bus_get_device(handle, &device);
 	if (ops->acpi_op_add && !device) {
-		acpi_add_single_object(&device, handle, type, sta, ops);
-		/* Is the device a known good platform device? */
-		if (device
-		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
-			acpi_create_platform_device(device);
-	}
-
-	if (!device)
-		return AE_CTRL_DEPTH;
+		struct acpi_bus_ops add_ops = *ops;
 
-	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
-		status = acpi_start_single_object(device);
-		if (ACPI_FAILURE(status))
+		add_ops.acpi_op_match = 0;
+		acpi_add_single_object(&device, handle, type, sta, &add_ops);
+		if (!device)
 			return AE_CTRL_DEPTH;
+
+		device->bus_ops.acpi_op_match = 1;
+		acpi_hot_add_bind(device);
 	}
 
 	if (!*return_value)
 		*return_value = device;
+
 	return AE_OK;
 }
 
+static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
+					void *context, void **not_used)
+{
+	struct acpi_bus_ops *ops = context;
+	acpi_status status = AE_OK;
+	struct acpi_device *device;
+	unsigned long long sta_not_used;
+	int type_not_used;
+
+	/*
+	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+	 * namespace walks prematurely.
+	 */
+	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+		return AE_OK;
+
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
+
+	if (ops->acpi_op_add) {
+		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+			/* This is a known good platform device. */
+			acpi_create_platform_device(device);
+		} else if (device_attach(&device->dev)) {
+			status = AE_CTRL_DEPTH;
+		}
+	} else if (ops->acpi_op_start) {
+		if (ACPI_FAILURE(acpi_start_single_object(device)))
+			status = AE_CTRL_DEPTH;
+	}
+	return status;
+}
+
 static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
 			 struct acpi_device **child)
 {
-	acpi_status status;
 	void *device = NULL;
+	acpi_status status;
+	int ret = -ENODEV;
 
 	status = acpi_bus_check_add(handle, 0, ops, &device);
 	if (ACPI_SUCCESS(status))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
 				    acpi_bus_check_add, NULL, ops, &device);
 
+	if (!device)
+		goto out;
+
+	ret = 0;
+	status = acpi_bus_probe_start(handle, 0, ops, NULL);
+	if (ACPI_SUCCESS(status))
+		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+				    acpi_bus_probe_start, NULL, ops, NULL);
+
+ out:
 	if (child)
 		*child = device;
 
-	if (device)
-		return 0;
-	else
-		return -ENODEV;
+	return ret;
 }
 
 /*
@@ -1752,6 +1792,7 @@ static int acpi_bus_scan_fixed(void)
 	memset(&ops, 0, sizeof(ops));
 	ops.acpi_op_add = 1;
 	ops.acpi_op_start = 1;
+	ops.acpi_op_match = 1;
 
 	/*
 	 * Enumerate all fixed-feature devices.


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18  1:48       ` Rafael J. Wysocki
@ 2012-12-18 16:10         ` Toshi Kani
  2012-12-18 18:59           ` Yinghai Lu
  2012-12-18 21:57           ` Rafael J. Wysocki
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
  1 sibling, 2 replies; 88+ messages in thread
From: Toshi Kani @ 2012-12-18 16:10 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
> On Monday, December 17, 2012 05:08:17 PM Toshi Kani wrote:
> > On Thu, 2012-12-13 at 23:17 +0100, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > 
> > 
> > (snip)
> > 
> > >  struct acpi_device_ops {
> > > Index: linux/drivers/acpi/scan.c
> > > ===================================================================
> > > --- linux.orig/drivers/acpi/scan.c
> > > +++ linux/drivers/acpi/scan.c
> > > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
> > >  	struct acpi_device *acpi_dev = to_acpi_device(dev);
> > >  	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
> > >  
> > > -	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> > > +	return acpi_dev->bus_ops.acpi_op_match
> > > +		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> > >  }
> > >  
> > >  static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
> > > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
> > >  	return 0;
> > >  }
> > >  
> > > +/*
> > > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
> > > + * @device: ACPI device node to bind.
> > > + */
> > > +static void acpi_hot_add_bind(struct acpi_device *device)
> > > +{
> > > +	if (device->flags.bus_address
> > > +	    && device->parent && device->parent->ops.bind)
> > > +		device->parent->ops.bind(device);
> > > +}
> > > +
> > >  static int acpi_add_single_object(struct acpi_device **child,
> > >  				  acpi_handle handle, int type,
> > >  				  unsigned long long sta,
> > > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
> > >  
> > >  	result = acpi_device_register(device);
> > >  
> > > -	/*
> > > -	 * Bind _ADR-Based Devices when hot add
> > > -	 */
> > > -	if (device->flags.bus_address) {
> > > -		if (device->parent && device->parent->ops.bind)
> > > -			device->parent->ops.bind(device);
> > > -	}
> > 
> > I think the original code above is hot-add only because ops.bind is not
> > set at boot since the acpi_pci driver has not been registered yet.  It
> > seems that acpi_pci_bridge_scan() called from acpi_pci_root_add() takes
> > care of the binding.
> 
> Ah, I see the problem.  During boot the PCI root bridge driver is not present
> yet when all struct acpi_device "devices" are registered, so their parents'
> .bind() callbacks are all empty, so the code above has no effect.
> 
> But say we're doing a PCI root bridge hotplug, in which case the driver is
> present, so acpi_pci_bind() will be executed both from acpi_pci_bridge_scan()
> and from here, won't it?

Right.


> OK, this needs to be addressed.
> 
> > This brings me a question for acpi_bus_probe_start() below...
> > 
> > 
> > > +	if (device->bus_ops.acpi_op_match)
> > > +		acpi_hot_add_bind(device);
> > >  
> > >  end:
> > >  	if (!result) {
> > > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
> > >  	struct acpi_bus_ops ops = {
> > >  		.acpi_op_add = 1,
> > >  		.acpi_op_start = 1,
> > > +		.acpi_op_match = 1,
> > >  	};
> > >  	struct acpi_device *device = NULL;
> > >  
> > > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
> > >  				      void *context, void **return_value)
> > >  {
> > >  	struct acpi_bus_ops *ops = context;
> > > +	struct acpi_device *device = NULL;
> > >  	int type;
> > >  	unsigned long long sta;
> > > -	struct acpi_device *device;
> > >  	acpi_status status;
> > >  	int result;
> > >  
> > > @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac
> > >  		return AE_CTRL_DEPTH;
> > >  	}
> > >  
> > > -	/*
> > > -	 * We may already have an acpi_device from a previous enumeration.  If
> > > -	 * so, we needn't add it again, but we may still have to start it.
> > > -	 */
> > > -	device = NULL;
> > >  	acpi_bus_get_device(handle, &device);
> > >  	if (ops->acpi_op_add && !device) {
> > > -		acpi_add_single_object(&device, handle, type, sta, ops);
> > > -		/* Is the device a known good platform device? */
> > > -		if (device
> > > -		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
> > > -			acpi_create_platform_device(device);
> > > -	}
> > > -
> > > -	if (!device)
> > > -		return AE_CTRL_DEPTH;
> > > +		struct acpi_bus_ops add_ops = *ops;
> > >  
> > > -	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> > > -		status = acpi_start_single_object(device);
> > > -		if (ACPI_FAILURE(status))
> > > +		add_ops.acpi_op_match = 0;
> > > +		acpi_add_single_object(&device, handle, type, sta, &add_ops);
> > > +		if (!device)
> > >  			return AE_CTRL_DEPTH;
> > > +
> > > +		device->bus_ops.acpi_op_match = 1;
> > >  	}
> > >  
> > >  	if (!*return_value)
> > >  		*return_value = device;
> > > +
> > >  	return AE_OK;
> > >  }
> > >  
> > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> > > +					void *context, void **not_used)
> > > +{
> > > +	struct acpi_bus_ops *ops = context;
> > > +	acpi_status status = AE_OK;
> > > +	struct acpi_device *device;
> > > +	unsigned long long sta_not_used;
> > > +	int type_not_used;
> > > +
> > > +	/*
> > > +	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
> > 
> > "ignore" seems duplicated. 
>  
> It is not.  This is supposed to mean that the errors previously ignored by
> acpi_bus_check_add() should be ignored here as well.

Oh, I see.  Thanks for the clarification.


> > > +	 * namespace walks prematurely.
> > > +	 */
> > > +	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> > > +		return AE_OK;
> > > +
> > > +	if (acpi_bus_get_device(handle, &device))
> > > +		return AE_CTRL_DEPTH;
> > > +
> > > +	if (ops->acpi_op_add) {
> > > +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> > > +			/* This is a known good platform device. */
> > > +			acpi_create_platform_device(device);
> > > +		} else {
> > > +			int ret = device_attach(&device->dev);
> > > +			acpi_hot_add_bind(device);
> > 
> > Since acpi_pci_root_add() is called by device_attach(), I think this
> > acpi_hot_add_bind() calls .bind() of a device at boot since its .bind()
> > may be set.  Is that correct?  If so, how does it coordinate with the
> > bind procedure in acpi_pci_bridge_scan()?
> 
> It actually doesn't.
> 
> However, the $subject patch doesn't change this particular aspect of the
> original behavior, because with it applied the PCI root bridge driver is still
> not present when the device_attach() above is executed for all objects in the
> given namespace scope, so the .bind() callbacks should all be empty.  In other
> words, it doesn't change the boot case.
> 
> It also reproduces the original behavior in the hotplug case which may not be
> correct.  Patch [2/6], however, kind of changes the boot case into the hotplug
> case and things start to get ugly.

Yes, I was concerned with the behavior when patch [2/6] applied.  It is
actually a good thing that this hotplug issue is now exposed in the boot
path.  This means that boot and hot-add paths are consistent.  So, we
just need to fix it.


> Well, what about calling acpi_hot_add_bind() from acpi_bus_check_add(),
> right after doing the acpi_add_single_object()?  It would avoid calling
> acpi_pci_bind() twice for the same device during root bridge hotplug too,
> because in that case acpi_pci_root_add() will be called after all of these
> acpi_hot_add_bind() calls.  At the same time if a single device is
> hot-added and its parent happens to have .bind() set, it will be run
> from acpi_bus_check_add().

I may be missing something here, but in case of root bridge hot-add, I
think acpi_pci_root_add() still calls .bind() after acpi_bus_check_add()
called it.  So, it's called twice, isn't it? 

We need to decide which module is responsible for calling .bind().  I
think it should be the ACPI scan module, not the ACPI PCI root bridge
driver, because:

 - bind() needs to be called when _ADR device is added.  The ACPI scan
module can scan any devices, while the PCI root driver can only scan
when it is added.
 - acpi_bus_remove() calls unbind() at hot-remove.  The same module
should be responsible for both bind() and unbind() handling.
 - It is cleaner to keep struct acpi_device_ops interface to be called
by the ACPI core.

So, I would propose the following changes.

 - Move the acpi_hot_add_bind() call back to the original place after
the device_attach() call.
 - Rename the name of acpi_hot_add_bind() to something like
acpi_bind_adr_device() since it is no longer hot-add only (and is
specific to _ADR devices).
 - Create its pair function, acpi_unbind_adr_device(), which is called
from acpi_bus_remove().  When a constructor interface is introduced, its
destructor should be introduced as well. 
 - Remove the binding procedure from acpi_pci_root_add().  This should
be done in patch [2/6].

Thanks,
-Toshi


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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 16:10         ` Toshi Kani
@ 2012-12-18 18:59           ` Yinghai Lu
  2012-12-18 20:48             ` Toshi Kani
  2012-12-18 22:05             ` Rafael J. Wysocki
  2012-12-18 21:57           ` Rafael J. Wysocki
  1 sibling, 2 replies; 88+ messages in thread
From: Yinghai Lu @ 2012-12-18 18:59 UTC (permalink / raw)
  To: Toshi Kani
  Cc: Rafael J. Wysocki, ACPI Devel Maling List, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Tue, Dec 18, 2012 at 8:10 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
>
> So, I would propose the following changes.
>
>  - Move the acpi_hot_add_bind() call back to the original place after
> the device_attach() call.
>  - Rename the name of acpi_hot_add_bind() to something like
> acpi_bind_adr_device() since it is no longer hot-add only (and is
> specific to _ADR devices).
>  - Create its pair function, acpi_unbind_adr_device(), which is called
> from acpi_bus_remove().  When a constructor interface is introduced, its
> destructor should be introduced as well.
>  - Remove the binding procedure from acpi_pci_root_add().  This should
> be done in patch [2/6].

i think we should put jiang four patches before Rafael's patches.

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

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 18:59           ` Yinghai Lu
@ 2012-12-18 20:48             ` Toshi Kani
  2012-12-18 21:11               ` Yinghai Lu
  2012-12-18 22:05             ` Rafael J. Wysocki
  1 sibling, 1 reply; 88+ messages in thread
From: Toshi Kani @ 2012-12-18 20:48 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Rafael J. Wysocki, ACPI Devel Maling List, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Tue, 2012-12-18 at 10:59 -0800, Yinghai Lu wrote:
> On Tue, Dec 18, 2012 at 8:10 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
> >
> > So, I would propose the following changes.
> >
> >  - Move the acpi_hot_add_bind() call back to the original place after
> > the device_attach() call.
> >  - Rename the name of acpi_hot_add_bind() to something like
> > acpi_bind_adr_device() since it is no longer hot-add only (and is
> > specific to _ADR devices).
> >  - Create its pair function, acpi_unbind_adr_device(), which is called
> > from acpi_bus_remove().  When a constructor interface is introduced, its
> > destructor should be introduced as well.
> >  - Remove the binding procedure from acpi_pci_root_add().  This should
> > be done in patch [2/6].
> 
> i think we should put jiang four patches before Rafael's patches.
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug

Thanks for the pointer!  Oh, I did not know that pci_dev gets removed
before acpi_bus_trim() is called...  I looked at Jiang's last two
patches for the bind update, and they look good to me.  

Thanks,
-Toshi


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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 20:48             ` Toshi Kani
@ 2012-12-18 21:11               ` Yinghai Lu
  0 siblings, 0 replies; 88+ messages in thread
From: Yinghai Lu @ 2012-12-18 21:11 UTC (permalink / raw)
  To: Toshi Kani
  Cc: Rafael J. Wysocki, ACPI Devel Maling List, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Tue, Dec 18, 2012 at 12:48 PM, Toshi Kani <toshi.kani@hp.com> wrote:
> On Tue, 2012-12-18 at 10:59 -0800, Yinghai Lu wrote:
>> On Tue, Dec 18, 2012 at 8:10 AM, Toshi Kani <toshi.kani@hp.com> wrote:
>> > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
>> >
>> > So, I would propose the following changes.
>> >
>> >  - Move the acpi_hot_add_bind() call back to the original place after
>> > the device_attach() call.
>> >  - Rename the name of acpi_hot_add_bind() to something like
>> > acpi_bind_adr_device() since it is no longer hot-add only (and is
>> > specific to _ADR devices).
>> >  - Create its pair function, acpi_unbind_adr_device(), which is called
>> > from acpi_bus_remove().  When a constructor interface is introduced, its
>> > destructor should be introduced as well.
>> >  - Remove the binding procedure from acpi_pci_root_add().  This should
>> > be done in patch [2/6].
>>
>> i think we should put jiang four patches before Rafael's patches.
>>
>> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug
>
> Thanks for the pointer!  Oh, I did not know that pci_dev gets removed
> before acpi_bus_trim() is called...

yes. that is
http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=commitdiff;h=8b4b836d8c56c290bc80ffa0b08b91fb3fe38867

> I looked at Jiang's last two
> patches for the bind update, and they look good to me.
>
> Thanks,
> -Toshi
>

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 16:10         ` Toshi Kani
  2012-12-18 18:59           ` Yinghai Lu
@ 2012-12-18 21:57           ` Rafael J. Wysocki
  2012-12-18 22:15             ` Toshi Kani
  1 sibling, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-18 21:57 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote:
> On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
> > On Monday, December 17, 2012 05:08:17 PM Toshi Kani wrote:
> > > On Thu, 2012-12-13 at 23:17 +0100, Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > 
> > > 
> > > (snip)
> > > 
> > > >  struct acpi_device_ops {
> > > > Index: linux/drivers/acpi/scan.c
> > > > ===================================================================
> > > > --- linux.orig/drivers/acpi/scan.c
> > > > +++ linux/drivers/acpi/scan.c
> > > > @@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
> > > >  	struct acpi_device *acpi_dev = to_acpi_device(dev);
> > > >  	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
> > > >  
> > > > -	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> > > > +	return acpi_dev->bus_ops.acpi_op_match
> > > > +		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
> > > >  }
> > > >  
> > > >  static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
> > > > @@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
> > > >  	return 0;
> > > >  }
> > > >  
> > > > +/*
> > > > + * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
> > > > + * @device: ACPI device node to bind.
> > > > + */
> > > > +static void acpi_hot_add_bind(struct acpi_device *device)
> > > > +{
> > > > +	if (device->flags.bus_address
> > > > +	    && device->parent && device->parent->ops.bind)
> > > > +		device->parent->ops.bind(device);
> > > > +}
> > > > +
> > > >  static int acpi_add_single_object(struct acpi_device **child,
> > > >  				  acpi_handle handle, int type,
> > > >  				  unsigned long long sta,
> > > > @@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
> > > >  
> > > >  	result = acpi_device_register(device);
> > > >  
> > > > -	/*
> > > > -	 * Bind _ADR-Based Devices when hot add
> > > > -	 */
> > > > -	if (device->flags.bus_address) {
> > > > -		if (device->parent && device->parent->ops.bind)
> > > > -			device->parent->ops.bind(device);
> > > > -	}
> > > 
> > > I think the original code above is hot-add only because ops.bind is not
> > > set at boot since the acpi_pci driver has not been registered yet.  It
> > > seems that acpi_pci_bridge_scan() called from acpi_pci_root_add() takes
> > > care of the binding.
> > 
> > Ah, I see the problem.  During boot the PCI root bridge driver is not present
> > yet when all struct acpi_device "devices" are registered, so their parents'
> > .bind() callbacks are all empty, so the code above has no effect.
> > 
> > But say we're doing a PCI root bridge hotplug, in which case the driver is
> > present, so acpi_pci_bind() will be executed both from acpi_pci_bridge_scan()
> > and from here, won't it?
> 
> Right.
> 
> 
> > OK, this needs to be addressed.
> > 
> > > This brings me a question for acpi_bus_probe_start() below...
> > > 
> > > 
> > > > +	if (device->bus_ops.acpi_op_match)
> > > > +		acpi_hot_add_bind(device);
> > > >  
> > > >  end:
> > > >  	if (!result) {
> > > > @@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
> > > >  	struct acpi_bus_ops ops = {
> > > >  		.acpi_op_add = 1,
> > > >  		.acpi_op_start = 1,
> > > > +		.acpi_op_match = 1,
> > > >  	};
> > > >  	struct acpi_device *device = NULL;
> > > >  
> > > > @@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
> > > >  				      void *context, void **return_value)
> > > >  {
> > > >  	struct acpi_bus_ops *ops = context;
> > > > +	struct acpi_device *device = NULL;
> > > >  	int type;
> > > >  	unsigned long long sta;
> > > > -	struct acpi_device *device;
> > > >  	acpi_status status;
> > > >  	int result;
> > > >  
> > > > @@ -1596,52 +1604,86 @@ static acpi_status acpi_bus_check_add(ac
> > > >  		return AE_CTRL_DEPTH;
> > > >  	}
> > > >  
> > > > -	/*
> > > > -	 * We may already have an acpi_device from a previous enumeration.  If
> > > > -	 * so, we needn't add it again, but we may still have to start it.
> > > > -	 */
> > > > -	device = NULL;
> > > >  	acpi_bus_get_device(handle, &device);
> > > >  	if (ops->acpi_op_add && !device) {
> > > > -		acpi_add_single_object(&device, handle, type, sta, ops);
> > > > -		/* Is the device a known good platform device? */
> > > > -		if (device
> > > > -		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
> > > > -			acpi_create_platform_device(device);
> > > > -	}
> > > > -
> > > > -	if (!device)
> > > > -		return AE_CTRL_DEPTH;
> > > > +		struct acpi_bus_ops add_ops = *ops;
> > > >  
> > > > -	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
> > > > -		status = acpi_start_single_object(device);
> > > > -		if (ACPI_FAILURE(status))
> > > > +		add_ops.acpi_op_match = 0;
> > > > +		acpi_add_single_object(&device, handle, type, sta, &add_ops);
> > > > +		if (!device)
> > > >  			return AE_CTRL_DEPTH;
> > > > +
> > > > +		device->bus_ops.acpi_op_match = 1;
> > > >  	}
> > > >  
> > > >  	if (!*return_value)
> > > >  		*return_value = device;
> > > > +
> > > >  	return AE_OK;
> > > >  }
> > > >  
> > > > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> > > > +					void *context, void **not_used)
> > > > +{
> > > > +	struct acpi_bus_ops *ops = context;
> > > > +	acpi_status status = AE_OK;
> > > > +	struct acpi_device *device;
> > > > +	unsigned long long sta_not_used;
> > > > +	int type_not_used;
> > > > +
> > > > +	/*
> > > > +	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
> > > 
> > > "ignore" seems duplicated. 
> >  
> > It is not.  This is supposed to mean that the errors previously ignored by
> > acpi_bus_check_add() should be ignored here as well.
> 
> Oh, I see.  Thanks for the clarification.
> 
> 
> > > > +	 * namespace walks prematurely.
> > > > +	 */
> > > > +	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> > > > +		return AE_OK;
> > > > +
> > > > +	if (acpi_bus_get_device(handle, &device))
> > > > +		return AE_CTRL_DEPTH;
> > > > +
> > > > +	if (ops->acpi_op_add) {
> > > > +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> > > > +			/* This is a known good platform device. */
> > > > +			acpi_create_platform_device(device);
> > > > +		} else {
> > > > +			int ret = device_attach(&device->dev);
> > > > +			acpi_hot_add_bind(device);
> > > 
> > > Since acpi_pci_root_add() is called by device_attach(), I think this
> > > acpi_hot_add_bind() calls .bind() of a device at boot since its .bind()
> > > may be set.  Is that correct?  If so, how does it coordinate with the
> > > bind procedure in acpi_pci_bridge_scan()?
> > 
> > It actually doesn't.
> > 
> > However, the $subject patch doesn't change this particular aspect of the
> > original behavior, because with it applied the PCI root bridge driver is still
> > not present when the device_attach() above is executed for all objects in the
> > given namespace scope, so the .bind() callbacks should all be empty.  In other
> > words, it doesn't change the boot case.
> > 
> > It also reproduces the original behavior in the hotplug case which may not be
> > correct.  Patch [2/6], however, kind of changes the boot case into the hotplug
> > case and things start to get ugly.
> 
> Yes, I was concerned with the behavior when patch [2/6] applied.  It is
> actually a good thing that this hotplug issue is now exposed in the boot
> path.  This means that boot and hot-add paths are consistent.  So, we
> just need to fix it.
> 
> 
> > Well, what about calling acpi_hot_add_bind() from acpi_bus_check_add(),
> > right after doing the acpi_add_single_object()?  It would avoid calling
> > acpi_pci_bind() twice for the same device during root bridge hotplug too,
> > because in that case acpi_pci_root_add() will be called after all of these
> > acpi_hot_add_bind() calls.  At the same time if a single device is
> > hot-added and its parent happens to have .bind() set, it will be run
> > from acpi_bus_check_add().
> 
> I may be missing something here, but in case of root bridge hot-add, I
> think acpi_pci_root_add() still calls .bind() after acpi_bus_check_add()
> called it.  So, it's called twice, isn't it? 

No, it isn't.  The reason is that the .bind pointers of all devices below the
root bridge are populated from within acpi_pci_root_add() and are NULL before
it is called.  Therefore they are NULL when acpi_bus_check_add() checks them. 

Of course, I'm referring to this patch:

https://patchwork.kernel.org/patch/1889821/

After this and [2/6] (https://patchwork.kernel.org/patch/1884701/) have been
applied, it is quite easy to verify that acpi_pci_bind() is called exactly once
for each PCI device during boot (just add a debug printk to that function) and
the same should happen during root bridge hotplug.

> We need to decide which module is responsible for calling .bind().  I
> think it should be the ACPI scan module, not the ACPI PCI root bridge
> driver, because:
>  - bind() needs to be called when _ADR device is added.  The ACPI scan
> module can scan any devices, while the PCI root driver can only scan
> when it is added.
>  - acpi_bus_remove() calls unbind() at hot-remove.  The same module
> should be responsible for both bind() and unbind() handling.
>  - It is cleaner to keep struct acpi_device_ops interface to be called
> by the ACPI core.

I agree with that. :-)

Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all.

> So, I would propose the following changes.
> 
>  - Move the acpi_hot_add_bind() call back to the original place after
> the device_attach() call.
>  - Rename the name of acpi_hot_add_bind() to something like
> acpi_bind_adr_device() since it is no longer hot-add only (and is
> specific to _ADR devices).
>  - Create its pair function, acpi_unbind_adr_device(), which is called
> from acpi_bus_remove().  When a constructor interface is introduced, its
> destructor should be introduced as well. 
>  - Remove the binding procedure from acpi_pci_root_add().  This should
> be done in patch [2/6].

Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind()
somewhere else and removing those things altogether?

Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 18:59           ` Yinghai Lu
  2012-12-18 20:48             ` Toshi Kani
@ 2012-12-18 22:05             ` Rafael J. Wysocki
  2012-12-19  1:57               ` Yinghai Lu
  1 sibling, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-18 22:05 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Toshi Kani, ACPI Devel Maling List, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Tuesday, December 18, 2012 10:59:46 AM Yinghai Lu wrote:
> On Tue, Dec 18, 2012 at 8:10 AM, Toshi Kani <toshi.kani@hp.com> wrote:
> > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
> >
> > So, I would propose the following changes.
> >
> >  - Move the acpi_hot_add_bind() call back to the original place after
> > the device_attach() call.
> >  - Rename the name of acpi_hot_add_bind() to something like
> > acpi_bind_adr_device() since it is no longer hot-add only (and is
> > specific to _ADR devices).
> >  - Create its pair function, acpi_unbind_adr_device(), which is called
> > from acpi_bus_remove().  When a constructor interface is introduced, its
> > destructor should be introduced as well.
> >  - Remove the binding procedure from acpi_pci_root_add().  This should
> > be done in patch [2/6].
> 
> i think we should put jiang four patches before Rafael's patches.
> 
> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug

Actually, I have something more radical than that in mind. :-)

Namely, we don't need to call the wakeup-related stuff from acpi_pci_bind() and
acpi_pci_unbind().  It's only there, because I did't find a better place for it
when I added it.

If we can set the ACPI handles of PCI devices in pci_scan_device(), which isn't
too difficult to do (I actually have a patch for that and it's not too invasive),
we can easily move the wakeup enabling stuff to pci_pm_init() and wakeup
disabling somewhere near pci_release_capabilities().

Then we are only left with the _PRT setup in there, but that could be done
as soon as in pci_scan_device() too, if I'm not mistaken.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 21:57           ` Rafael J. Wysocki
@ 2012-12-18 22:15             ` Toshi Kani
  2012-12-18 23:00               ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Toshi Kani @ 2012-12-18 22:15 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Tue, 2012-12-18 at 22:57 +0100, Rafael J. Wysocki wrote:
> On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote:
> > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
 :
> > We need to decide which module is responsible for calling .bind().  I
> > think it should be the ACPI scan module, not the ACPI PCI root bridge
> > driver, because:
> >  - bind() needs to be called when _ADR device is added.  The ACPI scan
> > module can scan any devices, while the PCI root driver can only scan
> > when it is added.
> >  - acpi_bus_remove() calls unbind() at hot-remove.  The same module
> > should be responsible for both bind() and unbind() handling.
> >  - It is cleaner to keep struct acpi_device_ops interface to be called
> > by the ACPI core.
> 
> I agree with that. :-)
> 
> Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all.
> 
> > So, I would propose the following changes.
> > 
> >  - Move the acpi_hot_add_bind() call back to the original place after
> > the device_attach() call.
> >  - Rename the name of acpi_hot_add_bind() to something like
> > acpi_bind_adr_device() since it is no longer hot-add only (and is
> > specific to _ADR devices).
> >  - Create its pair function, acpi_unbind_adr_device(), which is called
> > from acpi_bus_remove().  When a constructor interface is introduced, its
> > destructor should be introduced as well. 
> >  - Remove the binding procedure from acpi_pci_root_add().  This should
> > be done in patch [2/6].
> 
> Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind()
> somewhere else and removing those things altogether?

Sounds nice.  It will be bonus point if you can do that. :-)

Thanks,
-Toshi



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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 22:15             ` Toshi Kani
@ 2012-12-18 23:00               ` Rafael J. Wysocki
  2012-12-18 23:19                 ` Bjorn Helgaas
  0 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-18 23:00 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Tuesday, December 18, 2012 03:15:12 PM Toshi Kani wrote:
> On Tue, 2012-12-18 at 22:57 +0100, Rafael J. Wysocki wrote:
> > On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote:
> > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
>  :
> > > We need to decide which module is responsible for calling .bind().  I
> > > think it should be the ACPI scan module, not the ACPI PCI root bridge
> > > driver, because:
> > >  - bind() needs to be called when _ADR device is added.  The ACPI scan
> > > module can scan any devices, while the PCI root driver can only scan
> > > when it is added.
> > >  - acpi_bus_remove() calls unbind() at hot-remove.  The same module
> > > should be responsible for both bind() and unbind() handling.
> > >  - It is cleaner to keep struct acpi_device_ops interface to be called
> > > by the ACPI core.
> > 
> > I agree with that. :-)
> > 
> > Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all.
> > 
> > > So, I would propose the following changes.
> > > 
> > >  - Move the acpi_hot_add_bind() call back to the original place after
> > > the device_attach() call.
> > >  - Rename the name of acpi_hot_add_bind() to something like
> > > acpi_bind_adr_device() since it is no longer hot-add only (and is
> > > specific to _ADR devices).
> > >  - Create its pair function, acpi_unbind_adr_device(), which is called
> > > from acpi_bus_remove().  When a constructor interface is introduced, its
> > > destructor should be introduced as well. 
> > >  - Remove the binding procedure from acpi_pci_root_add().  This should
> > > be done in patch [2/6].
> > 
> > Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind()
> > somewhere else and removing those things altogether?
> 
> Sounds nice.  It will be bonus point if you can do that. :-)

I think I can, but I need a few more patches on top of what I've already posted
to do that.

I think that https://patchwork.kernel.org/patch/1889821/ and
https://patchwork.kernel.org/patch/1884701/ can stay as they are, since there's
some material on top of them already and I'll cut the new patches on top of all
that.  I'll repost the whole series some time later this week, stay tuned. :-)

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 23:00               ` Rafael J. Wysocki
@ 2012-12-18 23:19                 ` Bjorn Helgaas
  2012-12-19 11:13                   ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Bjorn Helgaas @ 2012-12-18 23:19 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Toshi Kani, ACPI Devel Maling List, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

On Tue, Dec 18, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Tuesday, December 18, 2012 03:15:12 PM Toshi Kani wrote:
>> On Tue, 2012-12-18 at 22:57 +0100, Rafael J. Wysocki wrote:
>> > On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote:
>> > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
>>  :
>> > > We need to decide which module is responsible for calling .bind().  I
>> > > think it should be the ACPI scan module, not the ACPI PCI root bridge
>> > > driver, because:
>> > >  - bind() needs to be called when _ADR device is added.  The ACPI scan
>> > > module can scan any devices, while the PCI root driver can only scan
>> > > when it is added.
>> > >  - acpi_bus_remove() calls unbind() at hot-remove.  The same module
>> > > should be responsible for both bind() and unbind() handling.
>> > >  - It is cleaner to keep struct acpi_device_ops interface to be called
>> > > by the ACPI core.
>> >
>> > I agree with that. :-)
>> >
>> > Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all.
>> >
>> > > So, I would propose the following changes.
>> > >
>> > >  - Move the acpi_hot_add_bind() call back to the original place after
>> > > the device_attach() call.
>> > >  - Rename the name of acpi_hot_add_bind() to something like
>> > > acpi_bind_adr_device() since it is no longer hot-add only (and is
>> > > specific to _ADR devices).
>> > >  - Create its pair function, acpi_unbind_adr_device(), which is called
>> > > from acpi_bus_remove().  When a constructor interface is introduced, its
>> > > destructor should be introduced as well.
>> > >  - Remove the binding procedure from acpi_pci_root_add().  This should
>> > > be done in patch [2/6].
>> >
>> > Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind()
>> > somewhere else and removing those things altogether?
>>
>> Sounds nice.  It will be bonus point if you can do that. :-)
>
> I think I can, but I need a few more patches on top of what I've already posted
> to do that.
>
> I think that https://patchwork.kernel.org/patch/1889821/ and
> https://patchwork.kernel.org/patch/1884701/ can stay as they are, since there's
> some material on top of them already and I'll cut the new patches on top of all
> that.  I'll repost the whole series some time later this week, stay tuned. :-)

I haven't follow this closely enough to give useful feedback, but I
trust that what you're doing is going in the right direction.

The only question I have right now is what I mentioned earlier on IRC,
namely, the idea of "binding" an ACPI handle or device to a pci_dev,
and whether there's a way to guarantee that the binding doesn't become
stale.  For example, if we bind pci_dev A to acpi_device B, I think we
essentially capture the pointer to B and store that pointer in A.
Obviously we want to know that the captured pointer in A remains valid
as long as A exists, but I don't know what assures us of that.

I don't think this is a new question; I have the same question about
the current code before your changes.  But it seems like you're
simplifying this area in a way that might make it easier to answer the
question.

Bjorn

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 22:05             ` Rafael J. Wysocki
@ 2012-12-19  1:57               ` Yinghai Lu
  0 siblings, 0 replies; 88+ messages in thread
From: Yinghai Lu @ 2012-12-19  1:57 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Toshi Kani, ACPI Devel Maling List, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Tue, Dec 18, 2012 at 2:05 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>>
>> i think we should put jiang four patches before Rafael's patches.
>>
>> http://git.kernel.org/?p=linux/kernel/git/yinghai/linux-yinghai.git;a=shortlog;h=refs/heads/for-pci-jiang-hotplug
>
> Actually, I have something more radical than that in mind. :-)
>
> Namely, we don't need to call the wakeup-related stuff from acpi_pci_bind() and
> acpi_pci_unbind().  It's only there, because I did't find a better place for it
> when I added it.
>
> If we can set the ACPI handles of PCI devices in pci_scan_device(), which isn't
> too difficult to do (I actually have a patch for that and it's not too invasive),
> we can easily move the wakeup enabling stuff to pci_pm_init() and wakeup
> disabling somewhere near pci_release_capabilities().

good, let's see how acpi handles could be be passed to pci devices.

Yinghai

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

* Re: [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-18 23:19                 ` Bjorn Helgaas
@ 2012-12-19 11:13                   ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-19 11:13 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Toshi Kani, ACPI Devel Maling List, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

On Tuesday, December 18, 2012 04:19:55 PM Bjorn Helgaas wrote:
> On Tue, Dec 18, 2012 at 4:00 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Tuesday, December 18, 2012 03:15:12 PM Toshi Kani wrote:
> >> On Tue, 2012-12-18 at 22:57 +0100, Rafael J. Wysocki wrote:
> >> > On Tuesday, December 18, 2012 09:10:41 AM Toshi Kani wrote:
> >> > > On Tue, 2012-12-18 at 02:48 +0100, Rafael J. Wysocki wrote:
> >>  :
> >> > > We need to decide which module is responsible for calling .bind().  I
> >> > > think it should be the ACPI scan module, not the ACPI PCI root bridge
> >> > > driver, because:
> >> > >  - bind() needs to be called when _ADR device is added.  The ACPI scan
> >> > > module can scan any devices, while the PCI root driver can only scan
> >> > > when it is added.
> >> > >  - acpi_bus_remove() calls unbind() at hot-remove.  The same module
> >> > > should be responsible for both bind() and unbind() handling.
> >> > >  - It is cleaner to keep struct acpi_device_ops interface to be called
> >> > > by the ACPI core.
> >> >
> >> > I agree with that. :-)
> >> >
> >> > Moreover, I don't think we need acpi_pci_bind() and acpi_pci_unbind() at all.
> >> >
> >> > > So, I would propose the following changes.
> >> > >
> >> > >  - Move the acpi_hot_add_bind() call back to the original place after
> >> > > the device_attach() call.
> >> > >  - Rename the name of acpi_hot_add_bind() to something like
> >> > > acpi_bind_adr_device() since it is no longer hot-add only (and is
> >> > > specific to _ADR devices).
> >> > >  - Create its pair function, acpi_unbind_adr_device(), which is called
> >> > > from acpi_bus_remove().  When a constructor interface is introduced, its
> >> > > destructor should be introduced as well.
> >> > >  - Remove the binding procedure from acpi_pci_root_add().  This should
> >> > > be done in patch [2/6].
> >> >
> >> > Well, what about moving the code from acpi_pci_bind()/acpi_pci_unbind()
> >> > somewhere else and removing those things altogether?
> >>
> >> Sounds nice.  It will be bonus point if you can do that. :-)
> >
> > I think I can, but I need a few more patches on top of what I've already posted
> > to do that.
> >
> > I think that https://patchwork.kernel.org/patch/1889821/ and
> > https://patchwork.kernel.org/patch/1884701/ can stay as they are, since there's
> > some material on top of them already and I'll cut the new patches on top of all
> > that.  I'll repost the whole series some time later this week, stay tuned. :-)
> 
> I haven't follow this closely enough to give useful feedback, but I
> trust that what you're doing is going in the right direction.

Cool. :-)

> The only question I have right now is what I mentioned earlier on IRC,
> namely, the idea of "binding" an ACPI handle or device to a pci_dev,
> and whether there's a way to guarantee that the binding doesn't become
> stale.  For example, if we bind pci_dev A to acpi_device B, I think we
> essentially capture the pointer to B and store that pointer in A.
> Obviously we want to know that the captured pointer in A remains valid
> as long as A exists, but I don't know what assures us of that.

This really is a bit more complicated.

First, what we store in A is not a pointer to B, but rather the corresponding
ACPICA handle, which is guaranteed to live longer that B itself.

Second, we not only store the B's handle in A, but also a pointer to A in B
(in the physical_node_list list).  Moreover, we create the "firmware_node"
sysfs file under A and a "physical_node" sysfs file under B.

All of that becomes invalid when either A or B is removed without notice.

For the removal of A we have acpi_platform_notify() that calls
acpi_unbind_one() which kills all of that stuff, so as long as A is removed
earlier than B, we have no problems.

For the removal of B, however, we seem to assume that if the device is
ejectable, there will be an ACPI driver bound to B (ie. the struct acpi_device)
that will take care of the removal of the physical nodes associated with it
before B itself is removed.  At least that's my understanding of the current
code.  Moreover, I'm not sure if this assumption is universally satisfied.

> I don't think this is a new question; I have the same question about
> the current code before your changes.  But it seems like you're
> simplifying this area in a way that might make it easier to answer the
> question.

Well, my patches are not likely to make things worse in this area. :-)

Anyway, I think we should make acpi_bus_scan(), or even acpi_bus_add() after
my changes, mutually exclusive with acpi_bus_trim(), because that will ensure
that we won't be removing ACPI device objects while setting them up (or the
other way around).  That would require us to redesign some ACPI drivers first,
though, because they call acpi_bus_trim() in their initialization code paths
(I don't really think they should be doing that).

Moreover, I think we should make the ACPI core trigger the removal of all
physical nodes (As) associated with the given ACPI node (B) after calling
device_release_driver() in acpi_bus_remove().  That will ensure that all
physical nodes are gone along with all the binding-related stuff (thanks to
acpi_platform_notify()) before the ACPI node is removed.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices
  2012-12-18  1:48       ` Rafael J. Wysocki
  2012-12-18 16:10         ` Toshi Kani
@ 2012-12-20  1:45         ` Rafael J. Wysocki
  2012-12-20  1:47           ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
                             ` (16 more replies)
  1 sibling, 17 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:45 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

Hi all,

I've finally cut the patches removing acpi_pci_bind() and acpi_pci_unbind(),
so I'm kind of ready to post the entire series reworking the ACPI namespace
scanning code.

Patches [1-6/16] are essentially these ones:

https://patchwork.kernel.org/patch/1889821/
https://patchwork.kernel.org/patch/1876481/
https://patchwork.kernel.org/patch/1876531/
https://patchwork.kernel.org/patch/1876571/
https://patchwork.kernel.org/patch/1876511/
https://patchwork.kernel.org/patch/1876401/

but [2-6/16] have been rebased on top of the first one.

Patches [7-12/16] are essentially these:

https://patchwork.kernel.org/patch/1884721/
https://patchwork.kernel.org/patch/1884701/
https://patchwork.kernel.org/patch/1884761/
https://patchwork.kernel.org/patch/1884731/
https://patchwork.kernel.org/patch/1884751/
https://patchwork.kernel.org/patch/1884661/

but they have been rebased on top of https://patchwork.kernel.org/patch/1889821/.
I added Yinghai's ACKs to them tentatively, although they are a bit different
from the previous versions.  The difference is not too important, however,
because the following patches finally remove the acpi_pci_bind()/acpi_pci_unbind()
stuff:

[13/16] Add .setup() and .cleanup() callbacks to struct acpi_bus_type.
[14/16] Rework the setup and cleanup of ACPI/PCI device wakeup.
[15/16] Move the _PRT setup and cleanup code to pci-acpi.c.
[16/16] Drop ACPI device .bind() and .unbind() callbacks.

This is done a bit differently than I thought it would be, mostly because the
_PRT-related operations require the "subordinate" pointers of bridges to be
populated.  I think it may be possible to simplify this further if that
requirement can be removed (I haven't looked into that).

In fact, patches [13-15/16] do not essentially depend on [1-12/16], only the
last one does.

The patches are on top of my master branch and I'm going to rebase them when
v3.8-rc1 is out.

There is a git tree you can pull them from at:

http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new

It's v3.7 with my master branch merged and the new patches on top.


Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
@ 2012-12-20  1:47           ` Rafael J. Wysocki
  2013-01-11 20:00             ` Mika Westerberg
  2012-12-20  1:48           ` [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
                             ` (15 subsequent siblings)
  16 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:47 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Split the ACPI namespace scanning for devices into two passes, such
that struct acpi_device objects are registerd in the first pass
without probing ACPI drivers and the drivers are probed against them
directly in the second pass.

There are two main reasons for doing that.

First, the ACPI PCI root bridge driver's .add() routine,
acpi_pci_root_add(), causes struct pci_dev objects to be created for
all PCI devices under the given root bridge.  Usually, there are
corresponding ACPI device nodes in the ACPI namespace for some of
those devices and therefore there should be "companion" struct
acpi_device objects to attach those struct pci_dev objects to.  These
struct acpi_device objects should exist when the corresponding
struct pci_dev objects are created, but that is only guaranteed
during boot and not during hotplug.  This leads to a number of
functional differences between the boot and the hotplug cases which
are not strictly necessary and make the code more complicated.

For example, this forces the ACPI PCI root bridge driver to defer the
registration of the just created struct pci_dev objects and to use a
special .start() callback routine, acpi_pci_root_start(), to make
sure that all of the "companion" struct acpi_device objects will be
present at PCI devices registration time during hotplug.

If those differences can be eliminated, we will be able to
consolidate the boot and hotplug code paths for the enumeration and
registration of PCI devices and to reduce the complexity of that
code quite a bit.

The second reason is that, in general, it should be possible to
resolve conflicts of resources assigned by the BIOS to different
devices represented by ACPI namespace nodes before any drivers bind
to them and before they are attached to "companion" objects
representing physical devices (such as struct pci_dev).  However, for
this purpose we first need to enumerate all ACPI device nodes in the
given namespace scope.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/scan.c     |  103 +++++++++++++++++++++++++++++++++---------------
 include/acpi/acpi_bus.h |    1 
 2 files changed, 73 insertions(+), 31 deletions(-)

Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -98,6 +98,7 @@ typedef void (*acpi_op_notify) (struct a
 struct acpi_bus_ops {
 	u32 acpi_op_add:1;
 	u32 acpi_op_start:1;
+	u32 acpi_op_match:1;
 };
 
 struct acpi_device_ops {
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -494,7 +494,8 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+	return acpi_dev->bus_ops.acpi_op_match
+		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
 static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -1418,6 +1419,17 @@ static int acpi_bus_remove(struct acpi_d
 	return 0;
 }
 
+/*
+ * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
+ * @device: ACPI device node to bind.
+ */
+static void acpi_hot_add_bind(struct acpi_device *device)
+{
+	if (device->flags.bus_address
+	    && device->parent && device->parent->ops.bind)
+		device->parent->ops.bind(device);
+}
+
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
 				  unsigned long long sta,
@@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct
 
 	result = acpi_device_register(device);
 
-	/*
-	 * Bind _ADR-Based Devices when hot add
-	 */
-	if (device->flags.bus_address) {
-		if (device->parent && device->parent->ops.bind)
-			device->parent->ops.bind(device);
-	}
+	if (device->bus_ops.acpi_op_match)
+		acpi_hot_add_bind(device);
 
 end:
 	if (!result) {
@@ -1522,6 +1529,7 @@ static void acpi_bus_add_power_resource(
 	struct acpi_bus_ops ops = {
 		.acpi_op_add = 1,
 		.acpi_op_start = 1,
+		.acpi_op_match = 1,
 	};
 	struct acpi_device *device = NULL;
 
@@ -1574,9 +1582,9 @@ static acpi_status acpi_bus_check_add(ac
 				      void *context, void **return_value)
 {
 	struct acpi_bus_ops *ops = context;
+	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
-	struct acpi_device *device;
 	acpi_status status;
 	int result;
 
@@ -1596,52 +1604,84 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_CTRL_DEPTH;
 	}
 
-	/*
-	 * We may already have an acpi_device from a previous enumeration.  If
-	 * so, we needn't add it again, but we may still have to start it.
-	 */
-	device = NULL;
 	acpi_bus_get_device(handle, &device);
 	if (ops->acpi_op_add && !device) {
-		acpi_add_single_object(&device, handle, type, sta, ops);
-		/* Is the device a known good platform device? */
-		if (device
-		    && !acpi_match_device_ids(device, acpi_platform_device_ids))
-			acpi_create_platform_device(device);
-	}
-
-	if (!device)
-		return AE_CTRL_DEPTH;
+		struct acpi_bus_ops add_ops = *ops;
 
-	if (ops->acpi_op_start && !(ops->acpi_op_add)) {
-		status = acpi_start_single_object(device);
-		if (ACPI_FAILURE(status))
+		add_ops.acpi_op_match = 0;
+		acpi_add_single_object(&device, handle, type, sta, &add_ops);
+		if (!device)
 			return AE_CTRL_DEPTH;
+
+		device->bus_ops.acpi_op_match = 1;
+		acpi_hot_add_bind(device);
 	}
 
 	if (!*return_value)
 		*return_value = device;
+
 	return AE_OK;
 }
 
+static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
+					void *context, void **not_used)
+{
+	struct acpi_bus_ops *ops = context;
+	acpi_status status = AE_OK;
+	struct acpi_device *device;
+	unsigned long long sta_not_used;
+	int type_not_used;
+
+	/*
+	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+	 * namespace walks prematurely.
+	 */
+	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+		return AE_OK;
+
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
+
+	if (ops->acpi_op_add) {
+		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+			/* This is a known good platform device. */
+			acpi_create_platform_device(device);
+		} else if (device_attach(&device->dev)) {
+			status = AE_CTRL_DEPTH;
+		}
+	} else if (ops->acpi_op_start) {
+		if (ACPI_FAILURE(acpi_start_single_object(device)))
+			status = AE_CTRL_DEPTH;
+	}
+	return status;
+}
+
 static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
 			 struct acpi_device **child)
 {
-	acpi_status status;
 	void *device = NULL;
+	acpi_status status;
+	int ret = -ENODEV;
 
 	status = acpi_bus_check_add(handle, 0, ops, &device);
 	if (ACPI_SUCCESS(status))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
 				    acpi_bus_check_add, NULL, ops, &device);
 
+	if (!device)
+		goto out;
+
+	ret = 0;
+	status = acpi_bus_probe_start(handle, 0, ops, NULL);
+	if (ACPI_SUCCESS(status))
+		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+				    acpi_bus_probe_start, NULL, ops, NULL);
+
+ out:
 	if (child)
 		*child = device;
 
-	if (device)
-		return 0;
-	else
-		return -ENODEV;
+	return ret;
 }
 
 /*
@@ -1752,6 +1792,7 @@ static int acpi_bus_scan_fixed(void)
 	memset(&ops, 0, sizeof(ops));
 	ops.acpi_op_add = 1;
 	ops.acpi_op_start = 1;
+	ops.acpi_op_match = 1;
 
 	/*
 	 * Enumerate all fixed-feature devices.


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

* [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
  2012-12-20  1:47           ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
@ 2012-12-20  1:48           ` Rafael J. Wysocki
  2012-12-20  1:49           ` [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
                             ` (14 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:48 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Instead of running acpi_pci_root_init() from a separate subsys
initcall, call it directly from acpi_scan_init() before scanning the
ACPI namespace for the first time, so that the PCI root bridge
driver's .add() routine, acpi_pci_root_start(), is always run
before binding ACPI drivers or attaching "companion" device objects
to struct acpi_device objects below the root bridge's device node in
the ACPI namespace.

The first, simpler reason for doing this is that it makes the
situation during boot more similar to the situation during hotplug,
in which the ACPI PCI root bridge driver is always present.

The second reason is that acpi_pci_root_init() causes struct pci_dev
objects to be created for all PCI devices below the bridge and
these objects may be necessary for whatever is done with the other
ACPI device nodes in that namespace scope.  For example, devices
created by acpi_create_platform_device() sometimes may need to be
added to the device hierarchy as children of PCI bridges.  For this
purpose, however, the struct pci_dev objects representing those
bridges need to exist before the platform devices in question are
registered.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/internal.h |    1 +
 drivers/acpi/pci_root.c |    4 +---
 drivers/acpi/scan.c     |    1 +
 3 files changed, 3 insertions(+), 3 deletions(-)

Index: linux/drivers/acpi/internal.h
===================================================================
--- linux.orig/drivers/acpi/internal.h
+++ linux/drivers/acpi/internal.h
@@ -67,6 +67,7 @@ struct acpi_ec {
 
 extern struct acpi_ec *first_ec;
 
+int acpi_pci_root_init(void);
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
 int acpi_boot_ec_enable(void);
Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c
+++ linux/drivers/acpi/pci_root.c
@@ -674,7 +674,7 @@ static int acpi_pci_root_remove(struct a
 	return 0;
 }
 
-static int __init acpi_pci_root_init(void)
+int __init acpi_pci_root_init(void)
 {
 	acpi_hest_init();
 
@@ -687,5 +687,3 @@ static int __init acpi_pci_root_init(voi
 
 	return 0;
 }
-
-subsys_initcall(acpi_pci_root_init);
Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1831,6 +1831,7 @@ int __init acpi_scan_init(void)
 	}
 
 	acpi_power_init();
+	acpi_pci_root_init();
 
 	/*
 	 * Enumerate devices in the ACPI namespace.


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

* [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
  2012-12-20  1:47           ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
  2012-12-20  1:48           ` [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
@ 2012-12-20  1:49           ` Rafael J. Wysocki
  2012-12-20  1:50           ` [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
                             ` (13 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:49 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The current ACPI namespace scanning code suggests that acpi_bus_add()
and acpi_bus_start() share some code.  In fact, however, they are
completely different code paths (except for the initial checks), so
refactor the code to make that distinction visibly clear.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/scan.c |   63 ++++++++++++++++++++++++++++------------------------
 1 file changed, 35 insertions(+), 28 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1623,10 +1623,9 @@ static acpi_status acpi_bus_check_add(ac
 	return AE_OK;
 }
 
-static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
-					void *context, void **not_used)
+static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
+					  void *not_used, void **ret_not_used)
 {
-	struct acpi_bus_ops *ops = context;
 	acpi_status status = AE_OK;
 	struct acpi_device *device;
 	unsigned long long sta_not_used;
@@ -1642,16 +1641,11 @@ static acpi_status acpi_bus_probe_start(
 	if (acpi_bus_get_device(handle, &device))
 		return AE_CTRL_DEPTH;
 
-	if (ops->acpi_op_add) {
-		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
-			/* This is a known good platform device. */
-			acpi_create_platform_device(device);
-		} else if (device_attach(&device->dev)) {
-			status = AE_CTRL_DEPTH;
-		}
-	} else if (ops->acpi_op_start) {
-		if (ACPI_FAILURE(acpi_start_single_object(device)))
-			status = AE_CTRL_DEPTH;
+	if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+		/* This is a known good platform device. */
+		acpi_create_platform_device(device);
+	} else if (device_attach(&device->dev)) {
+		status = AE_CTRL_DEPTH;
 	}
 	return status;
 }
@@ -1672,10 +1666,10 @@ static int acpi_bus_scan(acpi_handle han
 		goto out;
 
 	ret = 0;
-	status = acpi_bus_probe_start(handle, 0, ops, NULL);
+	status = acpi_bus_device_attach(handle, 0, NULL, NULL);
 	if (ACPI_SUCCESS(status))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_probe_start, NULL, ops, NULL);
+				    acpi_bus_device_attach, NULL, NULL, NULL);
 
  out:
 	if (child)
@@ -1700,31 +1694,44 @@ int
 acpi_bus_add(struct acpi_device **child,
 	     struct acpi_device *parent, acpi_handle handle, int type)
 {
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
+	struct acpi_bus_ops ops = { .acpi_op_add = 1, };
 
 	return acpi_bus_scan(handle, &ops, child);
 }
 EXPORT_SYMBOL(acpi_bus_add);
 
-int acpi_bus_start(struct acpi_device *device)
+static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl,
+					 void *not_used, void **ret_not_used)
 {
-	struct acpi_bus_ops ops;
-	int result;
+	struct acpi_device *device;
+	unsigned long long sta_not_used;
+	int type_not_used;
 
+	/*
+	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+	 * namespace walks prematurely.
+	 */
+	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+		return AE_OK;
+
+	if (acpi_bus_get_device(handle, &device))
+		return AE_CTRL_DEPTH;
+
+	return acpi_start_single_object(device);
+}
+
+int acpi_bus_start(struct acpi_device *device)
+{
 	if (!device)
 		return -EINVAL;
 
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_start = 1;
-
-	result = acpi_bus_scan(device->handle, &ops, NULL);
+	if (ACPI_SUCCESS(acpi_start_single_object(device)))
+		acpi_walk_namespace(ACPI_TYPE_ANY, device->handle,
+				    ACPI_UINT32_MAX, acpi_bus_start_device,
+				    NULL, NULL, NULL);
 
 	acpi_update_all_gpes();
-
-	return result;
+	return 0;
 }
 EXPORT_SYMBOL(acpi_bus_start);
 


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

* [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (2 preceding siblings ...)
  2012-12-20  1:49           ` [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
@ 2012-12-20  1:50           ` Rafael J. Wysocki
  2012-12-20  1:50           ` [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
                             ` (12 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:50 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Objects of type struct acpi_bus_ops are currently used to pass
information between different parts of the ACPI namespace scanning
code, sometimes in quite convoluted ways.  It turns out that that
is not necessary in some cases, so simplify the code by reducing
the utilization of struct acpi_bus_ops objects where clearly
possible.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/scan.c |   40 ++++++++++++++++------------------------
 1 file changed, 16 insertions(+), 24 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1527,7 +1527,6 @@ end:
 static void acpi_bus_add_power_resource(acpi_handle handle)
 {
 	struct acpi_bus_ops ops = {
-		.acpi_op_add = 1,
 		.acpi_op_start = 1,
 		.acpi_op_match = 1,
 	};
@@ -1581,7 +1580,6 @@ static int acpi_bus_type_and_status(acpi
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
 				      void *context, void **return_value)
 {
-	struct acpi_bus_ops *ops = context;
 	struct acpi_device *device = NULL;
 	int type;
 	unsigned long long sta;
@@ -1605,11 +1603,13 @@ static acpi_status acpi_bus_check_add(ac
 	}
 
 	acpi_bus_get_device(handle, &device);
-	if (ops->acpi_op_add && !device) {
-		struct acpi_bus_ops add_ops = *ops;
+	if (!device) {
+		struct acpi_bus_ops ops = {
+			.acpi_op_start = !!context,
+			.acpi_op_match = 0,
+		};
 
-		add_ops.acpi_op_match = 0;
-		acpi_add_single_object(&device, handle, type, sta, &add_ops);
+		acpi_add_single_object(&device, handle, type, sta, &ops);
 		if (!device)
 			return AE_CTRL_DEPTH;
 
@@ -1650,17 +1650,18 @@ static acpi_status acpi_bus_device_attac
 	return status;
 }
 
-static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
+static int acpi_bus_scan(acpi_handle handle, bool start,
 			 struct acpi_device **child)
 {
 	void *device = NULL;
 	acpi_status status;
 	int ret = -ENODEV;
 
-	status = acpi_bus_check_add(handle, 0, ops, &device);
+	status = acpi_bus_check_add(handle, 0, (void *)start, &device);
 	if (ACPI_SUCCESS(status))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_check_add, NULL, ops, &device);
+				    acpi_bus_check_add, NULL, (void *)start,
+				    &device);
 
 	if (!device)
 		goto out;
@@ -1694,9 +1695,7 @@ int
 acpi_bus_add(struct acpi_device **child,
 	     struct acpi_device *parent, acpi_handle handle, int type)
 {
-	struct acpi_bus_ops ops = { .acpi_op_add = 1, };
-
-	return acpi_bus_scan(handle, &ops, child);
+	return acpi_bus_scan(handle, false, child);
 }
 EXPORT_SYMBOL(acpi_bus_add);
 
@@ -1794,12 +1793,10 @@ static int acpi_bus_scan_fixed(void)
 {
 	int result = 0;
 	struct acpi_device *device = NULL;
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
-	ops.acpi_op_start = 1;
-	ops.acpi_op_match = 1;
+	struct acpi_bus_ops ops = {
+		.acpi_op_start = 1,
+		.acpi_op_match = 1,
+	};
 
 	/*
 	 * Enumerate all fixed-feature devices.
@@ -1825,11 +1822,6 @@ static int acpi_bus_scan_fixed(void)
 int __init acpi_scan_init(void)
 {
 	int result;
-	struct acpi_bus_ops ops;
-
-	memset(&ops, 0, sizeof(ops));
-	ops.acpi_op_add = 1;
-	ops.acpi_op_start = 1;
 
 	result = bus_register(&acpi_bus_type);
 	if (result) {
@@ -1843,7 +1835,7 @@ int __init acpi_scan_init(void)
 	/*
 	 * Enumerate devices in the ACPI namespace.
 	 */
-	result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
+	result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root);
 
 	if (!result)
 		result = acpi_bus_scan_fixed();


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

* [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (3 preceding siblings ...)
  2012-12-20  1:50           ` [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
@ 2012-12-20  1:50           ` Rafael J. Wysocki
  2012-12-20  1:51           ` [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
                             ` (11 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:50 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Notice that one member of struct acpi_bus_ops, acpi_op_add, is not
used anywhere any more and the relationship between its remaining
members, acpi_op_match and acpi_op_start, is such that it doesn't
make sense to set the latter without setting the former at the same
time.  Therefore, replace struct acpi_bus_ops with new a enum type,
enum acpi_bus_add_type, with three values, ACPI_BUS_ADD_BASIC,
ACPI_BUS_ADD_MATCH, ACPI_BUS_ADD_START, corresponding to
both acpi_op_match and acpi_op_start unset, acpi_op_match set and
acpi_op_start unset, and both acpi_op_match and acpi_op_start set,
respectively.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/scan.c     |   35 ++++++++++++-----------------------
 include/acpi/acpi_bus.h |   15 ++++++++-------
 2 files changed, 20 insertions(+), 30 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -494,7 +494,7 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return acpi_dev->bus_ops.acpi_op_match
+	return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH
 		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
@@ -580,7 +580,7 @@ static int acpi_device_probe(struct devi
 
 	ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
 	if (!ret) {
-		if (acpi_dev->bus_ops.acpi_op_start)
+		if (acpi_dev->add_type == ACPI_BUS_ADD_START)
 			acpi_start_single_object(acpi_dev);
 
 		if (acpi_drv->ops.notify) {
@@ -1433,7 +1433,7 @@ static void acpi_hot_add_bind(struct acp
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
 				  unsigned long long sta,
-				  struct acpi_bus_ops *ops)
+				  enum acpi_bus_add_type add_type)
 {
 	int result;
 	struct acpi_device *device;
@@ -1449,7 +1449,7 @@ static int acpi_add_single_object(struct
 	device->device_type = type;
 	device->handle = handle;
 	device->parent = acpi_bus_get_parent(handle);
-	device->bus_ops = *ops; /* workround for not call .start */
+	device->add_type = add_type;
 	STRUCT_TO_INT(device->status) = sta;
 
 	acpi_device_get_busid(device);
@@ -1502,7 +1502,7 @@ static int acpi_add_single_object(struct
 
 	result = acpi_device_register(device);
 
-	if (device->bus_ops.acpi_op_match)
+	if (device->add_type >= ACPI_BUS_ADD_MATCH)
 		acpi_hot_add_bind(device);
 
 end:
@@ -1526,16 +1526,12 @@ end:
 
 static void acpi_bus_add_power_resource(acpi_handle handle)
 {
-	struct acpi_bus_ops ops = {
-		.acpi_op_start = 1,
-		.acpi_op_match = 1,
-	};
 	struct acpi_device *device = NULL;
 
 	acpi_bus_get_device(handle, &device);
 	if (!device)
 		acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
-					ACPI_STA_DEFAULT, &ops);
+					ACPI_STA_DEFAULT, ACPI_BUS_ADD_START);
 }
 
 static int acpi_bus_type_and_status(acpi_handle handle, int *type,
@@ -1604,16 +1600,13 @@ static acpi_status acpi_bus_check_add(ac
 
 	acpi_bus_get_device(handle, &device);
 	if (!device) {
-		struct acpi_bus_ops ops = {
-			.acpi_op_start = !!context,
-			.acpi_op_match = 0,
-		};
-
-		acpi_add_single_object(&device, handle, type, sta, &ops);
+		acpi_add_single_object(&device, handle, type, sta,
+				       ACPI_BUS_ADD_BASIC);
 		if (!device)
 			return AE_CTRL_DEPTH;
 
-		device->bus_ops.acpi_op_match = 1;
+		device->add_type = context ?
+					ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
 		acpi_hot_add_bind(device);
 	}
 
@@ -1793,10 +1786,6 @@ static int acpi_bus_scan_fixed(void)
 {
 	int result = 0;
 	struct acpi_device *device = NULL;
-	struct acpi_bus_ops ops = {
-		.acpi_op_start = 1,
-		.acpi_op_match = 1,
-	};
 
 	/*
 	 * Enumerate all fixed-feature devices.
@@ -1805,7 +1794,7 @@ static int acpi_bus_scan_fixed(void)
 		result = acpi_add_single_object(&device, NULL,
 						ACPI_BUS_TYPE_POWER_BUTTON,
 						ACPI_STA_DEFAULT,
-						&ops);
+						ACPI_BUS_ADD_START);
 		device_init_wakeup(&device->dev, true);
 	}
 
@@ -1813,7 +1802,7 @@ static int acpi_bus_scan_fixed(void)
 		result = acpi_add_single_object(&device, NULL,
 						ACPI_BUS_TYPE_SLEEP_BUTTON,
 						ACPI_STA_DEFAULT,
-						&ops);
+						ACPI_BUS_ADD_START);
 	}
 
 	return result;
Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -63,6 +63,13 @@ acpi_get_physical_device_location(acpi_h
 #define ACPI_BUS_FILE_ROOT	"acpi"
 extern struct proc_dir_entry *acpi_root_dir;
 
+enum acpi_bus_add_type {
+	ACPI_BUS_ADD_BASIC = 0,
+	ACPI_BUS_ADD_MATCH,
+	ACPI_BUS_ADD_START,
+	ACPI_BUS_ADD_TYPE_COUNT
+};
+
 enum acpi_bus_removal_type {
 	ACPI_BUS_REMOVAL_NORMAL = 0,
 	ACPI_BUS_REMOVAL_EJECT,
@@ -95,12 +102,6 @@ typedef int (*acpi_op_bind) (struct acpi
 typedef int (*acpi_op_unbind) (struct acpi_device * device);
 typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
 
-struct acpi_bus_ops {
-	u32 acpi_op_add:1;
-	u32 acpi_op_start:1;
-	u32 acpi_op_match:1;
-};
-
 struct acpi_device_ops {
 	acpi_op_add add;
 	acpi_op_remove remove;
@@ -284,7 +285,7 @@ struct acpi_device {
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
-	struct acpi_bus_ops bus_ops;	/* workaround for different code path for hotplug */
+	enum acpi_bus_add_type add_type;	/* how to handle adding */
 	enum acpi_bus_removal_type removal_type;	/* indicate for different removal type */
 	u8 physical_node_count;
 	struct list_head physical_node_list;


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

* [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add()
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (4 preceding siblings ...)
  2012-12-20  1:50           ` [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
@ 2012-12-20  1:51           ` Rafael J. Wysocki
  2012-12-20  1:52           ` [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() Rafael J. Wysocki
                             ` (10 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:51 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>


If acpi_bus_check_add() is called for a handle already having an
existing struct acpi_device object attached, it is not necessary to
check the type and status of the device correspondig to it, so
change the ordering of acpi_bus_check_add() to avoid that.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/scan.c |   18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1582,6 +1582,10 @@ static acpi_status acpi_bus_check_add(ac
 	acpi_status status;
 	int result;
 
+	acpi_bus_get_device(handle, &device);
+	if (device)
+		goto out;
+
 	result = acpi_bus_type_and_status(handle, &type, &sta);
 	if (result)
 		return AE_OK;
@@ -1598,18 +1602,14 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_CTRL_DEPTH;
 	}
 
-	acpi_bus_get_device(handle, &device);
-	if (!device) {
-		acpi_add_single_object(&device, handle, type, sta,
-				       ACPI_BUS_ADD_BASIC);
-		if (!device)
-			return AE_CTRL_DEPTH;
+	acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC);
+	if (!device)
+		return AE_CTRL_DEPTH;
 
-		device->add_type = context ?
-					ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
-		acpi_hot_add_bind(device);
-	}
+	device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
+	acpi_hot_add_bind(device);
 
+ out:
 	if (!*return_value)
 		*return_value = device;
 


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

* [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add()
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (5 preceding siblings ...)
  2012-12-20  1:51           ` [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
@ 2012-12-20  1:52           ` Rafael J. Wysocki
  2012-12-20  1:53           ` [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start() Rafael J. Wysocki
                             ` (9 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:52 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Move the code from the ACPI PCI root bridge's .start() callback
routine, acpi_pci_root_start(), directly into acpi_pci_root_add()
and drop acpi_pci_root_start().

It is safe to do that, because it is now always guaranteed that
when struct pci_dev objects are created, their companion struct
acpi_device objects are already present, so it is not necessary to
wait for them to be created before calling pci_bus_add_devices().

This change was previously proposed in a different form by
Yinghai Lu.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/pci_root.c |   26 ++++++++------------------
 1 file changed, 8 insertions(+), 18 deletions(-)

Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c
+++ linux/drivers/acpi/pci_root.c
@@ -47,7 +47,6 @@ ACPI_MODULE_NAME("pci_root");
 #define ACPI_PCI_ROOT_DEVICE_NAME	"PCI Root Bridge"
 static int acpi_pci_root_add(struct acpi_device *device);
 static int acpi_pci_root_remove(struct acpi_device *device, int type);
-static int acpi_pci_root_start(struct acpi_device *device);
 
 #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
 				| OSC_ACTIVE_STATE_PWR_SUPPORT \
@@ -67,7 +66,6 @@ static struct acpi_driver acpi_pci_root_
 	.ops = {
 		.add = acpi_pci_root_add,
 		.remove = acpi_pci_root_remove,
-		.start = acpi_pci_root_start,
 		},
 };
 
@@ -453,6 +451,7 @@ static int __devinit acpi_pci_root_add(s
 	struct acpi_pci_root *root;
 	acpi_handle handle;
 	struct acpi_device *child;
+	struct acpi_pci_driver *driver;
 	u32 flags, base_flags;
 
 	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
@@ -628,6 +627,13 @@ static int __devinit acpi_pci_root_add(s
 	if (device->wakeup.flags.run_wake)
 		device_set_run_wake(root->bus->bridge, true);
 
+	mutex_lock(&acpi_pci_root_lock);
+	list_for_each_entry(driver, &acpi_pci_drivers, node)
+		if (driver->add)
+			driver->add(root);
+	mutex_unlock(&acpi_pci_root_lock);
+
+	pci_bus_add_devices(root->bus);
 	return 0;
 
 out_del_root:
@@ -639,22 +645,6 @@ end:
 	return result;
 }
 
-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);
-	mutex_unlock(&acpi_pci_root_lock);
-
-	pci_bus_add_devices(root->bus);
-
-	return 0;
-}
-
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);


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

* [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start()
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (6 preceding siblings ...)
  2012-12-20  1:52           ` [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() Rafael J. Wysocki
@ 2012-12-20  1:53           ` Rafael J. Wysocki
  2012-12-20  1:54           ` [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used Rafael J. Wysocki
                             ` (8 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:53 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The ACPI PCI root bridge driver was the only ACPI driver implementing
the .start() callback, which isn't used by any ACPI drivers any more
now.

For this reason, acpi_start_single_object() has no purpose any more,
so remove it and all references to it.  Also remove
acpi_bus_start_device(), whose only purpose was to call
acpi_start_single_object().

Moreover, since after the removal of acpi_bus_start_device() the
only purpose of acpi_bus_start() remains to call
acpi_update_all_gpes(), move that into acpi_bus_add() and drop
acpi_bus_start() too, remove its header from acpi_bus.h and
update all of its former users accordingly.

This change was previously proposed in a different from by
Yinghai Lu.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/container.c           |   16 +-------
 drivers/acpi/scan.c                |   66 ++++---------------------------------
 drivers/pci/hotplug/acpiphp_glue.c |    4 --
 drivers/pci/hotplug/sgi_hotplug.c  |    2 -
 include/acpi/acpi_bus.h            |    1 
 5 files changed, 12 insertions(+), 77 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -612,7 +612,6 @@ static void acpi_device_remove_notify_ha
 }
 
 static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *);
-static int acpi_start_single_object(struct acpi_device *);
 static int acpi_device_probe(struct device * dev)
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -621,9 +620,6 @@ static int acpi_device_probe(struct devi
 
 	ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
 	if (!ret) {
-		if (acpi_dev->add_type == ACPI_BUS_ADD_START)
-			acpi_start_single_object(acpi_dev);
-
 		if (acpi_drv->ops.notify) {
 			ret = acpi_device_install_notify_handler(acpi_dev);
 			if (ret) {
@@ -802,24 +798,6 @@ acpi_bus_driver_init(struct acpi_device
 	return 0;
 }
 
-static int acpi_start_single_object(struct acpi_device *device)
-{
-	int result = 0;
-	struct acpi_driver *driver;
-
-
-	if (!(driver = device->driver))
-		return 0;
-
-	if (driver->ops.start) {
-		result = driver->ops.start(device);
-		if (result && driver->ops.remove)
-			driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
-	}
-
-	return result;
-}
-
 /**
  * acpi_bus_register_driver - register a driver with the ACPI bus
  * @driver: driver being registered
@@ -1714,59 +1692,31 @@ static int acpi_bus_scan(acpi_handle han
 }
 
 /*
- * acpi_bus_add and acpi_bus_start
+ * acpi_bus_add
  *
  * scan a given ACPI tree and (probably recently hot-plugged)
- * create and add or starts found devices.
+ * create and add found devices.
  *
  * If no devices were found -ENODEV is returned which does not
  * mean that this is a real error, there just have been no suitable
  * ACPI objects in the table trunk from which the kernel could create
- * a device and add/start an appropriate driver.
+ * a device and add an appropriate driver.
  */
 
 int
 acpi_bus_add(struct acpi_device **child,
 	     struct acpi_device *parent, acpi_handle handle, int type)
 {
-	return acpi_bus_scan(handle, false, child);
-}
-EXPORT_SYMBOL(acpi_bus_add);
-
-static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl,
-					 void *not_used, void **ret_not_used)
-{
-	struct acpi_device *device;
-	unsigned long long sta_not_used;
-	int type_not_used;
-
-	/*
-	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
-	 * namespace walks prematurely.
-	 */
-	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
-		return AE_OK;
-
-	if (acpi_bus_get_device(handle, &device))
-		return AE_CTRL_DEPTH;
-
-	return acpi_start_single_object(device);
-}
-
-int acpi_bus_start(struct acpi_device *device)
-{
-	if (!device)
-		return -EINVAL;
+	int err;
 
-	if (ACPI_SUCCESS(acpi_start_single_object(device)))
-		acpi_walk_namespace(ACPI_TYPE_ANY, device->handle,
-				    ACPI_UINT32_MAX, acpi_bus_start_device,
-				    NULL, NULL, NULL);
+	err = acpi_bus_scan(handle, false, child);
+	if (err)
+		return err;
 
 	acpi_update_all_gpes();
 	return 0;
 }
-EXPORT_SYMBOL(acpi_bus_start);
+EXPORT_SYMBOL(acpi_bus_add);
 
 int acpi_bus_trim(struct acpi_device *start, int rmdevice)
 {
Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -402,7 +402,6 @@ int acpi_bus_add(struct acpi_device **ch
 		 acpi_handle handle, int type);
 void acpi_bus_hot_remove_device(void *context);
 int acpi_bus_trim(struct acpi_device *start, int rmdevice);
-int acpi_bus_start(struct acpi_device *device);
 acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);
 int acpi_match_device_ids(struct acpi_device *device,
 			  const struct acpi_device_id *ids);
Index: linux/drivers/pci/hotplug/sgi_hotplug.c
===================================================================
--- linux.orig/drivers/pci/hotplug/sgi_hotplug.c
+++ linux/drivers/pci/hotplug/sgi_hotplug.c
@@ -457,8 +457,6 @@ static int enable_slot(struct hotplug_sl
 					       ret, (int)(adr>>16),
 					       (int)(adr&0xffff));
 					/* try to continue on */
-				} else {
-					acpi_bus_start(device);
 				}
 			}
 		}
Index: linux/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux/drivers/pci/hotplug/acpiphp_glue.c
@@ -759,7 +759,6 @@ static int acpiphp_bus_add(struct acpiph
 			-ret_val);
 		goto acpiphp_bus_add_out;
 	}
-	ret_val = acpi_bus_start(device);
 
 acpiphp_bus_add_out:
 	return ret_val;
@@ -1148,8 +1147,7 @@ static void handle_bridge_insertion(acpi
 		err("cannot add bridge to acpi list\n");
 		return;
 	}
-	if (!acpiphp_configure_bridge(handle) &&
-		!acpi_bus_start(device))
+	if (!acpiphp_configure_bridge(handle))
 		add_bridge(handle);
 	else
 		err("cannot configure and start bridge\n");
Index: linux/drivers/acpi/container.c
===================================================================
--- linux.orig/drivers/acpi/container.c
+++ linux/drivers/acpi/container.c
@@ -139,24 +139,14 @@ static int container_device_add(struct a
 {
 	acpi_handle phandle;
 	struct acpi_device *pdev;
-	int result;
 
-
-	if (acpi_get_parent(handle, &phandle)) {
-		return -ENODEV;
-	}
-
-	if (acpi_bus_get_device(phandle, &pdev)) {
+	if (acpi_get_parent(handle, &phandle))
 		return -ENODEV;
-	}
 
-	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) {
+	if (acpi_bus_get_device(phandle, &pdev))
 		return -ENODEV;
-	}
-
-	result = acpi_bus_start(*device);
 
-	return result;
+	return acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE);
 }
 
 static void container_notify_cb(acpi_handle handle, u32 type, void *context)


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

* [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (7 preceding siblings ...)
  2012-12-20  1:53           ` [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start() Rafael J. Wysocki
@ 2012-12-20  1:54           ` Rafael J. Wysocki
  2012-12-20  1:54           ` [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan() Rafael J. Wysocki
                             ` (7 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:54 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Notice that acpi_bus_add() uses only 2 of its 4 arguments and
redefine its header to match the body.  Update all of its callers as
necessary and observe that this leads to quite a number of removed
lines of code (Linus will like that).

Add a kerneldoc comment documenting acpi_bus_add() and wonder how
its callers make wrong assumptions about the second argument (make
note to self to take care of that later).

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/acpi_memhotplug.c     |   19 +------------------
 drivers/acpi/container.c           |   16 +---------------
 drivers/acpi/dock.c                |   13 ++-----------
 drivers/acpi/processor_driver.c    |   24 +-----------------------
 drivers/acpi/scan.c                |   34 +++++++++++++++++++++-------------
 drivers/pci/hotplug/acpiphp_glue.c |   21 ++++-----------------
 drivers/pci/hotplug/sgi_hotplug.c  |    3 +--
 include/acpi/acpi_bus.h            |    3 +--
 8 files changed, 32 insertions(+), 101 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1691,25 +1691,33 @@ static int acpi_bus_scan(acpi_handle han
 	return ret;
 }
 
-/*
- * acpi_bus_add
+/**
+ * acpi_bus_add - Add ACPI device node objects in a given namespace scope.
+ * @handle: Root of the namespace scope to scan.
+ * @ret: Location to store a return struct acpi_device pointer.
  *
- * scan a given ACPI tree and (probably recently hot-plugged)
- * create and add found devices.
+ * Scan a given ACPI tree (probably recently hot-plugged) and create and add
+ * found devices.
  *
- * If no devices were found -ENODEV is returned which does not
- * mean that this is a real error, there just have been no suitable
- * ACPI objects in the table trunk from which the kernel could create
- * a device and add an appropriate driver.
+ * If no devices were found, -ENODEV is returned, but it does not mean that
+ * there has been a real error.  There just have been no suitable ACPI objects
+ * in the table trunk from which the kernel could create a device and add an
+ * appropriate driver.
+ *
+ * If 0 is returned, the memory location pointed to by @ret will be populated
+ * with a pointer to a struct acpi_device created while scanning the namespace.
+ * If @handle corresponds to a device node, that will be a pointer to the struct
+ * acpi_device object corresponding to @handle.  Otherwise, it will be a pointer
+ * to a struct acpi_device corresponding to one of its descendants.
+ *
+ * If an error code is returned, NULL will be stored in the memory location
+ * pointed to by @ret.
  */
-
-int
-acpi_bus_add(struct acpi_device **child,
-	     struct acpi_device *parent, acpi_handle handle, int type)
+int acpi_bus_add(acpi_handle handle, struct acpi_device **ret)
 {
 	int err;
 
-	err = acpi_bus_scan(handle, false, child);
+	err = acpi_bus_scan(handle, false, ret);
 	if (err)
 		return err;
 
Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -398,8 +398,7 @@ static inline int acpi_bus_generate_proc
 #endif
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);
-int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
-		 acpi_handle handle, int type);
+int acpi_bus_add(acpi_handle handle, struct acpi_device **ret);
 void acpi_bus_hot_remove_device(void *context);
 int acpi_bus_trim(struct acpi_device *start, int rmdevice);
 acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);
Index: linux/drivers/pci/hotplug/sgi_hotplug.c
===================================================================
--- linux.orig/drivers/pci/hotplug/sgi_hotplug.c
+++ linux/drivers/pci/hotplug/sgi_hotplug.c
@@ -448,8 +448,7 @@ static int enable_slot(struct hotplug_sl
 			if (ACPI_SUCCESS(ret) &&
 			    (adr>>16) == (slot->device_num + 1)) {
 
-				ret = acpi_bus_add(&device, pdevice, chandle,
-						   ACPI_BUS_TYPE_DEVICE);
+				ret = acpi_bus_add(chandle, &device);
 				if (ACPI_FAILURE(ret)) {
 					printk(KERN_ERR "%s: acpi_bus_add "
 					       "failed (0x%x) for slot %d "
Index: linux/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux/drivers/pci/hotplug/acpiphp_glue.c
@@ -734,15 +734,9 @@ static unsigned char acpiphp_max_busnr(s
  */
 static int acpiphp_bus_add(struct acpiphp_func *func)
 {
-	acpi_handle phandle;
-	struct acpi_device *device, *pdevice;
+	struct acpi_device *device;
 	int ret_val;
 
-	acpi_get_parent(func->handle, &phandle);
-	if (acpi_bus_get_device(phandle, &pdevice)) {
-		dbg("no parent device, assuming NULL\n");
-		pdevice = NULL;
-	}
 	if (!acpi_bus_get_device(func->handle, &device)) {
 		dbg("bus exists... trim\n");
 		/* this shouldn't be in here, so remove
@@ -752,8 +746,7 @@ static int acpiphp_bus_add(struct acpiph
 		dbg("acpi_bus_trim return %x\n", ret_val);
 	}
 
-	ret_val = acpi_bus_add(&device, pdevice, func->handle,
-		ACPI_BUS_TYPE_DEVICE);
+	ret_val = acpi_bus_add(func->handle, &device);
 	if (ret_val) {
 		dbg("error adding bus, %x\n",
 			-ret_val);
@@ -1129,8 +1122,7 @@ static int acpiphp_configure_bridge (acp
 
 static void handle_bridge_insertion(acpi_handle handle, u32 type)
 {
-	struct acpi_device *device, *pdevice;
-	acpi_handle phandle;
+	struct acpi_device *device;
 
 	if ((type != ACPI_NOTIFY_BUS_CHECK) &&
 			(type != ACPI_NOTIFY_DEVICE_CHECK)) {
@@ -1138,12 +1130,7 @@ static void handle_bridge_insertion(acpi
 		return;
 	}
 
-	acpi_get_parent(handle, &phandle);
-	if (acpi_bus_get_device(phandle, &pdevice)) {
-		dbg("no parent device, assuming NULL\n");
-		pdevice = NULL;
-	}
-	if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {
+	if (acpi_bus_add(handle, &device)) {
 		err("cannot add bridge to acpi list\n");
 		return;
 	}
Index: linux/drivers/acpi/processor_driver.c
===================================================================
--- linux.orig/drivers/acpi/processor_driver.c
+++ linux/drivers/acpi/processor_driver.c
@@ -677,28 +677,6 @@ static int is_processor_present(acpi_han
 	return 0;
 }
 
-static
-int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
-{
-	acpi_handle phandle;
-	struct acpi_device *pdev;
-
-
-	if (acpi_get_parent(handle, &phandle)) {
-		return -ENODEV;
-	}
-
-	if (acpi_bus_get_device(phandle, &pdev)) {
-		return -ENODEV;
-	}
-
-	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
 static void acpi_processor_hotplug_notify(acpi_handle handle,
 					  u32 event, void *data)
 {
@@ -721,7 +699,7 @@ static void acpi_processor_hotplug_notif
 		if (!acpi_bus_get_device(handle, &device))
 			break;
 
-		result = acpi_processor_device_add(handle, &device);
+		result = acpi_bus_add(handle, &device);
 		if (result) {
 			acpi_handle_err(handle, "Unable to add the device\n");
 			break;
Index: linux/drivers/acpi/dock.c
===================================================================
--- linux.orig/drivers/acpi/dock.c
+++ linux/drivers/acpi/dock.c
@@ -310,8 +310,6 @@ static int dock_present(struct dock_stat
 static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
 {
 	struct acpi_device *device;
-	struct acpi_device *parent_device;
-	acpi_handle parent;
 	int ret;
 
 	if (acpi_bus_get_device(handle, &device)) {
@@ -319,16 +317,9 @@ static struct acpi_device * dock_create_
 		 * no device created for this object,
 		 * so we should create one.
 		 */
-		acpi_get_parent(handle, &parent);
-		if (acpi_bus_get_device(parent, &parent_device))
-			parent_device = NULL;
-
-		ret = acpi_bus_add(&device, parent_device, handle,
-			ACPI_BUS_TYPE_DEVICE);
-		if (ret) {
+		ret = acpi_bus_add(handle, &device);
+		if (ret)
 			pr_debug("error adding bus, %x\n", -ret);
-			return NULL;
-		}
 	}
 	return device;
 }
Index: linux/drivers/acpi/container.c
===================================================================
--- linux.orig/drivers/acpi/container.c
+++ linux/drivers/acpi/container.c
@@ -135,20 +135,6 @@ static int acpi_container_remove(struct
 	return status;
 }
 
-static int container_device_add(struct acpi_device **device, acpi_handle handle)
-{
-	acpi_handle phandle;
-	struct acpi_device *pdev;
-
-	if (acpi_get_parent(handle, &phandle))
-		return -ENODEV;
-
-	if (acpi_bus_get_device(phandle, &pdev))
-		return -ENODEV;
-
-	return acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE);
-}
-
 static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 {
 	struct acpi_device *device = NULL;
@@ -180,7 +166,7 @@ static void container_notify_cb(acpi_han
 		if (!ACPI_FAILURE(status) || device)
 			break;
 
-		result = container_device_add(&device, handle);
+		result = acpi_bus_add(handle, &device);
 		if (result) {
 			acpi_handle_warn(handle, "Failed to add container\n");
 			break;
Index: linux/drivers/acpi/acpi_memhotplug.c
===================================================================
--- linux.orig/drivers/acpi/acpi_memhotplug.c
+++ linux/drivers/acpi/acpi_memhotplug.c
@@ -157,34 +157,17 @@ static int
 acpi_memory_get_device(acpi_handle handle,
 		       struct acpi_memory_device **mem_device)
 {
-	acpi_status status;
-	acpi_handle phandle;
 	struct acpi_device *device = NULL;
-	struct acpi_device *pdevice = NULL;
 	int result;
 
-
 	if (!acpi_bus_get_device(handle, &device) && device)
 		goto end;
 
-	status = acpi_get_parent(handle, &phandle);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Cannot find acpi parent"));
-		return -EINVAL;
-	}
-
-	/* Get the parent device */
-	result = acpi_bus_get_device(phandle, &pdevice);
-	if (result) {
-		acpi_handle_warn(phandle, "Cannot get acpi bus device\n");
-		return -EINVAL;
-	}
-
 	/*
 	 * Now add the notified device.  This creates the acpi_device
 	 * and invokes .add function
 	 */
-	result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
+	result = acpi_bus_add(handle, &device);
 	if (result) {
 		acpi_handle_warn(handle, "Cannot add acpi bus\n");
 		return -EINVAL;


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

* [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan()
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (8 preceding siblings ...)
  2012-12-20  1:54           ` [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used Rafael J. Wysocki
@ 2012-12-20  1:54           ` Rafael J. Wysocki
  2012-12-20  1:55           ` [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag Rafael J. Wysocki
                             ` (6 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:54 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

After the removal of acpi_start_single_object() and acpi_bus_start()
the second argument of acpi_bus_scan() is not necessary any more,
so drop it and update acpi_bus_check_add() accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/scan.c |   18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1592,8 +1592,8 @@ static int acpi_bus_type_and_status(acpi
 	return 0;
 }
 
-static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
-				      void *context, void **return_value)
+static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
+				      void *not_used, void **return_value)
 {
 	struct acpi_device *device = NULL;
 	int type;
@@ -1625,7 +1625,7 @@ static acpi_status acpi_bus_check_add(ac
 	if (!device)
 		return AE_CTRL_DEPTH;
 
-	device->add_type = context ? ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
+	device->add_type = ACPI_BUS_ADD_START;
 	acpi_hot_add_bind(device);
 
  out:
@@ -1662,18 +1662,16 @@ static acpi_status acpi_bus_device_attac
 	return status;
 }
 
-static int acpi_bus_scan(acpi_handle handle, bool start,
-			 struct acpi_device **child)
+static int acpi_bus_scan(acpi_handle handle, struct acpi_device **child)
 {
 	void *device = NULL;
 	acpi_status status;
 	int ret = -ENODEV;
 
-	status = acpi_bus_check_add(handle, 0, (void *)start, &device);
+	status = acpi_bus_check_add(handle, 0, NULL, &device);
 	if (ACPI_SUCCESS(status))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-				    acpi_bus_check_add, NULL, (void *)start,
-				    &device);
+				    acpi_bus_check_add, NULL, NULL, &device);
 
 	if (!device)
 		goto out;
@@ -1717,7 +1715,7 @@ int acpi_bus_add(acpi_handle handle, str
 {
 	int err;
 
-	err = acpi_bus_scan(handle, false, ret);
+	err = acpi_bus_scan(handle, ret);
 	if (err)
 		return err;
 
@@ -1823,7 +1821,7 @@ int __init acpi_scan_init(void)
 	/*
 	 * Enumerate devices in the ACPI namespace.
 	 */
-	result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root);
+	result = acpi_bus_scan(ACPI_ROOT_OBJECT, &acpi_root);
 
 	if (!result)
 		result = acpi_bus_scan_fixed();


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

* [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (9 preceding siblings ...)
  2012-12-20  1:54           ` [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan() Rafael J. Wysocki
@ 2012-12-20  1:55           ` Rafael J. Wysocki
  2012-12-20  1:56           ` [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument Rafael J. Wysocki
                             ` (5 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:55 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

After the removal of the second argument of acpi_bus_scan() there is
no difference between the ACPI_BUS_ADD_MATCH and ACPI_BUS_ADD_START
add types, so the add_type field in struct acpi_device may be
replaced with a single flag.  Do that calling the flag match_driver.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/scan.c     |   21 +++++++++------------
 include/acpi/acpi_bus.h |   11 ++---------
 2 files changed, 11 insertions(+), 21 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -535,7 +535,7 @@ static int acpi_bus_match(struct device
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH
+	return acpi_dev->flags.match_driver
 		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
@@ -1451,8 +1451,7 @@ static void acpi_hot_add_bind(struct acp
 
 static int acpi_add_single_object(struct acpi_device **child,
 				  acpi_handle handle, int type,
-				  unsigned long long sta,
-				  enum acpi_bus_add_type add_type)
+				  unsigned long long sta, bool match_driver)
 {
 	int result;
 	struct acpi_device *device;
@@ -1468,7 +1467,6 @@ static int acpi_add_single_object(struct
 	device->device_type = type;
 	device->handle = handle;
 	device->parent = acpi_bus_get_parent(handle);
-	device->add_type = add_type;
 	STRUCT_TO_INT(device->status) = sta;
 
 	acpi_device_get_busid(device);
@@ -1519,9 +1517,10 @@ static int acpi_add_single_object(struct
 	if ((result = acpi_device_set_context(device)))
 		goto end;
 
+	device->flags.match_driver = match_driver;
 	result = acpi_device_register(device);
 
-	if (device->add_type >= ACPI_BUS_ADD_MATCH)
+	if (device->flags.match_driver)
 		acpi_hot_add_bind(device);
 
 end:
@@ -1550,7 +1549,7 @@ static void acpi_bus_add_power_resource(
 	acpi_bus_get_device(handle, &device);
 	if (!device)
 		acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
-					ACPI_STA_DEFAULT, ACPI_BUS_ADD_START);
+					ACPI_STA_DEFAULT, true);
 }
 
 static int acpi_bus_type_and_status(acpi_handle handle, int *type,
@@ -1621,11 +1620,11 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_CTRL_DEPTH;
 	}
 
-	acpi_add_single_object(&device, handle, type, sta, ACPI_BUS_ADD_BASIC);
+	acpi_add_single_object(&device, handle, type, sta, false);
 	if (!device)
 		return AE_CTRL_DEPTH;
 
-	device->add_type = ACPI_BUS_ADD_START;
+	device->flags.match_driver = true;
 	acpi_hot_add_bind(device);
 
  out:
@@ -1790,16 +1789,14 @@ static int acpi_bus_scan_fixed(void)
 	if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
 		result = acpi_add_single_object(&device, NULL,
 						ACPI_BUS_TYPE_POWER_BUTTON,
-						ACPI_STA_DEFAULT,
-						ACPI_BUS_ADD_START);
+						ACPI_STA_DEFAULT, true);
 		device_init_wakeup(&device->dev, true);
 	}
 
 	if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
 		result = acpi_add_single_object(&device, NULL,
 						ACPI_BUS_TYPE_SLEEP_BUTTON,
-						ACPI_STA_DEFAULT,
-						ACPI_BUS_ADD_START);
+						ACPI_STA_DEFAULT, true);
 	}
 
 	return result;
Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -63,13 +63,6 @@ acpi_get_physical_device_location(acpi_h
 #define ACPI_BUS_FILE_ROOT	"acpi"
 extern struct proc_dir_entry *acpi_root_dir;
 
-enum acpi_bus_add_type {
-	ACPI_BUS_ADD_BASIC = 0,
-	ACPI_BUS_ADD_MATCH,
-	ACPI_BUS_ADD_START,
-	ACPI_BUS_ADD_TYPE_COUNT
-};
-
 enum acpi_bus_removal_type {
 	ACPI_BUS_REMOVAL_NORMAL = 0,
 	ACPI_BUS_REMOVAL_EJECT,
@@ -150,7 +143,8 @@ struct acpi_device_flags {
 	u32 power_manageable:1;
 	u32 performance_manageable:1;
 	u32 eject_pending:1;
-	u32 reserved:24;
+	u32 match_driver:1;
+	u32 reserved:23;
 };
 
 /* File System */
@@ -285,7 +279,6 @@ struct acpi_device {
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
-	enum acpi_bus_add_type add_type;	/* how to handle adding */
 	enum acpi_bus_removal_type removal_type;	/* indicate for different removal type */
 	u8 physical_node_count;
 	struct list_head physical_node_list;


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

* [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (10 preceding siblings ...)
  2012-12-20  1:55           ` [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag Rafael J. Wysocki
@ 2012-12-20  1:56           ` Rafael J. Wysocki
  2012-12-20  1:57           ` [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type Rafael J. Wysocki
                             ` (4 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:56 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

The callers of acpi_bus_add() usually assume that if it has
succeeded, then a struct acpi_device object has been attached to
the handle passed as the first argument.  Unfortunately, however,
this assumption is wrong, because acpi_bus_scan(), and acpi_bus_add()
too as a result, may return a pointer to a different struct
acpi_device object on success (it may be an object corresponding to
one of the descendant ACPI nodes in the namespace scope below that
handle).

For this reason, the callers of acpi_bus_add() who care about
whether or not a struct acpi_device object has been created for
its first argument need to check that using acpi_bus_get_device()
anyway, so the second argument of acpi_bus_add() is not really
useful for them.  The same observation applies to acpi_bus_scan()
executed directly from acpi_scan_init().

Therefore modify the relevant callers of acpi_bus_add() to check the
existence of the struct acpi_device in question with the help of
acpi_bus_get_device() and drop the no longer necessary second
argument of acpi_bus_add().  Accordingly, modify acpi_scan_init() to
use acpi_bus_get_device() to get acpi_root and drop the no longer
needed second argument of acpi_bus_scan().

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/acpi/acpi_memhotplug.c     |    7 +++++-
 drivers/acpi/container.c           |    7 +++++-
 drivers/acpi/dock.c                |    4 ++-
 drivers/acpi/processor_driver.c    |    8 +++++--
 drivers/acpi/scan.c                |   38 ++++++++++---------------------------
 drivers/pci/hotplug/acpiphp_glue.c |   19 ++++++++++--------
 drivers/pci/hotplug/sgi_hotplug.c  |    3 --
 include/acpi/acpi_bus.h            |    2 -
 8 files changed, 45 insertions(+), 43 deletions(-)

Index: linux/drivers/acpi/scan.c
===================================================================
--- linux.orig/drivers/acpi/scan.c
+++ linux/drivers/acpi/scan.c
@@ -1661,37 +1661,27 @@ static acpi_status acpi_bus_device_attac
 	return status;
 }
 
-static int acpi_bus_scan(acpi_handle handle, struct acpi_device **child)
+static int acpi_bus_scan(acpi_handle handle)
 {
 	void *device = NULL;
-	acpi_status status;
-	int ret = -ENODEV;
 
-	status = acpi_bus_check_add(handle, 0, NULL, &device);
-	if (ACPI_SUCCESS(status))
+	if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device)))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
 				    acpi_bus_check_add, NULL, NULL, &device);
 
 	if (!device)
-		goto out;
+		return -ENODEV;
 
-	ret = 0;
-	status = acpi_bus_device_attach(handle, 0, NULL, NULL);
-	if (ACPI_SUCCESS(status))
+	if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL)))
 		acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
 				    acpi_bus_device_attach, NULL, NULL, NULL);
 
- out:
-	if (child)
-		*child = device;
-
-	return ret;
+	return 0;
 }
 
 /**
  * acpi_bus_add - Add ACPI device node objects in a given namespace scope.
  * @handle: Root of the namespace scope to scan.
- * @ret: Location to store a return struct acpi_device pointer.
  *
  * Scan a given ACPI tree (probably recently hot-plugged) and create and add
  * found devices.
@@ -1700,21 +1690,12 @@ static int acpi_bus_scan(acpi_handle han
  * there has been a real error.  There just have been no suitable ACPI objects
  * in the table trunk from which the kernel could create a device and add an
  * appropriate driver.
- *
- * If 0 is returned, the memory location pointed to by @ret will be populated
- * with a pointer to a struct acpi_device created while scanning the namespace.
- * If @handle corresponds to a device node, that will be a pointer to the struct
- * acpi_device object corresponding to @handle.  Otherwise, it will be a pointer
- * to a struct acpi_device corresponding to one of its descendants.
- *
- * If an error code is returned, NULL will be stored in the memory location
- * pointed to by @ret.
  */
-int acpi_bus_add(acpi_handle handle, struct acpi_device **ret)
+int acpi_bus_add(acpi_handle handle)
 {
 	int err;
 
-	err = acpi_bus_scan(handle, ret);
+	err = acpi_bus_scan(handle);
 	if (err)
 		return err;
 
@@ -1818,8 +1799,11 @@ int __init acpi_scan_init(void)
 	/*
 	 * Enumerate devices in the ACPI namespace.
 	 */
-	result = acpi_bus_scan(ACPI_ROOT_OBJECT, &acpi_root);
+	result = acpi_bus_scan(ACPI_ROOT_OBJECT);
+	if (result)
+		return result;
 
+	result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root);
 	if (!result)
 		result = acpi_bus_scan_fixed();
 
Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -391,7 +391,7 @@ static inline int acpi_bus_generate_proc
 #endif
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);
-int acpi_bus_add(acpi_handle handle, struct acpi_device **ret);
+int acpi_bus_add(acpi_handle handle);
 void acpi_bus_hot_remove_device(void *context);
 int acpi_bus_trim(struct acpi_device *start, int rmdevice);
 acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);
Index: linux/drivers/pci/hotplug/sgi_hotplug.c
===================================================================
--- linux.orig/drivers/pci/hotplug/sgi_hotplug.c
+++ linux/drivers/pci/hotplug/sgi_hotplug.c
@@ -412,7 +412,6 @@ static int enable_slot(struct hotplug_sl
 	if (SN_ACPI_BASE_SUPPORT() && ssdt) {
 		unsigned long long adr;
 		struct acpi_device *pdevice;
-		struct acpi_device *device;
 		acpi_handle phandle;
 		acpi_handle chandle = NULL;
 		acpi_handle rethandle;
@@ -448,7 +447,7 @@ static int enable_slot(struct hotplug_sl
 			if (ACPI_SUCCESS(ret) &&
 			    (adr>>16) == (slot->device_num + 1)) {
 
-				ret = acpi_bus_add(chandle, &device);
+				ret = acpi_bus_add(chandle);
 				if (ACPI_FAILURE(ret)) {
 					printk(KERN_ERR "%s: acpi_bus_add "
 					       "failed (0x%x) for slot %d "
Index: linux/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux/drivers/pci/hotplug/acpiphp_glue.c
@@ -746,14 +746,13 @@ static int acpiphp_bus_add(struct acpiph
 		dbg("acpi_bus_trim return %x\n", ret_val);
 	}
 
-	ret_val = acpi_bus_add(func->handle, &device);
-	if (ret_val) {
-		dbg("error adding bus, %x\n",
-			-ret_val);
-		goto acpiphp_bus_add_out;
-	}
+	ret_val = acpi_bus_add(func->handle);
+	if (!ret_val)
+		ret_val = acpi_bus_get_device(func->handle, &device);
+
+	if (ret_val)
+		dbg("error adding bus, %x\n", -ret_val);
 
-acpiphp_bus_add_out:
 	return ret_val;
 }
 
@@ -1130,10 +1129,14 @@ static void handle_bridge_insertion(acpi
 		return;
 	}
 
-	if (acpi_bus_add(handle, &device)) {
+	if (acpi_bus_add(handle)) {
 		err("cannot add bridge to acpi list\n");
 		return;
 	}
+	if (acpi_bus_get_device(handle, &device)) {
+		err("ACPI device object missing\n");
+		return;
+	}
 	if (!acpiphp_configure_bridge(handle))
 		add_bridge(handle);
 	else
Index: linux/drivers/acpi/processor_driver.c
===================================================================
--- linux.orig/drivers/acpi/processor_driver.c
+++ linux/drivers/acpi/processor_driver.c
@@ -699,12 +699,16 @@ static void acpi_processor_hotplug_notif
 		if (!acpi_bus_get_device(handle, &device))
 			break;
 
-		result = acpi_bus_add(handle, &device);
+		result = acpi_bus_add(handle);
 		if (result) {
 			acpi_handle_err(handle, "Unable to add the device\n");
 			break;
 		}
-
+		result = acpi_bus_get_device(handle, &device);
+		if (result) {
+			acpi_handle_err(handle, "Missing device object\n");
+			break;
+		}
 		ost_code = ACPI_OST_SC_SUCCESS;
 		break;
 
Index: linux/drivers/acpi/dock.c
===================================================================
--- linux.orig/drivers/acpi/dock.c
+++ linux/drivers/acpi/dock.c
@@ -317,9 +317,11 @@ static struct acpi_device * dock_create_
 		 * no device created for this object,
 		 * so we should create one.
 		 */
-		ret = acpi_bus_add(handle, &device);
+		ret = acpi_bus_add(handle);
 		if (ret)
 			pr_debug("error adding bus, %x\n", -ret);
+
+		acpi_bus_get_device(handle, &device);
 	}
 	return device;
 }
Index: linux/drivers/acpi/container.c
===================================================================
--- linux.orig/drivers/acpi/container.c
+++ linux/drivers/acpi/container.c
@@ -166,11 +166,16 @@ static void container_notify_cb(acpi_han
 		if (!ACPI_FAILURE(status) || device)
 			break;
 
-		result = acpi_bus_add(handle, &device);
+		result = acpi_bus_add(handle);
 		if (result) {
 			acpi_handle_warn(handle, "Failed to add container\n");
 			break;
 		}
+		result = acpi_bus_get_device(handle, &device);
+		if (result) {
+			acpi_handle_warn(handle, "Missing device object\n");
+			break;
+		}
 
 		kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
 		ost_code = ACPI_OST_SC_SUCCESS;
Index: linux/drivers/acpi/acpi_memhotplug.c
===================================================================
--- linux.orig/drivers/acpi/acpi_memhotplug.c
+++ linux/drivers/acpi/acpi_memhotplug.c
@@ -167,11 +167,16 @@ acpi_memory_get_device(acpi_handle handl
 	 * Now add the notified device.  This creates the acpi_device
 	 * and invokes .add function
 	 */
-	result = acpi_bus_add(handle, &device);
+	result = acpi_bus_add(handle);
 	if (result) {
 		acpi_handle_warn(handle, "Cannot add acpi bus\n");
 		return -EINVAL;
 	}
+	result = acpi_bus_get_device(handle, &device);
+	if (result) {
+		acpi_handle_warn(handle, "Missing device object\n");
+		return -EINVAL;
+	}
 
       end:
 	*mem_device = acpi_driver_data(device);


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

* [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (11 preceding siblings ...)
  2012-12-20  1:56           ` [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument Rafael J. Wysocki
@ 2012-12-20  1:57           ` Rafael J. Wysocki
  2012-12-20  1:58           ` [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup Rafael J. Wysocki
                             ` (3 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:57 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Add two new callbacks,.setup() and .cleanup(), struct acpi_bus_type
and modify acpi_platform_notify() to call .setup() after executing
acpi_bind_one() successfully and acpi_platform_notify_remove() to
call .cleanup() before running acpi_unbind_one().  This will allow
the users of struct acpi_bus_type, PCI in particular, to specify
operations to be executed right after the given device has been
associated with a companion struct acpi_device and right before
it's going to be detached from that companion, respectively.

The main motivation is to be able to get rid of acpi_pci_bind()
and acpi_pci_unbind(), which are horrible horrible stuff.  [In short,
there are three problems with them: The way they populate the .bind()
and .unbind() callbacks of ACPI devices is rather less than
straightforward, they require special hotplug-specific paths to be
present in the ACPI namespace scanning code and by the time
acpi_pci_unbind() is called the PCI device object in question may
not exist any more.]

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/glue.c     |   52 +++++++++++++++++++++++++++++++++---------------
 include/acpi/acpi_bus.h |    2 +
 2 files changed, 38 insertions(+), 16 deletions(-)

Index: linux/include/acpi/acpi_bus.h
===================================================================
--- linux.orig/include/acpi/acpi_bus.h
+++ linux/include/acpi/acpi_bus.h
@@ -423,6 +423,8 @@ struct acpi_bus_type {
 	int (*find_device) (struct device *, acpi_handle *);
 	/* For bridges, such as PCI root bridge, IDE controller */
 	int (*find_bridge) (struct device *, acpi_handle *);
+	void (*setup)(struct device *);
+	void (*cleanup)(struct device *);
 };
 int register_acpi_bus_type(struct acpi_bus_type *);
 int unregister_acpi_bus_type(struct acpi_bus_type *);
Index: linux/drivers/acpi/glue.c
===================================================================
--- linux.orig/drivers/acpi/glue.c
+++ linux/drivers/acpi/glue.c
@@ -63,6 +63,9 @@ static struct acpi_bus_type *acpi_get_bu
 {
 	struct acpi_bus_type *tmp, *ret = NULL;
 
+	if (!type)
+		return NULL;
+
 	down_read(&bus_type_sem);
 	list_for_each_entry(tmp, &bus_type_list, list) {
 		if (tmp->bus == type) {
@@ -264,28 +267,39 @@ static int acpi_platform_notify(struct d
 {
 	struct acpi_bus_type *type;
 	acpi_handle handle;
-	int ret = -EINVAL;
+	int ret;
 
 	ret = acpi_bind_one(dev, NULL);
-	if (!ret)
-		goto out;
-
-	if (!dev->bus || !dev->parent) {
+	if (ret && (!dev->bus || !dev->parent)) {
 		/* bridge devices genernally haven't bus or parent */
 		ret = acpi_find_bridge_device(dev, &handle);
-		goto end;
+		if (!ret) {
+			ret = acpi_bind_one(dev, handle);
+			if (ret)
+				goto out;
+		}
 	}
+
 	type = acpi_get_bus_type(dev->bus);
-	if (!type) {
-		DBG("No ACPI bus support for %s\n", dev_name(dev));
-		ret = -EINVAL;
-		goto end;
-	}
-	if ((ret = type->find_device(dev, &handle)) != 0)
-		DBG("Can't get handler for %s\n", dev_name(dev));
- end:
-	if (!ret)
-		acpi_bind_one(dev, handle);
+	if (ret) {
+		if (!type || !type->find_device) {
+			DBG("No ACPI bus support for %s\n", dev_name(dev));
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = type->find_device(dev, &handle);
+		if (ret) {
+			DBG("Unable to get handle for %s\n", dev_name(dev));
+			goto out;
+		}
+		ret = acpi_bind_one(dev, handle);
+		if (ret)
+			goto out;
+	}
+
+	if (type && type->setup)
+		type->setup(dev);
 
  out:
 #if ACPI_GLUE_DEBUG
@@ -304,6 +318,12 @@ static int acpi_platform_notify(struct d
 
 static int acpi_platform_notify_remove(struct device *dev)
 {
+	struct acpi_bus_type *type;
+
+	type = acpi_get_bus_type(dev->bus);
+	if (type && type->cleanup)
+		type->cleanup(dev);
+
 	acpi_unbind_one(dev);
 	return 0;
 }


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

* [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (12 preceding siblings ...)
  2012-12-20  1:57           ` [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type Rafael J. Wysocki
@ 2012-12-20  1:58           ` Rafael J. Wysocki
  2012-12-20  1:59           ` [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c Rafael J. Wysocki
                             ` (2 subsequent siblings)
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:58 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Currently, the ACPI wakeup capability of PCI devices is set up
in two different places, partially in acpi_pci_bind() where
runtime wakeup is initialized and partially in
platform_pci_wakeup_init(), where system wakeup is initialized.
The cleanup is only done in acpi_pci_unbind() and it only covers
runtime wakeup.

Use the new .setup() and .cleanup() callbacks in struct acpi_bus_type
to consolidate that code and do the setup and the cleanup each in one
place.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/device_pm.c |    2 +-
 drivers/acpi/pci_bind.c  |    7 -------
 drivers/pci/pci-acpi.c   |   30 +++++++++++++++++++++++++++++-
 drivers/pci/pci.c        |   26 +-------------------------
 drivers/pci/pci.h        |    5 -----
 drivers/pci/probe.c      |    1 -
 include/linux/acpi.h     |    5 +++++
 7 files changed, 36 insertions(+), 40 deletions(-)

Index: linux/drivers/acpi/pci_bind.c
===================================================================
--- linux.orig/drivers/acpi/pci_bind.c
+++ linux/drivers/acpi/pci_bind.c
@@ -43,9 +43,6 @@ static int acpi_pci_unbind(struct acpi_d
 	if (!dev)
 		goto out;
 
-	device_set_run_wake(&dev->dev, false);
-	pci_acpi_remove_pm_notifier(device);
-
 	if (!dev->subordinate)
 		goto out;
 
@@ -70,10 +67,6 @@ static int acpi_pci_bind(struct acpi_dev
 	if (!dev)
 		return 0;
 
-	pci_acpi_add_pm_notifier(device, dev);
-	if (device->wakeup.flags.run_wake)
-		device_set_run_wake(&dev->dev, true);
-
 	/*
 	 * Install the 'bind' function to facilitate callbacks for
 	 * children of the P2P bridge.
Index: linux/drivers/pci/pci.h
===================================================================
--- linux.orig/drivers/pci/pci.h
+++ linux/drivers/pci/pci.h
@@ -44,9 +44,6 @@ int pci_probe_reset_function(struct pci_
  *                platform; to be used during system-wide transitions from a
  *                sleeping state to the working state and vice versa
  *
- * @can_wakeup: returns 'true' if given device is capable of waking up the
- *              system from a sleeping state
- *
  * @sleep_wake: enables/disables the system wake up capability of given device
  *
  * @run_wake: enables/disables the platform to generate run-time wake-up events
@@ -60,7 +57,6 @@ struct pci_platform_pm_ops {
 	bool (*is_manageable)(struct pci_dev *dev);
 	int (*set_state)(struct pci_dev *dev, pci_power_t state);
 	pci_power_t (*choose_state)(struct pci_dev *dev);
-	bool (*can_wakeup)(struct pci_dev *dev);
 	int (*sleep_wake)(struct pci_dev *dev, bool enable);
 	int (*run_wake)(struct pci_dev *dev, bool enable);
 };
@@ -75,7 +71,6 @@ extern void pci_wakeup_bus(struct pci_bu
 extern void pci_config_pm_runtime_get(struct pci_dev *dev);
 extern void pci_config_pm_runtime_put(struct pci_dev *dev);
 extern void pci_pm_init(struct pci_dev *dev);
-extern void platform_pci_wakeup_init(struct pci_dev *dev);
 extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
 void pci_free_cap_save_buffers(struct pci_dev *dev);
 
Index: linux/drivers/pci/probe.c
===================================================================
--- linux.orig/drivers/pci/probe.c
+++ linux/drivers/pci/probe.c
@@ -1276,7 +1276,6 @@ static void pci_init_capabilities(struct
 
 	/* Power Management */
 	pci_pm_init(dev);
-	platform_pci_wakeup_init(dev);
 
 	/* Vital Product Data */
 	pci_vpd_pci22_init(dev);
Index: linux/drivers/pci/pci.c
===================================================================
--- linux.orig/drivers/pci/pci.c
+++ linux/drivers/pci/pci.c
@@ -450,7 +450,7 @@ static struct pci_platform_pm_ops *pci_p
 int pci_set_platform_pm(struct pci_platform_pm_ops *ops)
 {
 	if (!ops->is_manageable || !ops->set_state || !ops->choose_state
-	    || !ops->sleep_wake || !ops->can_wakeup)
+	    || !ops->sleep_wake)
 		return -EINVAL;
 	pci_platform_pm = ops;
 	return 0;
@@ -473,11 +473,6 @@ static inline pci_power_t platform_pci_c
 			pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR;
 }
 
-static inline bool platform_pci_can_wakeup(struct pci_dev *dev)
-{
-	return pci_platform_pm ? pci_platform_pm->can_wakeup(dev) : false;
-}
-
 static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
 {
 	return pci_platform_pm ?
@@ -1960,25 +1955,6 @@ void pci_pm_init(struct pci_dev *dev)
 	}
 }
 
-/**
- * platform_pci_wakeup_init - init platform wakeup if present
- * @dev: PCI device
- *
- * Some devices don't have PCI PM caps but can still generate wakeup
- * events through platform methods (like ACPI events).  If @dev supports
- * platform wakeup events, set the device flag to indicate as much.  This
- * may be redundant if the device also supports PCI PM caps, but double
- * initialization should be safe in that case.
- */
-void platform_pci_wakeup_init(struct pci_dev *dev)
-{
-	if (!platform_pci_can_wakeup(dev))
-		return;
-
-	device_set_wakeup_capable(&dev->dev, true);
-	platform_pci_sleep_wake(dev, false);
-}
-
 static void pci_add_saved_cap(struct pci_dev *pci_dev,
 	struct pci_cap_saved_state *new_cap)
 {
Index: linux/include/linux/acpi.h
===================================================================
--- linux.orig/include/linux/acpi.h
+++ linux/include/linux/acpi.h
@@ -510,9 +510,14 @@ static inline int acpi_subsys_resume_ear
 #endif
 
 #if defined(CONFIG_ACPI) && defined(CONFIG_PM)
+struct acpi_device *acpi_dev_pm_get_node(struct device *dev);
 int acpi_dev_pm_attach(struct device *dev, bool power_on);
 void acpi_dev_pm_detach(struct device *dev, bool power_off);
 #else
+static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
+{
+	return NULL;
+}
 static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
 {
 	return -ENODEV;
Index: linux/drivers/acpi/device_pm.c
===================================================================
--- linux.orig/drivers/acpi/device_pm.c
+++ linux/drivers/acpi/device_pm.c
@@ -634,7 +634,7 @@ int acpi_pm_device_sleep_wake(struct dev
  * acpi_dev_pm_get_node - Get ACPI device node for the given physical device.
  * @dev: Device to get the ACPI node for.
  */
-static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
+struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
 {
 	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
 	struct acpi_device *adev;
Index: linux/drivers/pci/pci-acpi.c
===================================================================
--- linux.orig/drivers/pci/pci-acpi.c
+++ linux/drivers/pci/pci-acpi.c
@@ -283,7 +283,6 @@ static struct pci_platform_pm_ops acpi_p
 	.is_manageable = acpi_pci_power_manageable,
 	.set_state = acpi_pci_set_power_state,
 	.choose_state = acpi_pci_choose_state,
-	.can_wakeup = acpi_pci_can_wakeup,
 	.sleep_wake = acpi_pci_sleep_wake,
 	.run_wake = acpi_pci_run_wake,
 };
@@ -321,10 +320,39 @@ static int acpi_pci_find_root_bridge(str
 	return 0;
 }
 
+static void acpi_pci_wakeup_setup(struct device *dev)
+{
+	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+
+	if (!adev || !adev->wakeup.flags.valid)
+		return;
+
+	device_set_wakeup_capable(dev, true);
+	acpi_pci_sleep_wake(pci_dev, false);
+
+	pci_acpi_add_pm_notifier(adev, pci_dev);
+	if (adev->wakeup.flags.run_wake)
+		device_set_run_wake(dev, true);
+}
+
+static void acpi_pci_wakeup_cleanup(struct device *dev)
+{
+	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+
+	if (adev && adev->wakeup.flags.valid) {
+		device_set_wakeup_capable(dev, false);
+		device_set_run_wake(dev, false);
+		pci_acpi_remove_pm_notifier(adev);
+	}
+}
+
 static struct acpi_bus_type acpi_pci_bus = {
 	.bus = &pci_bus_type,
 	.find_device = acpi_pci_find_device,
 	.find_bridge = acpi_pci_find_root_bridge,
+	.setup = acpi_pci_wakeup_setup,
+	.cleanup = acpi_pci_wakeup_cleanup,
 };
 
 static int __init acpi_pci_init(void)


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

* [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (13 preceding siblings ...)
  2012-12-20  1:58           ` [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup Rafael J. Wysocki
@ 2012-12-20  1:59           ` Rafael J. Wysocki
  2012-12-20  2:06           ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu
  2012-12-20 21:07           ` Toshi Kani
  16 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20  1:59 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Toshi Kani, Bjorn Helgaas, LKML, linux-pci, Yinghai Lu,
	Myron Stowe, Yijing Wang, Jiang Liu

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Move the code related to _PRT setup and removal from acpi_pci_bind()
and acpi_pci_unbind() to the .setup() and .cleanup() callbacks in
acpi_pci_bus and remove acpi_pci_bind() and acpi_pci_unbind() that
have no purpose any more.  Accordingly, remove the code related to
device .bind() and .unbind() operations from the ACPI PCI root bridge
driver.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/Makefile   |    2 
 drivers/acpi/pci_bind.c |  113 ------------------------------------------------
 drivers/acpi/pci_root.c |   31 -------------
 drivers/pci/pci-acpi.c  |   34 +++++++++++---
 4 files changed, 29 insertions(+), 151 deletions(-)

Index: linux/drivers/acpi/pci_bind.c
===================================================================
--- linux.orig/drivers/acpi/pci_bind.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *  pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $)
- *
- *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
- *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/pci-acpi.h>
-#include <linux/acpi.h>
-#include <linux/pm_runtime.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
-#define _COMPONENT		ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_bind");
-
-static int acpi_pci_unbind(struct acpi_device *device)
-{
-	struct pci_dev *dev;
-
-	dev = acpi_get_pci_dev(device->handle);
-	if (!dev)
-		goto out;
-
-	if (!dev->subordinate)
-		goto out;
-
-	acpi_pci_irq_del_prt(dev->subordinate);
-
-	device->ops.bind = NULL;
-	device->ops.unbind = NULL;
-
-out:
-	pci_dev_put(dev);
-	return 0;
-}
-
-static int acpi_pci_bind(struct acpi_device *device)
-{
-	acpi_status status;
-	acpi_handle handle;
-	struct pci_bus *bus;
-	struct pci_dev *dev;
-
-	dev = acpi_get_pci_dev(device->handle);
-	if (!dev)
-		return 0;
-
-	/*
-	 * Install the 'bind' function to facilitate callbacks for
-	 * children of the P2P bridge.
-	 */
-	if (dev->subordinate) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Device %04x:%02x:%02x.%d is a PCI bridge\n",
-				  pci_domain_nr(dev->bus), dev->bus->number,
-				  PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)));
-		device->ops.bind = acpi_pci_bind;
-		device->ops.unbind = acpi_pci_unbind;
-	}
-
-	/*
-	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
-	 * _PRT objects within the scope of non-bridge devices.  Note that
-	 * _PRTs within the scope of a PCI bridge assume the bridge's
-	 * subordinate bus number.
-	 *
-	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
-	 */
-	status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
-	if (ACPI_FAILURE(status))
-		goto out;
-
-	if (dev->subordinate)
-		bus = dev->subordinate;
-	else
-		bus = dev->bus;
-
-	acpi_pci_irq_add_prt(device->handle, bus);
-
-out:
-	pci_dev_put(dev);
-	return 0;
-}
-
-int acpi_pci_bind_root(struct acpi_device *device)
-{
-	device->ops.bind = acpi_pci_bind;
-	device->ops.unbind = acpi_pci_unbind;
-
-	return 0;
-}
Index: linux/drivers/pci/pci-acpi.c
===================================================================
--- linux.orig/drivers/pci/pci-acpi.c
+++ linux/drivers/pci/pci-acpi.c
@@ -320,12 +320,30 @@ static int acpi_pci_find_root_bridge(str
 	return 0;
 }
 
-static void acpi_pci_wakeup_setup(struct device *dev)
+static void pci_acpi_setup(struct device *dev)
 {
-	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
 	struct pci_dev *pci_dev = to_pci_dev(dev);
+	acpi_handle handle = ACPI_HANDLE(dev);
+	struct acpi_device *adev;
+	acpi_status status;
+	acpi_handle dummy;
+
+	/*
+	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
+	 * _PRT objects within the scope of non-bridge devices.  Note that
+	 * _PRTs within the scope of a PCI bridge assume the bridge's
+	 * subordinate bus number.
+	 *
+	 * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
+	 */
+	status = acpi_get_handle(handle, METHOD_NAME__PRT, &dummy);
+	if (ACPI_SUCCESS(status)) {
+		struct pci_bus *bus = pci_dev->subordinate;
+
+		acpi_pci_irq_add_prt(handle, bus ? bus : pci_dev->bus);
+	}
 
-	if (!adev || !adev->wakeup.flags.valid)
+	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
 		return;
 
 	device_set_wakeup_capable(dev, true);
@@ -336,23 +354,27 @@ static void acpi_pci_wakeup_setup(struct
 		device_set_run_wake(dev, true);
 }
 
-static void acpi_pci_wakeup_cleanup(struct device *dev)
+static void pci_acpi_cleanup(struct device *dev)
 {
 	struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+	struct pci_dev *pci_dev = to_pci_dev(dev);
 
 	if (adev && adev->wakeup.flags.valid) {
 		device_set_wakeup_capable(dev, false);
 		device_set_run_wake(dev, false);
 		pci_acpi_remove_pm_notifier(adev);
 	}
+
+	if (pci_dev->subordinate)
+		acpi_pci_irq_del_prt(pci_dev->subordinate);
 }
 
 static struct acpi_bus_type acpi_pci_bus = {
 	.bus = &pci_bus_type,
 	.find_device = acpi_pci_find_device,
 	.find_bridge = acpi_pci_find_root_bridge,
-	.setup = acpi_pci_wakeup_setup,
-	.cleanup = acpi_pci_wakeup_cleanup,
+	.setup = pci_acpi_setup,
+	.cleanup = pci_acpi_cleanup,
 };
 
 static int __init acpi_pci_init(void)
Index: linux/drivers/acpi/Makefile
===================================================================
--- linux.orig/drivers/acpi/Makefile
+++ linux/drivers/acpi/Makefile
@@ -37,7 +37,7 @@ acpi-y				+= resource.o
 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-y				+= pci_root.o pci_link.o pci_irq.o
 acpi-y				+= acpi_platform.o
 acpi-y				+= power.o
 acpi-y				+= event.o
Index: linux/drivers/acpi/pci_root.c
===================================================================
--- linux.orig/drivers/acpi/pci_root.c
+++ linux/drivers/acpi/pci_root.c
@@ -186,21 +186,6 @@ static acpi_status try_get_root_bridge_b
 	return AE_OK;
 }
 
-static void acpi_pci_bridge_scan(struct acpi_device *device)
-{
-	int status;
-	struct acpi_device *child = NULL;
-
-	if (device->flags.bus_address)
-		if (device->parent && device->parent->ops.bind) {
-			status = device->parent->ops.bind(device);
-			if (!status) {
-				list_for_each_entry(child, &device->children, node)
-					acpi_pci_bridge_scan(child);
-			}
-		}
-}
-
 static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
 
 static acpi_status acpi_pci_run_osc(acpi_handle handle,
@@ -450,7 +435,6 @@ static int __devinit acpi_pci_root_add(s
 	int result;
 	struct acpi_pci_root *root;
 	acpi_handle handle;
-	struct acpi_device *child;
 	struct acpi_pci_driver *driver;
 	u32 flags, base_flags;
 
@@ -538,15 +522,6 @@ static int __devinit acpi_pci_root_add(s
 	}
 
 	/*
-	 * Attach ACPI-PCI Context
-	 * -----------------------
-	 * Thus binding the ACPI and PCI devices.
-	 */
-	result = acpi_pci_bind_root(device);
-	if (result)
-		goto out_del_root;
-
-	/*
 	 * PCI Routing Table
 	 * -----------------
 	 * Evaluate and parse _PRT, if exists.
@@ -555,12 +530,6 @@ static int __devinit acpi_pci_root_add(s
 	if (ACPI_SUCCESS(status))
 		result = acpi_pci_irq_add_prt(device->handle, root->bus);
 
-	/*
-	 * Scan and bind all _ADR-Based Devices
-	 */
-	list_for_each_entry(child, &device->children, node)
-		acpi_pci_bridge_scan(child);
-
 	/* Indicate support for various _OSC capabilities. */
 	if (pci_ext_cfg_avail(root->bus->self))
 		flags |= OSC_EXT_PCI_CONFIG_SUPPORT;


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

* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (14 preceding siblings ...)
  2012-12-20  1:59           ` [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c Rafael J. Wysocki
@ 2012-12-20  2:06           ` Yinghai Lu
  2012-12-21  0:09             ` Rafael J. Wysocki
  2012-12-20 21:07           ` Toshi Kani
  16 siblings, 1 reply; 88+ messages in thread
From: Yinghai Lu @ 2012-12-20  2:06 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Wed, Dec 19, 2012 at 5:45 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:

great!, the .bind and .unbind go away.

>
> The patches are on top of my master branch and I'm going to rebase them when
> v3.8-rc1 is out.

>
> There is a git tree you can pull them from at:
>
> http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new
>
> It's v3.7 with my master branch merged and the new patches on top.


can you make it base to today's Linus tree ?

otherwise I have to do some manual merge...

Bjorn change the _PRT for v.3.8...

Thanks

Yinghai

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

* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices
  2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
                             ` (15 preceding siblings ...)
  2012-12-20  2:06           ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu
@ 2012-12-20 21:07           ` Toshi Kani
  2012-12-20 23:20             ` Rafael J. Wysocki
  16 siblings, 1 reply; 88+ messages in thread
From: Toshi Kani @ 2012-12-20 21:07 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

Hi Rafael,

The changes look very good.  It's much cleaner and consistent. :-)  For
the series:

Acked-by: Toshi Kani <toshi.kani@hp.com>

Thanks,
-Toshi


On Thu, 2012-12-20 at 02:45 +0100, Rafael J. Wysocki wrote:
> Hi all,
> 
> I've finally cut the patches removing acpi_pci_bind() and acpi_pci_unbind(),
> so I'm kind of ready to post the entire series reworking the ACPI namespace
> scanning code.
> 
> Patches [1-6/16] are essentially these ones:
> 
> https://patchwork.kernel.org/patch/1889821/
> https://patchwork.kernel.org/patch/1876481/
> https://patchwork.kernel.org/patch/1876531/
> https://patchwork.kernel.org/patch/1876571/
> https://patchwork.kernel.org/patch/1876511/
> https://patchwork.kernel.org/patch/1876401/
> 
> but [2-6/16] have been rebased on top of the first one.
> 
> Patches [7-12/16] are essentially these:
> 
> https://patchwork.kernel.org/patch/1884721/
> https://patchwork.kernel.org/patch/1884701/
> https://patchwork.kernel.org/patch/1884761/
> https://patchwork.kernel.org/patch/1884731/
> https://patchwork.kernel.org/patch/1884751/
> https://patchwork.kernel.org/patch/1884661/
> 
> but they have been rebased on top of https://patchwork.kernel.org/patch/1889821/.
> I added Yinghai's ACKs to them tentatively, although they are a bit different
> from the previous versions.  The difference is not too important, however,
> because the following patches finally remove the acpi_pci_bind()/acpi_pci_unbind()
> stuff:
> 
> [13/16] Add .setup() and .cleanup() callbacks to struct acpi_bus_type.
> [14/16] Rework the setup and cleanup of ACPI/PCI device wakeup.
> [15/16] Move the _PRT setup and cleanup code to pci-acpi.c.
> [16/16] Drop ACPI device .bind() and .unbind() callbacks.
> 
> This is done a bit differently than I thought it would be, mostly because the
> _PRT-related operations require the "subordinate" pointers of bridges to be
> populated.  I think it may be possible to simplify this further if that
> requirement can be removed (I haven't looked into that).
> 
> In fact, patches [13-15/16] do not essentially depend on [1-12/16], only the
> last one does.
> 
> The patches are on top of my master branch and I'm going to rebase them when
> v3.8-rc1 is out.
> 
> There is a git tree you can pull them from at:
> 
> http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new
> 
> It's v3.7 with my master branch merged and the new patches on top.
> 
> 
> Thanks,
> Rafael
> 
> 



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

* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices
  2012-12-20 21:07           ` Toshi Kani
@ 2012-12-20 23:20             ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-20 23:20 UTC (permalink / raw)
  To: Toshi Kani
  Cc: ACPI Devel Maling List, Bjorn Helgaas, LKML, linux-pci,
	Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Thursday, December 20, 2012 02:07:27 PM Toshi Kani wrote:
> Hi Rafael,
> 
> The changes look very good.  It's much cleaner and consistent. :-)  For
> the series:
> 
> Acked-by: Toshi Kani <toshi.kani@hp.com>

Thanks!


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices
  2012-12-20  2:06           ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu
@ 2012-12-21  0:09             ` Rafael J. Wysocki
  2012-12-21  3:59               ` Yinghai Lu
  0 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-21  0:09 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Wednesday, December 19, 2012 06:06:57 PM Yinghai Lu wrote:
> On Wed, Dec 19, 2012 at 5:45 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> 
> great!, the .bind and .unbind go away.
> 
> >
> > The patches are on top of my master branch and I'm going to rebase them when
> > v3.8-rc1 is out.
> 
> >
> > There is a git tree you can pull them from at:
> >
> > http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new
> >
> > It's v3.7 with my master branch merged and the new patches on top.
> 
> 
> can you make it base to today's Linus tree ?

Sure.  Rebased and pushed out:

git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git acpi-scan-next

Untested, though, so caveat emptor. :-)

> otherwise I have to do some manual merge...
> 
> Bjorn change the _PRT for v.3.8...

Well, not only that has changed.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices
  2012-12-21  0:09             ` Rafael J. Wysocki
@ 2012-12-21  3:59               ` Yinghai Lu
  2012-12-21 22:23                 ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Yinghai Lu @ 2012-12-21  3:59 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Thu, Dec 20, 2012 at 4:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Wednesday, December 19, 2012 06:06:57 PM Yinghai Lu wrote:
>> On Wed, Dec 19, 2012 at 5:45 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>>
>> great!, the .bind and .unbind go away.
>>
>> >
>> > The patches are on top of my master branch and I'm going to rebase them when
>> > v3.8-rc1 is out.
>>
>> >
>> > There is a git tree you can pull them from at:
>> >
>> > http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new
>> >
>> > It's v3.7 with my master branch merged and the new patches on top.
>>
>>
>> can you make it base to today's Linus tree ?
>
> Sure.  Rebased and pushed out:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git acpi-scan-next
>

Thanks.

I rebased pci-root-bus-hotplug patchset on top it, and it works well.

So
Acked-by: Yinghai Lu <yinghai@kernel.org>
for the four new ones in your acpi_scan_next branch.

i put the updated patches in

git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git
for-pci-root-bus-3.9

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

* Re: [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices
  2012-12-21  3:59               ` Yinghai Lu
@ 2012-12-21 22:23                 ` Rafael J. Wysocki
  0 siblings, 0 replies; 88+ messages in thread
From: Rafael J. Wysocki @ 2012-12-21 22:23 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Myron Stowe, Yijing Wang, Jiang Liu

On Thursday, December 20, 2012 07:59:15 PM Yinghai Lu wrote:
> On Thu, Dec 20, 2012 at 4:09 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Wednesday, December 19, 2012 06:06:57 PM Yinghai Lu wrote:
> >> On Wed, Dec 19, 2012 at 5:45 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >>
> >> great!, the .bind and .unbind go away.
> >>
> >> >
> >> > The patches are on top of my master branch and I'm going to rebase them when
> >> > v3.8-rc1 is out.
> >>
> >> >
> >> > There is a git tree you can pull them from at:
> >> >
> >> > http://git.kernel.org/?p=linux/kernel/git/rafael/linux-pm.git;a=summary acpi-scan-temp-new
> >> >
> >> > It's v3.7 with my master branch merged and the new patches on top.
> >>
> >>
> >> can you make it base to today's Linus tree ?
> >
> > Sure.  Rebased and pushed out:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git acpi-scan-next
> >
> 
> Thanks.
> 
> I rebased pci-root-bus-hotplug patchset on top it, and it works well.

Great, thanks for testing!

> So
> Acked-by: Yinghai Lu <yinghai@kernel.org>
> for the four new ones in your acpi_scan_next branch.

Thanks!

I'll rebase the whole series on top of v3.8-rc1 when it's out.

> i put the updated patches in
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git
> for-pci-root-bus-3.9

OK, thanks.

I'll have a look at that series next week.

Thanks,
Rafael


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2012-12-20  1:47           ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
@ 2013-01-11 20:00             ` Mika Westerberg
  2013-01-11 20:31               ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Mika Westerberg @ 2013-01-11 20:00 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

(Sorry to jump in late but I noticed one problem with this series while
testing).

On Thu, Dec 20, 2012 at 02:47:47AM +0100, Rafael J. Wysocki wrote:
> +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> +					void *context, void **not_used)
> +{
> +	struct acpi_bus_ops *ops = context;
> +	acpi_status status = AE_OK;
> +	struct acpi_device *device;
> +	unsigned long long sta_not_used;
> +	int type_not_used;
> +
> +	/*
> +	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
> +	 * namespace walks prematurely.
> +	 */
> +	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> +		return AE_OK;
> +
> +	if (acpi_bus_get_device(handle, &device))
> +		return AE_CTRL_DEPTH;
> +
> +	if (ops->acpi_op_add) {
> +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> +			/* This is a known good platform device. */
> +			acpi_create_platform_device(device);
> +		} else if (device_attach(&device->dev)) {

device_attach() returns 1 if it succeeds to attach device to a driver. In
that case we should continue and not return AE_CTRL_DEPTH, right?

> +			status = AE_CTRL_DEPTH;
> +		}
> +	} else if (ops->acpi_op_start) {
> +		if (ACPI_FAILURE(acpi_start_single_object(device)))
> +			status = AE_CTRL_DEPTH;
> +	}
> +	return status;
> +}

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

* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2013-01-11 20:00             ` Mika Westerberg
@ 2013-01-11 20:31               ` Rafael J. Wysocki
  2013-01-11 20:37                 ` Mika Westerberg
  0 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2013-01-11 20:31 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Friday, January 11, 2013 10:00:46 PM Mika Westerberg wrote:
> (Sorry to jump in late but I noticed one problem with this series while
> testing).
> 
> On Thu, Dec 20, 2012 at 02:47:47AM +0100, Rafael J. Wysocki wrote:
> > +static acpi_status acpi_bus_probe_start(acpi_handle handle, u32 lvl,
> > +					void *context, void **not_used)
> > +{
> > +	struct acpi_bus_ops *ops = context;
> > +	acpi_status status = AE_OK;
> > +	struct acpi_device *device;
> > +	unsigned long long sta_not_used;
> > +	int type_not_used;
> > +
> > +	/*
> > +	 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
> > +	 * namespace walks prematurely.
> > +	 */
> > +	if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> > +		return AE_OK;
> > +
> > +	if (acpi_bus_get_device(handle, &device))
> > +		return AE_CTRL_DEPTH;
> > +
> > +	if (ops->acpi_op_add) {
> > +		if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
> > +			/* This is a known good platform device. */
> > +			acpi_create_platform_device(device);
> > +		} else if (device_attach(&device->dev)) {
> 
> device_attach() returns 1 if it succeeds to attach device to a driver. In
> that case we should continue and not return AE_CTRL_DEPTH, right?

That's correct.  The check is reversed, so we need the appended patch on top
of linux-pm.git/acpi-scan.

Thanks,
Rafael


---
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Subject: ACPI / scan: Fix check of device_attach() return value.

Since device_attach() returns 1 on success and 0 on failure,
the check against its return value in acpi_bus_device_attach()
should be reveresed.  Make it so.

Reported-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -1598,7 +1598,7 @@ static acpi_status acpi_bus_device_attac
 	if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
 		/* This is a known good platform device. */
 		acpi_create_platform_device(device);
-	} else if (device_attach(&device->dev)) {
+	} else if (!device_attach(&device->dev)) {
 		status = AE_CTRL_DEPTH;
 	}
 	return status;

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2013-01-11 20:31               ` Rafael J. Wysocki
@ 2013-01-11 20:37                 ` Mika Westerberg
  2013-01-11 20:58                   ` Rafael J. Wysocki
  0 siblings, 1 reply; 88+ messages in thread
From: Mika Westerberg @ 2013-01-11 20:37 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Fri, Jan 11, 2013 at 09:31:43PM +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Subject: ACPI / scan: Fix check of device_attach() return value.
> 
> Since device_attach() returns 1 on success and 0 on failure,
> the check against its return value in acpi_bus_device_attach()
> should be reveresed.  Make it so.

Not sure if it matters but it returns 0 if no device was bound to a driver
and -ENODEV in case of error. If we only want to terminate in case of
error, following might be better.

	} else if (device_attach(&device->dev) < 0) {

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

* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2013-01-11 20:37                 ` Mika Westerberg
@ 2013-01-11 20:58                   ` Rafael J. Wysocki
  2013-01-11 20:59                     ` Mika Westerberg
  0 siblings, 1 reply; 88+ messages in thread
From: Rafael J. Wysocki @ 2013-01-11 20:58 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Friday, January 11, 2013 10:37:59 PM Mika Westerberg wrote:
> On Fri, Jan 11, 2013 at 09:31:43PM +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > Subject: ACPI / scan: Fix check of device_attach() return value.
> > 
> > Since device_attach() returns 1 on success and 0 on failure,
> > the check against its return value in acpi_bus_device_attach()
> > should be reveresed.  Make it so.
> 
> Not sure if it matters but it returns 0 if no device was bound to a driver
> and -ENODEV in case of error. If we only want to terminate in case of
> error, following might be better.
> 
> 	} else if (device_attach(&device->dev) < 0) {

Yes, this check will be better.

Which means that the patch is actually yours, so I've just added the changelog. :-)

Thanks,
Rafael


---
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Subject: ACPI / scan: Fix check of device_attach() return value.

Since device_attach() returns 1 on success (a driver has been bound
to the device), the check against its return value in
acpi_bus_device_attach() should modified to take that into accout.
Make it so.

[rjw: Subject and changelog.]
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/acpi/scan.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -1598,7 +1598,7 @@ static acpi_status acpi_bus_device_attac
 	if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
 		/* This is a known good platform device. */
 		acpi_create_platform_device(device);
-	} else if (device_attach(&device->dev)) {
+	} else if (device_attach(&device->dev) < 0) {
 		status = AE_CTRL_DEPTH;
 	}
 	return status;


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

* Re: [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers
  2013-01-11 20:58                   ` Rafael J. Wysocki
@ 2013-01-11 20:59                     ` Mika Westerberg
  0 siblings, 0 replies; 88+ messages in thread
From: Mika Westerberg @ 2013-01-11 20:59 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Toshi Kani, Bjorn Helgaas, LKML,
	linux-pci, Yinghai Lu, Myron Stowe, Yijing Wang, Jiang Liu

On Fri, Jan 11, 2013 at 09:58:50PM +0100, Rafael J. Wysocki wrote:
> On Friday, January 11, 2013 10:37:59 PM Mika Westerberg wrote:
> > On Fri, Jan 11, 2013 at 09:31:43PM +0100, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > Subject: ACPI / scan: Fix check of device_attach() return value.
> > > 
> > > Since device_attach() returns 1 on success and 0 on failure,
> > > the check against its return value in acpi_bus_device_attach()
> > > should be reveresed.  Make it so.
> > 
> > Not sure if it matters but it returns 0 if no device was bound to a driver
> > and -ENODEV in case of error. If we only want to terminate in case of
> > error, following might be better.
> > 
> > 	} else if (device_attach(&device->dev) < 0) {
> 
> Yes, this check will be better.
> 
> Which means that the patch is actually yours, so I've just added the changelog. :-)
> 

Thanks! (and I've tested this, it works ;-))

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

end of thread, other threads:[~2013-01-11 20:59 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-09 22:58 [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Rafael J. Wysocki
2012-12-09 23:00 ` [PATCH 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
2012-12-12 15:50   ` Jiang Liu
2012-12-12 22:34     ` Rafael J. Wysocki
2012-12-12 16:38   ` Jiang Liu
2012-12-12 22:32     ` Rafael J. Wysocki
2012-12-12 23:43       ` [update][PATCH " Rafael J. Wysocki
2012-12-13 13:05       ` [PATCH " Jiang Liu
2012-12-13 19:40         ` Rafael J. Wysocki
2012-12-13  1:00   ` Bjorn Helgaas
2012-12-13 11:41     ` Rafael J. Wysocki
2012-12-09 23:00 ` [PATCH 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
2012-12-13  1:00   ` Bjorn Helgaas
2012-12-13 12:19     ` Rafael J. Wysocki
2012-12-09 23:01 ` [PATCH 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
2012-12-13  0:11   ` [Update][PATCH " Rafael J. Wysocki
2012-12-09 23:02 ` [PATCH 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
2012-12-09 23:03 ` [PATCH 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
2012-12-10  5:34   ` Yinghai Lu
2012-12-10 14:46     ` Rafael J. Wysocki
2012-12-10 17:07       ` Yinghai Lu
2012-12-10 22:47         ` Rafael J. Wysocki
2012-12-10 23:09           ` Rafael J. Wysocki
2012-12-10 23:14             ` Yinghai Lu
2012-12-11  1:02               ` Rafael J. Wysocki
2012-12-11  1:28                 ` Rafael J. Wysocki
2012-12-11  2:26                   ` Yinghai Lu
2012-12-11 12:45                     ` Rafael J. Wysocki
2012-12-11 15:09                     ` Jiang Liu
2012-12-11 18:30                       ` Rafael J. Wysocki
2012-12-12 14:34                         ` Yijing Wang
2012-12-12 15:05                           ` Jiang Liu
2012-12-12 22:39                             ` Rafael J. Wysocki
2012-12-10 23:22           ` Yinghai Lu
2012-12-11  0:48             ` Rafael J. Wysocki
2012-12-09 23:04 ` [PATCH 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
2012-12-13  1:00   ` Bjorn Helgaas
2012-12-13 12:20     ` Rafael J. Wysocki
2012-12-13 11:45 ` [PATCH 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
2012-12-13 22:15 ` [PATCH rev.2 " Rafael J. Wysocki
2012-12-13 22:17   ` [PATCH rev.2 1/6] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
2012-12-18  0:08     ` Toshi Kani
2012-12-18  1:48       ` Rafael J. Wysocki
2012-12-18 16:10         ` Toshi Kani
2012-12-18 18:59           ` Yinghai Lu
2012-12-18 20:48             ` Toshi Kani
2012-12-18 21:11               ` Yinghai Lu
2012-12-18 22:05             ` Rafael J. Wysocki
2012-12-19  1:57               ` Yinghai Lu
2012-12-18 21:57           ` Rafael J. Wysocki
2012-12-18 22:15             ` Toshi Kani
2012-12-18 23:00               ` Rafael J. Wysocki
2012-12-18 23:19                 ` Bjorn Helgaas
2012-12-19 11:13                   ` Rafael J. Wysocki
2012-12-20  1:45         ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Rafael J. Wysocki
2012-12-20  1:47           ` [PATCH 1/16] ACPI: Separate adding ACPI device objects from probing ACPI drivers Rafael J. Wysocki
2013-01-11 20:00             ` Mika Westerberg
2013-01-11 20:31               ` Rafael J. Wysocki
2013-01-11 20:37                 ` Mika Westerberg
2013-01-11 20:58                   ` Rafael J. Wysocki
2013-01-11 20:59                     ` Mika Westerberg
2012-12-20  1:48           ` [PATCH 2/16] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
2012-12-20  1:49           ` [PATCH 3/16] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
2012-12-20  1:50           ` [PATCH 4/16] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
2012-12-20  1:50           ` [PATCH 5/16] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
2012-12-20  1:51           ` [PATCH 6/16] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
2012-12-20  1:52           ` [PATCH 7/16] ACPI / PCI: Fold acpi_pci_root_start() into acpi_pci_root_add() Rafael J. Wysocki
2012-12-20  1:53           ` [PATCH 8/16] ACPI: Remove acpi_start_single_object() and acpi_bus_start() Rafael J. Wysocki
2012-12-20  1:54           ` [PATCH 9/16] ACPI: Remove the arguments of acpi_bus_add() that are not used Rafael J. Wysocki
2012-12-20  1:54           ` [PATCH 10/16] ACPI: Drop the second argument of acpi_bus_scan() Rafael J. Wysocki
2012-12-20  1:55           ` [PATCH 11/16] ACPI: Replace ACPI device add_type field with a match_driver flag Rafael J. Wysocki
2012-12-20  1:56           ` [PATCH 12/16] ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument Rafael J. Wysocki
2012-12-20  1:57           ` [PATCH 13/16] ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type Rafael J. Wysocki
2012-12-20  1:58           ` [PATCH 14/16] ACPI / PCI: Rework the setup and cleanup of device wakeup Rafael J. Wysocki
2012-12-20  1:59           ` [PATCH 15/16] ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c Rafael J. Wysocki
2012-12-20  2:06           ` [PATCH 0/16] ACPI: Rework ACPI namespace scanning for devices Yinghai Lu
2012-12-21  0:09             ` Rafael J. Wysocki
2012-12-21  3:59               ` Yinghai Lu
2012-12-21 22:23                 ` Rafael J. Wysocki
2012-12-20 21:07           ` Toshi Kani
2012-12-20 23:20             ` Rafael J. Wysocki
2012-12-13 22:18   ` [PATCH rev.2 2/6] ACPI: Change the ordering of PCI root bridge driver registrarion Rafael J. Wysocki
2012-12-13 22:21   ` [PATCH rev.2 3/6] ACPI: Make acpi_bus_add() and acpi_bus_start() visibly different Rafael J. Wysocki
2012-12-13 22:21   ` [PATCH rev.2 4/6] ACPI: Reduce the usage of struct acpi_bus_ops Rafael J. Wysocki
2012-12-13 22:22   ` [PATCH rev.2 5/6] ACPI: Replace struct acpi_bus_ops with enum type Rafael J. Wysocki
2012-12-13 22:23   ` [PATCH rev.2 6/6] ACPI: Change the ordering of acpi_bus_check_add() Rafael J. Wysocki
2012-12-14  9:56   ` [PATCH rev.2 0/6] ACPI: Change the ACPI namespace scanning code ordering Yijing Wang
2012-12-14 22:59     ` Rafael J. Wysocki

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).