linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently
@ 2014-01-27  0:37 Rafael J. Wysocki
  2014-01-27  0:38 ` [PATCH 1/11] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
                   ` (13 more replies)
  0 siblings, 14 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:37 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

Hi All,

ACPIPHP can be simplified a bit on top of some PCI and ACPI changes merged
recently and the following series of patches implements those simplifications:

[1/11] Fix up two kerneldoc comments in acpiphp_glue.c.
[2/11] Get rid of an unnecessary label in register_slot().
[3/11] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
[4/11] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
[5/11] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
[6/11] Drop acpiphp_bus_add() (which has only one user).
[7/11] Drop crit_sect mutexes (that are redundant).
[8/11] Clean up the usage of the slot variable in hotplug_event().
[9/11] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
[10/11] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
[11/11] Drop handle argument from the member functions of struct acpi_dock_ops.

All of that is relateively straightforward, but I have some more intrusive changes
on top of it in the works.  They will be posted separately later this week.

Thanks!

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

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

* [PATCH 1/11] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
@ 2014-01-27  0:38 ` Rafael J. Wysocki
  2014-01-27  0:38 ` [PATCH 2/11] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:38 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Add proper kerneldoc comments describing acpiphp_enumerate_slots()
and acpiphp_remove_slots().

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -986,9 +986,12 @@ static void handle_hotplug_event(acpi_ha
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-/*
- * Create hotplug slots for the PCI bus.
- * It should always return 0 to avoid skipping following notifiers.
+/**
+ * acpiphp_enumerate_slots - Enumerate PCI slots for a given bus.
+ * @bus: PCI bus to enumerate the slots for.
+ *
+ * A "slot" is an object associated with a PCI device number.  All functions
+ * (PCI devices) with the same bus and device number belong to the same slot.
  */
 void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
@@ -1061,7 +1064,10 @@ void acpiphp_enumerate_slots(struct pci_
 	}
 }
 
-/* Destroy hotplug slots associated with the PCI bus */
+/**
+ * acpiphp_remove_slots - Remove slot objects associated with a given bus.
+ * @bus: PCI bus to remove the slot objects for.
+ */
 void acpiphp_remove_slots(struct pci_bus *bus)
 {
 	struct acpiphp_bridge *bridge;


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

* [PATCH 2/11] ACPI / hotplug / PCI: Simplify register_slot()
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
  2014-01-27  0:38 ` [PATCH 1/11] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
@ 2014-01-27  0:38 ` Rafael J. Wysocki
  2014-01-27  0:39 ` [PATCH 3/11] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:38 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

The err label in register_slot() is only jumped to from one place,
so move the code under the label to that place and drop the label.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -316,8 +316,10 @@ static acpi_status register_slot(acpi_ha
 
 	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 	if (!slot) {
-		status = AE_NO_MEMORY;
-		goto err;
+		mutex_lock(&acpiphp_context_lock);
+		acpiphp_put_context(context);
+		mutex_unlock(&acpiphp_context_lock);
+		return AE_NO_MEMORY;
 	}
 
 	slot->bus = bridge->pci_bus;
@@ -385,12 +387,6 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	return AE_OK;
-
- err:
-	mutex_lock(&acpiphp_context_lock);
-	acpiphp_put_context(context);
-	mutex_unlock(&acpiphp_context_lock);
-	return status;
 }
 
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)


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

* [PATCH 3/11] ACPI / hotplug / PCI: Drop acpiphp_bus_trim()
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
  2014-01-27  0:38 ` [PATCH 1/11] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
  2014-01-27  0:38 ` [PATCH 2/11] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
@ 2014-01-27  0:39 ` Rafael J. Wysocki
  2014-01-27  0:40 ` [PATCH 4/11] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:39 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

If trim_stale_devices() calls acpi_bus_trim() directly, we can
save a potentially costly acpi_bus_get_device() invocation.  After
making that change acpiphp_bus_trim() would only be called from one
place, so move the code from it to that place and drop it.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -468,19 +468,6 @@ static unsigned char acpiphp_max_busnr(s
 }
 
 /**
- * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree.
- * @handle: ACPI device object handle to start from.
- */
-static void acpiphp_bus_trim(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
-	if (adev)
-		acpi_bus_trim(adev);
-}
-
-/**
  * acpiphp_bus_add - Scan ACPI namespace subtree.
  * @handle: ACPI object handle to start the scan from.
  */
@@ -638,8 +625,12 @@ static void disable_slot(struct acpiphp_
 		pci_dev_put(pdev);
 	}
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_trim(func_to_handle(func));
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev;
+
+		if (!acpi_bus_get_device(func_to_handle(func), &adev))
+			acpi_bus_trim(adev);
+	}
 
 	slot->flags &= (~SLOT_ENABLED);
 }
@@ -711,11 +702,12 @@ static unsigned int get_slot_status(stru
  */
 static void trim_stale_devices(struct pci_dev *dev)
 {
-	acpi_handle handle = ACPI_HANDLE(&dev->dev);
+	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
 	struct pci_bus *bus = dev->subordinate;
 	bool alive = false;
 
-	if (handle) {
+	if (adev) {
+		acpi_handle handle = adev->handle;
 		acpi_status status;
 		unsigned long long sta;
 
@@ -731,8 +723,8 @@ static void trim_stale_devices(struct pc
 	}
 	if (!alive) {
 		pci_stop_and_remove_bus_device(dev);
-		if (handle)
-			acpiphp_bus_trim(handle);
+		if (adev)
+			acpi_bus_trim(adev);
 	} else if (bus) {
 		struct pci_dev *child, *tmp;
 


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

* [PATCH 4/11] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug()
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (2 preceding siblings ...)
  2014-01-27  0:39 ` [PATCH 3/11] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
@ 2014-01-27  0:40 ` Rafael J. Wysocki
  2014-01-27  0:41 ` [PATCH 5/11] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:40 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

If a struct acpi_device pointer is passed to acpiphp_no_hotplug()
instead of an ACPI handle, the function won't need to call
acpi_bus_get_device(), which may be costly, any more.  Then,
trim_stale_devices() can call acpiphp_no_hotplug() passing
the struct acpi_device object it already has directly to that
function.

Make those changes and update slot_no_hotplug() accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -635,11 +635,8 @@ static void disable_slot(struct acpiphp_
 	slot->flags &= (~SLOT_ENABLED);
 }
 
-static bool acpiphp_no_hotplug(acpi_handle handle)
+static bool acpiphp_no_hotplug(struct acpi_device *adev)
 {
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
 	return adev && adev->flags.no_hotplug;
 }
 
@@ -647,10 +644,13 @@ static bool slot_no_hotplug(struct acpip
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		if (acpiphp_no_hotplug(func_to_handle(func)))
-			return true;
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev = NULL;
 
+		acpi_bus_get_device(func_to_handle(func), &adev);
+		if (acpiphp_no_hotplug(adev))
+			return true;
+	}
 	return false;
 }
 
@@ -707,13 +707,12 @@ static void trim_stale_devices(struct pc
 	bool alive = false;
 
 	if (adev) {
-		acpi_handle handle = adev->handle;
 		acpi_status status;
 		unsigned long long sta;
 
-		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+		status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
 		alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
-			|| acpiphp_no_hotplug(handle);
+			|| acpiphp_no_hotplug(adev);
 	}
 	if (!alive) {
 		u32 v;


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

* [PATCH 5/11] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (3 preceding siblings ...)
  2014-01-27  0:40 ` [PATCH 4/11] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
@ 2014-01-27  0:41 ` Rafael J. Wysocki
  2014-01-27  0:41 ` [PATCH 6/11] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:41 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

After recent modifications of the ACPI core making it create a struct
acpi_device object for every namespace node representing a device
regardless of the current status of that device the ACPIPHP code
can store a struct acpi_device pointer instead of an ACPI handle
in struct acpiphp_context.  This immediately makes it possible to
avoid making potentially costly calls to acpi_bus_get_device() in
two places and allows some more simplifications to be made going
forward.

The reason why that is correct is because ACPIPHP only installs
hotify handlers for namespace nodes that exist when
acpiphp_enumerate_slots() is called for their parent bridge.
That only happens if the parent bridge has an ACPI companion
associated with it, which means that the ACPI namespace scope
in question has been scanned already at that point.  That, in
turn, means that struct acpi_device objects have been created
for all namespace nodes in that scope and pointers to those
objects can be stored directly instead of their ACPI handles.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp.h      |    9 +++++--
 drivers/pci/hotplug/acpiphp_glue.c |   44 +++++++++++++++++--------------------
 2 files changed, 28 insertions(+), 25 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -117,8 +117,8 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
-	acpi_handle handle;
 	struct acpiphp_func func;
+	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
@@ -128,9 +128,14 @@ static inline struct acpiphp_context *fu
 	return container_of(func, struct acpiphp_context, func);
 }
 
+static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
+{
+	return func_to_context(func)->adev;
+}
+
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
 {
-	return func_to_context(func)->handle;
+	return func_to_acpi_device(func)->handle;
 }
 
 /*
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -73,11 +73,11 @@ static void acpiphp_context_handler(acpi
 
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
- * @handle: ACPI object handle to create the context for.
+ * @adev: ACPI device object to create the context for.
  *
  * Call under acpiphp_context_lock.
  */
-static struct acpiphp_context *acpiphp_init_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
 	acpi_status status;
@@ -86,9 +86,9 @@ static struct acpiphp_context *acpiphp_i
 	if (!context)
 		return NULL;
 
-	context->handle = handle;
+	context->adev = adev;
 	context->refcount = 1;
-	status = acpi_attach_data(handle, acpiphp_context_handler, context);
+	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
 	if (ACPI_FAILURE(status)) {
 		kfree(context);
 		return NULL;
@@ -118,7 +118,7 @@ static struct acpiphp_context *acpiphp_g
 
 /**
  * acpiphp_put_context - Drop a reference to ACPI hotplug context.
- * @handle: ACPI object handle to put the context for.
+ * @context: ACPI hotplug context to drop a reference to.
  *
  * The context object is removed if there are no more references to it.
  *
@@ -130,7 +130,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->handle, acpiphp_context_handler);
+	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
 	kfree(context);
 }
 
@@ -265,6 +265,7 @@ static acpi_status register_slot(acpi_ha
 {
 	struct acpiphp_bridge *bridge = data;
 	struct acpiphp_context *context;
+	struct acpi_device *adev;
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *newfunc;
 	acpi_status status = AE_OK;
@@ -284,12 +285,14 @@ static acpi_status register_slot(acpi_ha
 				"can't evaluate _ADR (%#x)\n", status);
 		return AE_OK;
 	}
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
 
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 
 	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_init_context(handle);
+	context = acpiphp_init_context(adev);
 	if (!context) {
 		mutex_unlock(&acpiphp_context_lock);
 		acpi_handle_err(handle, "No hotplug context\n");
@@ -625,12 +628,8 @@ static void disable_slot(struct acpiphp_
 		pci_dev_put(pdev);
 	}
 
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		struct acpi_device *adev;
-
-		if (!acpi_bus_get_device(func_to_handle(func), &adev))
-			acpi_bus_trim(adev);
-	}
+	list_for_each_entry(func, &slot->funcs, sibling)
+		acpi_bus_trim(func_to_acpi_device(func));
 
 	slot->flags &= (~SLOT_ENABLED);
 }
@@ -644,13 +643,10 @@ static bool slot_no_hotplug(struct acpip
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		struct acpi_device *adev = NULL;
-
-		acpi_bus_get_device(func_to_handle(func), &adev);
-		if (acpiphp_no_hotplug(adev))
+	list_for_each_entry(func, &slot->funcs, sibling)
+		if (acpiphp_no_hotplug(func_to_acpi_device(func)))
 			return true;
-	}
+
 	return false;
 }
 
@@ -899,7 +895,7 @@ static void hotplug_event(acpi_handle ha
 static void hotplug_event_work(void *data, u32 type)
 {
 	struct acpiphp_context *context = data;
-	acpi_handle handle = context->handle;
+	acpi_handle handle = context->adev->handle;
 
 	acpi_scan_lock_acquire();
 	pci_lock_rescan_remove();
@@ -959,7 +955,7 @@ static void handle_hotplug_event(acpi_ha
 
 	mutex_lock(&acpiphp_context_lock);
 	context = acpiphp_get_context(handle);
-	if (context && !WARN_ON(context->handle != handle)) {
+	if (context && !WARN_ON(context->adev->handle != handle)) {
 		get_bridge(context->func.parent);
 		acpiphp_put_context(context);
 		acpi_hotplug_execute(hotplug_event_work, context, type);
@@ -983,16 +979,18 @@ static void handle_hotplug_event(acpi_ha
 void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
 	struct acpiphp_bridge *bridge;
+	struct acpi_device *adev;
 	acpi_handle handle;
 	acpi_status status;
 
 	if (acpiphp_disabled)
 		return;
 
-	handle = ACPI_HANDLE(bus->bridge);
-	if (!handle)
+	adev = ACPI_COMPANION(bus->bridge);
+	if (!adev)
 		return;
 
+	handle = adev->handle;
 	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 	if (!bridge) {
 		acpi_handle_err(handle, "No memory for bridge object\n");


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

* [PATCH 6/11] ACPI / hotplug / PCI: Drop acpiphp_bus_add()
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (4 preceding siblings ...)
  2014-01-27  0:41 ` [PATCH 5/11] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
@ 2014-01-27  0:41 ` Rafael J. Wysocki
  2014-01-27  0:42 ` [PATCH 7/11] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:41 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

acpiphp_bus_add() is only called from one place, so move the code out
of it into that place and drop it.  Also make that code use
func_to_acpi_device() to get the struct acpi_device pointer it needs
instead of calling acpi_bus_get_device() which may be costly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -470,20 +470,6 @@ static unsigned char acpiphp_max_busnr(s
 	return max;
 }
 
-/**
- * acpiphp_bus_add - Scan ACPI namespace subtree.
- * @handle: ACPI object handle to start the scan from.
- */
-static void acpiphp_bus_add(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_scan(handle);
-	acpi_bus_get_device(handle, &adev);
-	if (acpi_device_enumerated(adev))
-		acpi_device_set_power(adev, ACPI_STATE_D0);
-}
-
 static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
 {
 	struct acpiphp_func *func;
@@ -523,9 +509,13 @@ static int acpiphp_rescan_slot(struct ac
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_add(func_to_handle(func));
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev = func_to_acpi_device(func);
 
+		acpi_bus_scan(adev->handle);
+		if (acpi_device_enumerated(adev))
+			acpi_device_set_power(adev, ACPI_STATE_D0);
+	}
 	return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0));
 }
 


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

* [PATCH 7/11] ACPI / hotplug / PCI: Drop crit_sect locking
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (5 preceding siblings ...)
  2014-01-27  0:41 ` [PATCH 6/11] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
@ 2014-01-27  0:42 ` Rafael J. Wysocki
  2014-01-27  0:43 ` [PATCH 8/11] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:42 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

After recent PCI core changes related to the rescan/remove locking,
the code sections under crit_sect mutexes from ACPIPHP slot objects
are always executed under the general PCI rescan/remove lock.
For this reason, the crit_sect mutexes are simply redundant, so drop
them.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp.h      |    1 -
 drivers/pci/hotplug/acpiphp_glue.c |   23 +++--------------------
 2 files changed, 3 insertions(+), 21 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -328,7 +328,6 @@ static acpi_status register_slot(acpi_ha
 	slot->bus = bridge->pci_bus;
 	slot->device = device;
 	INIT_LIST_HEAD(&slot->funcs);
-	mutex_init(&slot->crit_sect);
 
 	list_add_tail(&slot->node, &bridge->slots);
 
@@ -741,7 +740,6 @@ static void acpiphp_check_bridge(struct
 		struct pci_bus *bus = slot->bus;
 		struct pci_dev *dev, *tmp;
 
-		mutex_lock(&slot->crit_sect);
 		if (slot_no_hotplug(slot)) {
 			; /* do nothing */
 		} else if (get_slot_status(slot) == ACPI_STA_ALL) {
@@ -756,7 +754,6 @@ static void acpiphp_check_bridge(struct
 		} else {
 			disable_slot(slot);
 		}
-		mutex_unlock(&slot->crit_sect);
 	}
 }
 
@@ -838,12 +835,8 @@ static void hotplug_event(acpi_handle ha
 		} else {
 			struct acpiphp_slot *slot = func->slot;
 
-			if (slot->flags & SLOT_IS_GOING_AWAY)
-				break;
-
-			mutex_lock(&slot->crit_sect);
-			enable_slot(slot);
-			mutex_unlock(&slot->crit_sect);
+			if (!(slot->flags & SLOT_IS_GOING_AWAY))
+				enable_slot(slot);
 		}
 		break;
 
@@ -854,7 +847,6 @@ static void hotplug_event(acpi_handle ha
 			acpiphp_check_bridge(bridge);
 		} else {
 			struct acpiphp_slot *slot = func->slot;
-			int ret;
 
 			if (slot->flags & SLOT_IS_GOING_AWAY)
 				break;
@@ -863,10 +855,7 @@ static void hotplug_event(acpi_handle ha
 			 * Check if anything has changed in the slot and rescan
 			 * from the parent if that's the case.
 			 */
-			mutex_lock(&slot->crit_sect);
-			ret = acpiphp_rescan_slot(slot);
-			mutex_unlock(&slot->crit_sect);
-			if (ret)
+			if (acpiphp_rescan_slot(slot))
 				acpiphp_check_bridge(func->parent);
 		}
 		break;
@@ -1073,13 +1062,10 @@ int acpiphp_enable_slot(struct acpiphp_s
 	if (slot->flags & SLOT_IS_GOING_AWAY)
 		return -ENODEV;
 
-	mutex_lock(&slot->crit_sect);
 	/* configure all functions */
 	if (!(slot->flags & SLOT_ENABLED))
 		enable_slot(slot);
 
-	mutex_unlock(&slot->crit_sect);
-
 	pci_unlock_rescan_remove();
 	return 0;
 }
@@ -1095,8 +1081,6 @@ static int acpiphp_disable_and_eject_slo
 	if (slot->flags & SLOT_IS_GOING_AWAY)
 		return -ENODEV;
 
-	mutex_lock(&slot->crit_sect);
-
 	/* unconfigure all functions */
 	disable_slot(slot);
 
@@ -1110,7 +1094,6 @@ static int acpiphp_disable_and_eject_slo
 			break;
 		}
 
-	mutex_unlock(&slot->crit_sect);
 	return 0;
 }
 
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -93,7 +93,6 @@ struct acpiphp_slot {
 	struct list_head funcs;		/* one slot may have different
 					   objects (i.e. for each function) */
 	struct slot *slot;
-	struct mutex crit_sect;
 
 	u8		device;		/* pci device# */
 	u32		flags;		/* see below */


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

* [PATCH 8/11] ACPI / hotplug / PCI: Simplify hotplug_event()
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (6 preceding siblings ...)
  2014-01-27  0:42 ` [PATCH 7/11] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
@ 2014-01-27  0:43 ` Rafael J. Wysocki
  2014-01-27  0:44 ` [PATCH 9/11] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:43 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

A few lines of code can be cut from hotplug_event() by defining
and initializing the slot variable at the top of the function,
so do that.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -810,6 +810,7 @@ static void hotplug_event(acpi_handle ha
 {
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
+	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
 	char objname[64];
 	struct acpi_buffer buffer = { .length = sizeof(objname),
@@ -830,14 +831,11 @@ static void hotplug_event(acpi_handle ha
 		pr_debug("%s: Bus check notify on %s\n", __func__, objname);
 		pr_debug("%s: re-enumerating slots under %s\n",
 			 __func__, objname);
-		if (bridge) {
+		if (bridge)
 			acpiphp_check_bridge(bridge);
-		} else {
-			struct acpiphp_slot *slot = func->slot;
+		else if (!(slot->flags & SLOT_IS_GOING_AWAY))
+			enable_slot(slot);
 
-			if (!(slot->flags & SLOT_IS_GOING_AWAY))
-				enable_slot(slot);
-		}
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
@@ -845,12 +843,7 @@ static void hotplug_event(acpi_handle ha
 		pr_debug("%s: Device check notify on %s\n", __func__, objname);
 		if (bridge) {
 			acpiphp_check_bridge(bridge);
-		} else {
-			struct acpiphp_slot *slot = func->slot;
-
-			if (slot->flags & SLOT_IS_GOING_AWAY)
-				break;
-
+		} else if (!(slot->flags & SLOT_IS_GOING_AWAY)) {
 			/*
 			 * Check if anything has changed in the slot and rescan
 			 * from the parent if that's the case.
@@ -863,7 +856,7 @@ static void hotplug_event(acpi_handle ha
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
 		pr_debug("%s: Device eject notify on %s\n", __func__, objname);
-		acpiphp_disable_and_eject_slot(func->slot);
+		acpiphp_disable_and_eject_slot(slot);
 		break;
 	}
 


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

* [PATCH 9/11] ACPI / hotplug / PCI: Simplify disable_slot()
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (7 preceding siblings ...)
  2014-01-27  0:43 ` [PATCH 8/11] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
@ 2014-01-27  0:44 ` Rafael J. Wysocki
  2014-01-27  0:45 ` [PATCH 10/11] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:44 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

After recent PCI core changes related to the rescan/remove locking,
the ACPIPHP's disable_slot() function is only called under the
general PCI rescan/remove lock, so it doesn't have to use
dev_in_slot() any more to avoid race conditions.  Make it simply
walk the devices on the bus and remove the ones in the slot being
disabled.  Then, drop dev_in_slot() which has no more users.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   28 +++++-----------------------
 1 file changed, 5 insertions(+), 23 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -579,32 +579,15 @@ static void __ref enable_slot(struct acp
 	}
 }
 
-/* return first device in slot, acquiring a reference on it */
-static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
-{
-	struct pci_bus *bus = slot->bus;
-	struct pci_dev *dev;
-	struct pci_dev *ret = NULL;
-
-	down_read(&pci_bus_sem);
-	list_for_each_entry(dev, &bus->devices, bus_list)
-		if (PCI_SLOT(dev->devfn) == slot->device) {
-			ret = pci_dev_get(dev);
-			break;
-		}
-	up_read(&pci_bus_sem);
-
-	return ret;
-}
-
 /**
  * disable_slot - disable a slot
  * @slot: ACPI PHP slot
  */
 static void disable_slot(struct acpiphp_slot *slot)
 {
+	struct pci_bus *bus = slot->bus;
+	struct pci_dev *dev, *next;
 	struct acpiphp_func *func;
-	struct pci_dev *pdev;
 
 	/*
 	 * enable_slot() enumerates all functions in this device via
@@ -612,10 +595,9 @@ static void disable_slot(struct acpiphp_
 	 * methods (_EJ0, etc.) or not.  Therefore, we remove all functions
 	 * here.
 	 */
-	while ((pdev = dev_in_slot(slot))) {
-		pci_stop_and_remove_bus_device(pdev);
-		pci_dev_put(pdev);
-	}
+	list_for_each_entry_safe(dev, next, &bus->devices, bus_list)
+		if (PCI_SLOT(dev->devfn) == slot->device)
+			pci_stop_and_remove_bus_device(dev);
 
 	list_for_each_entry(func, &slot->funcs, sibling)
 		acpi_bus_trim(func_to_acpi_device(func));


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

* [PATCH 10/11] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event()
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (8 preceding siblings ...)
  2014-01-27  0:44 ` [PATCH 9/11] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
@ 2014-01-27  0:45 ` Rafael J. Wysocki
  2014-01-27  0:46 ` [PATCH 11/11] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations Rafael J. Wysocki
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:45 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Make hotplug_event() use acpi_handle_debug() instead of an open-coded
debug message printing and clean up the messages printed by it.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -794,9 +794,6 @@ static void hotplug_event(acpi_handle ha
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
-	char objname[64];
-	struct acpi_buffer buffer = { .length = sizeof(objname),
-				      .pointer = objname };
 
 	mutex_lock(&acpiphp_context_lock);
 	bridge = context->bridge;
@@ -805,14 +802,10 @@ static void hotplug_event(acpi_handle ha
 
 	mutex_unlock(&acpiphp_context_lock);
 
-	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		/* bus re-enumerate */
-		pr_debug("%s: Bus check notify on %s\n", __func__, objname);
-		pr_debug("%s: re-enumerating slots under %s\n",
-			 __func__, objname);
+		acpi_handle_debug(handle, "Bus check in %s()\n", __func__);
 		if (bridge)
 			acpiphp_check_bridge(bridge);
 		else if (!(slot->flags & SLOT_IS_GOING_AWAY))
@@ -822,7 +815,7 @@ static void hotplug_event(acpi_handle ha
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		/* device check */
-		pr_debug("%s: Device check notify on %s\n", __func__, objname);
+		acpi_handle_debug(handle, "Device check in %s()\n", __func__);
 		if (bridge) {
 			acpiphp_check_bridge(bridge);
 		} else if (!(slot->flags & SLOT_IS_GOING_AWAY)) {
@@ -837,7 +830,7 @@ static void hotplug_event(acpi_handle ha
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
-		pr_debug("%s: Device eject notify on %s\n", __func__, objname);
+		acpi_handle_debug(handle, "Eject request in %s()\n", __func__);
 		acpiphp_disable_and_eject_slot(slot);
 		break;
 	}


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

* [PATCH 11/11] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (9 preceding siblings ...)
  2014-01-27  0:45 ` [PATCH 10/11] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
@ 2014-01-27  0:46 ` Rafael J. Wysocki
  2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-27  0:46 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

None of the existing users of struct acpi_dock_ops actually needs the
first argument of its member functions, so redefine those functions
to take only two arguments, the event type and data pointer, and
update the users of struct acpi_dock_ops accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/dock.c                |    4 ++--
 drivers/ata/libata-acpi.c          |    8 ++++----
 drivers/pci/hotplug/acpiphp_glue.c |   13 +++++++------
 include/acpi/acpi_drivers.h        |    6 +++---
 4 files changed, 16 insertions(+), 15 deletions(-)

Index: linux-pm/include/acpi/acpi_drivers.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_drivers.h
+++ linux-pm/include/acpi/acpi_drivers.h
@@ -110,9 +110,9 @@ void pci_acpi_crs_quirks(void);
                                   Dock Station
   -------------------------------------------------------------------------- */
 struct acpi_dock_ops {
-	acpi_notify_handler fixup;
-	acpi_notify_handler handler;
-	acpi_notify_handler uevent;
+	void (*handler)(u32 event_type, void *data);
+	void (*fixup)(u32 event_type, void *data);
+	void (*uevent)(u32 event_type, void *data);
 };
 
 #ifdef CONFIG_ACPI_DOCK
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -63,7 +63,7 @@ static DEFINE_MUTEX(acpiphp_context_lock
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
-static void hotplug_event(acpi_handle handle, u32 type, void *data);
+static void hotplug_event(u32 type, void *data);
 static void free_bridge(struct kref *kref);
 
 static void acpiphp_context_handler(acpi_handle handle, void *context)
@@ -185,7 +185,7 @@ static void free_bridge(struct kref *kre
  * TBD - figure out a way to only call fixups for
  * systems that require them.
  */
-static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
+static void post_dock_fixups(u32 event, void *data)
 {
 	struct acpiphp_context *context = data;
 	struct pci_bus *bus = context->func.slot->bus;
@@ -788,11 +788,12 @@ void acpiphp_check_host_bridge(acpi_hand
 
 static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot);
 
-static void hotplug_event(acpi_handle handle, u32 type, void *data)
+static void hotplug_event(u32 type, void *data)
 {
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
+	acpi_handle handle = context->adev->handle;
 	struct acpiphp_bridge *bridge;
 
 	mutex_lock(&acpiphp_context_lock);
@@ -842,16 +843,16 @@ static void hotplug_event(acpi_handle ha
 static void hotplug_event_work(void *data, u32 type)
 {
 	struct acpiphp_context *context = data;
-	acpi_handle handle = context->adev->handle;
 
 	acpi_scan_lock_acquire();
 	pci_lock_rescan_remove();
 
-	hotplug_event(handle, type, context);
+	hotplug_event(type, context);
 
 	pci_unlock_rescan_remove();
 	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
+	acpi_evaluate_hotplug_ost(context->adev->handle, type,
+				  ACPI_OST_SC_SUCCESS, NULL);
 	put_bridge(context->func.parent);
 }
 
Index: linux-pm/drivers/acpi/dock.c
===================================================================
--- linux-pm.orig/drivers/acpi/dock.c
+++ linux-pm/drivers/acpi/dock.c
@@ -185,7 +185,7 @@ static void dock_release_hotplug(struct
 static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
 			       enum dock_callback_type cb_type)
 {
-	acpi_notify_handler cb = NULL;
+	void (*cb)(u32, void *) = NULL;
 	bool run = false;
 
 	mutex_lock(&hotplug_lock);
@@ -213,7 +213,7 @@ static void dock_hotplug_event(struct do
 		return;
 
 	if (cb)
-		cb(dd->handle, event, dd->hp_context);
+		cb(event, dd->hp_context);
 
 	dock_release_hotplug(dd);
 }
Index: linux-pm/drivers/ata/libata-acpi.c
===================================================================
--- linux-pm.orig/drivers/ata/libata-acpi.c
+++ linux-pm/drivers/ata/libata-acpi.c
@@ -121,14 +121,14 @@ static void ata_acpi_handle_hotplug(stru
 		ata_port_wait_eh(ap);
 }
 
-static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_dev_notify_dock(u32 event, void *data)
 {
 	struct ata_device *dev = data;
 
 	ata_acpi_handle_hotplug(dev->link->ap, dev, event);
 }
 
-static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_ap_notify_dock(u32 event, void *data)
 {
 	struct ata_port *ap = data;
 
@@ -154,12 +154,12 @@ static void ata_acpi_uevent(struct ata_p
 	}
 }
 
-static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_ap_uevent(u32 event, void *data)
 {
 	ata_acpi_uevent(data, NULL, event);
 }
 
-static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_dev_uevent(u32 event, void *data)
 {
 	struct ata_device *dev = data;
 	ata_acpi_uevent(dev->link->ap, dev, event);


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

* [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (10 preceding siblings ...)
  2014-01-27  0:46 ` [PATCH 11/11] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations Rafael J. Wysocki
@ 2014-01-28 22:10 ` Rafael J. Wysocki
  2014-01-28 22:12   ` [PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
                     ` (5 more replies)
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
  2014-02-11  0:19 ` [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Bjorn Helgaas
  13 siblings, 6 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 22:10 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

Hi All,

It looks like there's time for more adventurous stuff. :-)

The following series is on top of the one I sent on Sunday:

https://lkml.org/lkml/2014/1/26/191

The final outcome of the patches below is that all ACPI hotplug notifications
for PCI devices and for core system things like CPU, memory, PCI roots etc.,
will be dispatched from acpi_bus_notify() and it is not necessary to install a
separate hotplug notify handler for each device any more.

[1/5] Attach ACPIPHP hotplug contexts to struct acpi_device objects.
[2/5] Introduce wrappers for installing and removing hotplug notify handlers
      (those wrappers go away later on, but they are useful for separating
       changes).
[3/5] Consolidate ACPI hotplug signaling for PCI and ACPI core.
[4/5] Simplify notify handle registration wrapper.
[5/5] Dispatch ACPI hotplug notifications for "core" devices and PCI from acpi_bus_notify().

The ACPIPHP part of this has been tested on Acer Aspire S5 with Thunderbolt
hotplug, but if you have access to systems with hot-removable CPUs, PCI host
bridges and such things, please check if the above changes don't break them.

Thanks!

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

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

* [PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device
  2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
@ 2014-01-28 22:12   ` Rafael J. Wysocki
  2014-01-28 22:13   ` [PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler() Rafael J. Wysocki
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 22:12 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its
hotplug context objects directly to ACPI namespace nodes representing
hotplug devices.  However, after recent changes causing struct
acpi_device to be created for every namespace node representing a
device (regardless of its status), that is not necessary any more.
Moreover, it's vulnerable to a theoretical issue that the ACPI
handle passed in the context between handle_hotplug_event() and
hotplug_event_work() may become invalid in the meantime (as a
result of a concurrent table unload).

For this reason, modify the code to attach the ACPIPHP's device
hotplug contexts to struct device objects representing hotplug
devices.

This also allows further consolidation of the ACPI hotplug code
to be carried out in subsequent changesets.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |    3 +
 drivers/pci/hotplug/acpiphp.h      |    9 ++-
 drivers/pci/hotplug/acpiphp_glue.c |   99 ++++++++++++++++++++++---------------
 include/acpi/acpi_bus.h            |   11 ++++
 4 files changed, 80 insertions(+), 42 deletions(-)

Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -139,6 +139,16 @@ struct acpi_scan_handler {
 };
 
 /*
+ * ACPI Hotplug Context
+ * --------------------
+ */
+
+struct acpi_hotplug_context {
+	struct acpi_device *self;
+	void (*release)(struct acpi_hotplug_context *);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -331,6 +341,7 @@ struct acpi_device {
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
 	struct acpi_scan_handler *handler;
+	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -1063,6 +1063,9 @@ static void acpi_device_del_work_fn(stru
 		mutex_unlock(&acpi_device_del_lock);
 
 		acpi_device_del(adev);
+		if (adev->hp && adev->hp->release)
+			adev->hp->release(adev->hp);
+
 		/*
 		 * Drop references to all power resources that might have been
 		 * used by the device.
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -116,12 +116,17 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
+	struct acpi_hotplug_context hp;
 	struct acpiphp_func func;
-	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
 
+static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
+{
+	return container_of(hp, struct acpiphp_context, hp);
+}
+
 static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
 {
 	return container_of(func, struct acpiphp_context, func);
@@ -129,7 +134,7 @@ static inline struct acpiphp_context *fu
 
 static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
 {
-	return func_to_context(func)->adev;
+	return func_to_context(func)->hp.self;
 }
 
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -53,9 +53,13 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 
+#include <asm/pgtable.h>
+
 #include "../pci.h"
 #include "acpiphp.h"
 
+#define INVALID_ACPI_HANDLE	((acpi_handle)empty_zero_page)
+
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 static DEFINE_MUTEX(acpiphp_context_lock);
@@ -66,9 +70,9 @@ static void acpiphp_set_hpp_values(struc
 static void hotplug_event(u32 type, void *data);
 static void free_bridge(struct kref *kref);
 
-static void acpiphp_context_handler(acpi_handle handle, void *context)
+static void acpiphp_free_context(struct acpi_hotplug_context *hp)
 {
-	/* Intentionally empty. */
+	kfree(to_acpiphp_context(hp));
 }
 
 /**
@@ -80,39 +84,29 @@ static void acpiphp_context_handler(acpi
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
-	acpi_status status;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return NULL;
 
-	context->adev = adev;
+	context->hp.self = adev;
+	context->hp.release = acpiphp_free_context;
 	context->refcount = 1;
-	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
-	if (ACPI_FAILURE(status)) {
-		kfree(context);
-		return NULL;
-	}
+	adev->hp = &context->hp;
 	return context;
 }
 
 /**
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
- * @handle: ACPI object handle to get the context for.
+ * @adev: ACPI device object to get the context for.
  *
  * Call under acpiphp_context_lock.
  */
-static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = NULL;
-	acpi_status status;
-	void *data;
+	struct acpiphp_context *context = to_acpiphp_context(adev->hp);
 
-	status = acpi_get_data(handle, acpiphp_context_handler, &data);
-	if (ACPI_SUCCESS(status)) {
-		context = data;
-		context->refcount++;
-	}
+	context->refcount++;
 	return context;
 }
 
@@ -130,7 +124,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
+	context->hp.self->hp = NULL;
 	kfree(context);
 }
 
@@ -395,9 +389,13 @@ static struct acpiphp_bridge *acpiphp_ha
 {
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
+	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return NULL;
 
 	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_get_context(handle);
+	context = acpiphp_get_context(adev);
 	if (context) {
 		bridge = context->bridge;
 		if (bridge)
@@ -793,7 +791,7 @@ static void hotplug_event(u32 type, void
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
-	acpi_handle handle = context->adev->handle;
+	acpi_handle handle = context->hp.self->handle;
 	struct acpiphp_bridge *bridge;
 
 	mutex_lock(&acpiphp_context_lock);
@@ -842,18 +840,39 @@ static void hotplug_event(u32 type, void
 
 static void hotplug_event_work(void *data, u32 type)
 {
-	struct acpiphp_context *context = data;
+	struct acpi_device *adev = data;
+	struct acpiphp_context *context;
+	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
 	acpi_scan_lock_acquire();
-	pci_lock_rescan_remove();
+	/*
+	 * The device object's ACPI handle cannot become invalid as long as we
+	 * are holding acpi_scan_lock, but it might have become invalid before
+	 * that lock was acquired.
+	 */
+	if (adev->handle == INVALID_ACPI_HANDLE)
+		goto out;
 
-	hotplug_event(type, context);
+	mutex_lock(&acpiphp_context_lock);
+	context = acpiphp_get_context(adev);
+	if (!context) {
+		mutex_unlock(&acpiphp_context_lock);
+		goto out;
+	}
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
+	mutex_unlock(&acpiphp_context_lock);
 
+	pci_lock_rescan_remove();
+	hotplug_event(type, context);
 	pci_unlock_rescan_remove();
-	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(context->adev->handle, type,
-				  ACPI_OST_SC_SUCCESS, NULL);
 	put_bridge(context->func.parent);
+	ost_code = ACPI_OST_SC_SUCCESS;
+
+ out:
+	acpi_evaluate_hotplug_ost(adev->handle, type, ost_code, NULL);
+	put_device(&adev->dev);
+	acpi_scan_lock_release();
 }
 
 /**
@@ -866,7 +885,8 @@ static void hotplug_event_work(void *dat
  */
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 {
-	struct acpiphp_context *context;
+	struct acpi_device *adev;
+	acpi_status status;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 
 	switch (type) {
@@ -901,17 +921,16 @@ static void handle_hotplug_event(acpi_ha
 		goto out;
 	}
 
-	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_get_context(handle);
-	if (context && !WARN_ON(context->adev->handle != handle)) {
-		get_bridge(context->func.parent);
-		acpiphp_put_context(context);
-		acpi_hotplug_execute(hotplug_event_work, context, type);
-		mutex_unlock(&acpiphp_context_lock);
-		return;
-	}
-	mutex_unlock(&acpiphp_context_lock);
 	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+	if (acpi_bus_get_device(handle, &adev))
+		goto out;
+
+	get_device(&adev->dev);
+	status = acpi_hotplug_execute(hotplug_event_work, adev, type);
+	if (ACPI_SUCCESS(status))
+		return;
+
+	put_device(&adev->dev);
 
  out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
@@ -967,7 +986,7 @@ void acpiphp_enumerate_slots(struct pci_
 		 * bridge is not interesting to us either.
 		 */
 		mutex_lock(&acpiphp_context_lock);
-		context = acpiphp_get_context(handle);
+		context = acpiphp_get_context(adev);
 		if (!context) {
 			mutex_unlock(&acpiphp_context_lock);
 			put_device(&bus->dev);


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

* [PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler()
  2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  2014-01-28 22:12   ` [PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
@ 2014-01-28 22:13   ` Rafael J. Wysocki
  2014-01-28 22:14   ` [PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 22:13 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Introduce a helper routine for installing acpi_hotplug_notify_cb()
as an ACPI notify handler for the given ACPI namespace node and make
acpi_scan_init_hotplug() use it.

This is to make subsequent changes easier to follow.

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

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -523,6 +523,18 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+{
+	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				    acpi_hotplug_notify_cb, data);
+}
+
+void acpi_remove_hotplug_notify_handler(acpi_handle handle)
+{
+	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				   acpi_hotplug_notify_cb);
+}
+
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1961,8 +1973,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					acpi_hotplug_notify_cb, handler);
+			acpi_install_hotplug_notify_handler(handle, handler);
 			break;
 		}
 	}
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -434,6 +434,8 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver


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

* [PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
  2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  2014-01-28 22:12   ` [PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
  2014-01-28 22:13   ` [PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-01-28 22:14   ` Rafael J. Wysocki
  2014-01-28 22:14   ` [PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 22:14 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Use the same ACPI notify handler, acpi_hotplug_notify_cb() for both
ACPI-based PCI hotplug (ACPIPHP) and the generic ACPI-based hotplug
of devices.  For PCI devices use the  .hp.event() callback from
their ACPI companions that points to acpiphp_hotplug_event().
For other devices (CPU, memory, containers, PCI host bridges) the
generic ACPI-based device hotplug code is used.

This allows code duplication between ACPIPHP and the ACPI core to be
reduced significantly and makes further ACPI-based device hotplug
consolidation possible.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |   85 ++++++++++++++++++----------
 drivers/pci/hotplug/acpiphp_glue.c |  110 +++----------------------------------
 include/acpi/acpi_bus.h            |    1 
 3 files changed, 66 insertions(+), 130 deletions(-)

Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -145,6 +145,7 @@ struct acpi_scan_handler {
 
 struct acpi_hotplug_context {
 	struct acpi_device *self;
+	int (*event)(struct acpi_device *, u32);
 	void (*release)(struct acpi_hotplug_context *);
 };
 
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -439,40 +439,44 @@ static int acpi_scan_bus_check(struct ac
 	return 0;
 }
 
+static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
+{
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		return acpi_scan_bus_check(adev);
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		return acpi_scan_device_check(adev);
+	case ACPI_NOTIFY_EJECT_REQUEST:
+	case ACPI_OST_EC_OSPM_EJECT:
+		return acpi_scan_hot_remove(adev);
+	}
+	return -EINVAL;
+}
+
 static void acpi_device_hotplug(void *data, u32 src)
 {
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev = data;
-	int error;
+	int error = -ENODEV;
 
 	lock_device_hotplug();
 	mutex_lock(&acpi_scan_lock);
 
 	/*
 	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it may have become invalid before
+	 * are holding acpi_scan_lock, but it might have become invalid before
 	 * that lock was acquired.
 	 */
 	if (adev->handle == INVALID_ACPI_HANDLE)
 		goto out;
 
-	switch (src) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		error = acpi_scan_bus_check(adev);
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		error = acpi_scan_device_check(adev);
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-	case ACPI_OST_EC_OSPM_EJECT:
-		error = acpi_scan_hot_remove(adev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
-	}
-	if (!error)
-		ost_code = ACPI_OST_SC_SUCCESS;
+	if (adev->handler)
+		error = acpi_generic_hotplug_event(adev, src);
+	else if (adev->hp && adev->hp->event)
+		error = adev->hp->event(adev, src);
+
+	if (error)
+		ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
  out:
 	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
@@ -483,35 +487,58 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_scan_handler *handler = data;
+	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
 
-	if (acpi_bus_get_device(handle, &adev))
-		goto err_out;
-
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (!handler->hotplug.enabled) {
+		if (handler && !handler->hotplug.enabled) {
 			acpi_handle_err(handle, "Eject disabled\n");
 			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto err_out;
+			goto out;
 		}
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
-	default:
-		/* non-hotplug event; possibly handled by other handler */
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
 		return;
+
+	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_POWER_FAULT:
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
+		goto out;
+
+	default:
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto out;
 	}
+
+	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+	if (acpi_bus_get_device(handle, &adev))
+		goto out;
+
 	get_device(&adev->dev);
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
@@ -519,7 +546,7 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	put_device(&adev->dev);
 
- err_out:
+ out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -53,18 +53,14 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 
-#include <asm/pgtable.h>
-
 #include "../pci.h"
 #include "acpiphp.h"
 
-#define INVALID_ACPI_HANDLE	((acpi_handle)empty_zero_page)
-
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 static DEFINE_MUTEX(acpiphp_context_lock);
 
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
 static void hotplug_event(u32 type, void *data);
@@ -91,6 +87,7 @@ static struct acpiphp_context *acpiphp_i
 
 	context->hp.self = adev;
 	context->hp.release = acpiphp_free_context;
+	context->hp.event = acpiphp_hotplug_event;
 	context->refcount = 1;
 	adev->hp = &context->hp;
 	return context;
@@ -373,14 +370,8 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-						     handle_hotplug_event,
-						     context);
-		if (ACPI_FAILURE(status))
-			acpi_handle_err(handle,
-					"failed to install notify handler\n");
-	}
+	if (!(newfunc->flags & FUNC_HAS_DCK))
+		acpi_install_hotplug_notify_handler(handle, NULL);
 
 	return AE_OK;
 }
@@ -411,7 +402,6 @@ static void cleanup_bridge(struct acpiph
 {
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
-	acpi_status status;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
@@ -420,13 +410,8 @@ static void cleanup_bridge(struct acpiph
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
 
-			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(handle,
-							ACPI_SYSTEM_NOTIFY,
-							handle_hotplug_event);
-				if (ACPI_FAILURE(status))
-					pr_err("failed to remove notify handler\n");
-			}
+			if (!(func->flags & FUNC_HAS_DCK))
+				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
@@ -838,26 +823,15 @@ static void hotplug_event(u32 type, void
 		put_bridge(bridge);
 }
 
-static void hotplug_event_work(void *data, u32 type)
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type)
 {
-	struct acpi_device *adev = data;
 	struct acpiphp_context *context;
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-
-	acpi_scan_lock_acquire();
-	/*
-	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it might have become invalid before
-	 * that lock was acquired.
-	 */
-	if (adev->handle == INVALID_ACPI_HANDLE)
-		goto out;
 
 	mutex_lock(&acpiphp_context_lock);
 	context = acpiphp_get_context(adev);
 	if (!context) {
 		mutex_unlock(&acpiphp_context_lock);
-		goto out;
+		return -ENODATA;
 	}
 	get_bridge(context->func.parent);
 	acpiphp_put_context(context);
@@ -867,73 +841,7 @@ static void hotplug_event_work(void *dat
 	hotplug_event(type, context);
 	pci_unlock_rescan_remove();
 	put_bridge(context->func.parent);
-	ost_code = ACPI_OST_SC_SUCCESS;
-
- out:
-	acpi_evaluate_hotplug_ost(adev->handle, type, ost_code, NULL);
-	put_device(&adev->dev);
-	acpi_scan_lock_release();
-}
-
-/**
- * handle_hotplug_event - handle ACPI hotplug event
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @data: pointer to acpiphp_context structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
-{
-	struct acpi_device *adev;
-	acpi_status status;
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
-		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
-
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-	if (acpi_bus_get_device(handle, &adev))
-		goto out;
-
-	get_device(&adev->dev);
-	status = acpi_hotplug_execute(hotplug_event_work, adev, type);
-	if (ACPI_SUCCESS(status))
-		return;
-
-	put_device(&adev->dev);
-
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
+	return 0;
 }
 
 /**


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

* [PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                     ` (2 preceding siblings ...)
  2014-01-28 22:14   ` [PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
@ 2014-01-28 22:14   ` Rafael J. Wysocki
  2014-01-28 22:16   ` [PATCH 5/5][RFT] ACPI / hotplug: Dispach hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
  2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  5 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 22:14 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Use the observation that the ACPI scan handler of the device object
in acpi_hotplug_notify_cb() can be obtained from that device object's
handler pointer and do not pass it as data to
acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().

That allows the second argument of acpi_install_hotplug_notify_handler()
to be dropped, so do it and update its callers accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |   23 ++++++++++++-----------
 drivers/pci/hotplug/acpiphp_glue.c |    2 +-
 include/acpi/acpi_bus.h            |    2 +-
 3 files changed, 14 insertions(+), 13 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_scan_handler *handler = data;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
@@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (handler && !handler->hotplug.enabled) {
-			acpi_handle_err(handle, "Eject disabled\n");
-			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto out;
-		}
-		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
@@ -539,6 +531,15 @@ static void acpi_hotplug_notify_cb(acpi_
 	if (acpi_bus_get_device(handle, &adev))
 		goto out;
 
+	if (type == ACPI_NOTIFY_EJECT_REQUEST) {
+		if (adev->handler && !adev->handler->hotplug.enabled) {
+			acpi_handle_err(handle, "Eject disabled\n");
+			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+			goto out;
+		}
+		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
+					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+	}
 	get_device(&adev->dev);
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
@@ -550,10 +551,10 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+void acpi_install_hotplug_notify_handler(acpi_handle handle)
 {
 	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, data);
+				    acpi_hotplug_notify_cb, NULL);
 }
 
 void acpi_remove_hotplug_notify_handler(acpi_handle handle)
@@ -2000,7 +2001,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_hotplug_notify_handler(handle, handler);
+			acpi_install_hotplug_notify_handler(handle);
 			break;
 		}
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -371,7 +371,7 @@ static acpi_status register_slot(acpi_ha
 
 	/* install notify handler */
 	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle, NULL);
+		acpi_install_hotplug_notify_handler(handle);
 
 	return AE_OK;
 }
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -435,7 +435,7 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_install_hotplug_notify_handler(acpi_handle handle);
 void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**


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

* [PATCH 5/5][RFT] ACPI / hotplug: Dispach hotplug notifications from acpi_bus_notify()
  2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                     ` (3 preceding siblings ...)
  2014-01-28 22:14   ` [PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-01-28 22:16   ` Rafael J. Wysocki
  2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  5 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 22:16 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Since acpi_bus_notify() is executed on all notifications for all
devices anyway, rename acpi_hotplug_notify_cb() to acpi_system_notify()
and call it directly from acpi_bus_notify() instead of installing
notify handlers pointing to it for all hotplug devices.

This change reduces both the size and complexity of ACPI-base device
hotplug code.  Moreover, since acpi_system_notify() only does
significant things for devices that either have an ACPI scan handler,
or have a hotplug context with .eject() defined, and those devices
had notify handlers pointing to acpi_hotplug_notify_cb() installed
before anyway, this change shouldn't modify functionality, except for
executing _OST with the ACPI_OST_SC_NON_SPECIFIC_FAILURE status code
for devices that were not handled at all previously.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/bus.c                 |   42 -----------------------------------
 drivers/acpi/internal.h            |    1 
 drivers/acpi/scan.c                |   44 -------------------------------------
 drivers/pci/hotplug/acpiphp.h      |    1 
 drivers/pci/hotplug/acpiphp_glue.c |   16 +++++--------
 include/acpi/acpi_bus.h            |    2 -
 6 files changed, 10 insertions(+), 96 deletions(-)

Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -345,47 +345,7 @@ static void acpi_bus_notify(acpi_handle
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
 			  type, handle));
 
-	switch (type) {
-
-	case ACPI_NOTIFY_BUS_CHECK:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
-		/* TBD: Exactly what does 'light' mean? */
-		break;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		/* TBD */
-		break;
-
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received unknown/unsupported notification [%08x]\n",
-				  type));
-		break;
-	}
-
+	acpi_system_notify(handle, type);
 	acpi_bus_get_device(handle, &device);
 	if (device) {
 		driver = device->driver;
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -74,6 +74,7 @@ static inline void acpi_lpss_init(void)
 
 bool acpi_queue_hotplug_work(struct work_struct *work);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
+void acpi_system_notify(acpi_handle handle, u32 type);
 
 /* --------------------------------------------------------------------------
                      Device Node Initialization / Removal
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -485,7 +485,7 @@ static void acpi_device_hotplug(void *da
 	unlock_device_hotplug();
 }
 
-static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
+void acpi_system_notify(acpi_handle handle, u32 type)
 {
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
@@ -551,18 +551,6 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, NULL);
-}
-
-void acpi_remove_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				   acpi_hotplug_notify_cb);
-}
-
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1982,34 +1970,6 @@ void acpi_scan_hotplug_enabled(struct ac
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
-{
-	struct acpi_device_pnp pnp = {};
-	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
-
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
-
-	if (!pnp.type.hardware_id)
-		goto out;
-
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
-		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (handler) {
-			acpi_install_hotplug_notify_handler(handle);
-			break;
-		}
-	}
-
-out:
-	acpi_free_pnp_ids(&pnp);
-}
-
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 				      void *not_used, void **return_value)
 {
@@ -2031,8 +1991,6 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -292,7 +292,6 @@ static acpi_status register_slot(acpi_ha
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	mutex_unlock(&acpiphp_context_lock);
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -300,8 +299,14 @@ static acpi_status register_slot(acpi_ha
 	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
+	/*
+	 * Dock stations' notify handler should be used for dock devices instead
+	 * of the common one, so clear hp.event in their contexts.
+	 */
 	if (acpi_has_method(handle, "_DCK"))
-		newfunc->flags |= FUNC_HAS_DCK;
+		context->hp.event = NULL;
+
+	mutex_unlock(&acpiphp_context_lock);
 
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
@@ -369,10 +374,6 @@ static acpi_status register_slot(acpi_ha
 			pr_debug("failed to register dock device\n");
 	}
 
-	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle);
-
 	return AE_OK;
 }
 
@@ -409,9 +410,6 @@ static void cleanup_bridge(struct acpiph
 
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
-
-			if (!(func->flags & FUNC_HAS_DCK))
-				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -435,8 +435,6 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle);
-void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -167,7 +167,6 @@ struct acpiphp_attention_info
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 


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

* Re: [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug
  2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                     ` (4 preceding siblings ...)
  2014-01-28 22:16   ` [PATCH 5/5][RFT] ACPI / hotplug: Dispach hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
@ 2014-01-28 23:57   ` Rafael J. Wysocki
  2014-01-28 23:58     ` [Resend][PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
                       ` (5 more replies)
  5 siblings, 6 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 23:57 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

On Tuesday, January 28, 2014 11:10:30 PM Rafael J. Wysocki wrote:
> Hi All,
> 
> It looks like there's time for more adventurous stuff. :-)
> 
> The following series is on top of the one I sent on Sunday:
> 
> https://lkml.org/lkml/2014/1/26/191
> 
> The final outcome of the patches below is that all ACPI hotplug notifications
> for PCI devices and for core system things like CPU, memory, PCI roots etc.,
> will be dispatched from acpi_bus_notify() and it is not necessary to install a
> separate hotplug notify handler for each device any more.
> 
> [1/5] Attach ACPIPHP hotplug contexts to struct acpi_device objects.
> [2/5] Introduce wrappers for installing and removing hotplug notify handlers
>       (those wrappers go away later on, but they are useful for separating
>        changes).
> [3/5] Consolidate ACPI hotplug signaling for PCI and ACPI core.
> [4/5] Simplify notify handle registration wrapper.
> [5/5] Dispatch ACPI hotplug notifications for "core" devices and PCI from acpi_bus_notify().

Unfortunately, I realized that patches [3-5/5] were buggy.  The bugs were
kind of subtle and might not be easy to reproduce, but they were bugs anyway. :-)

A respin of the whole series follows.

Thanks!

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

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

* [Resend][PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device
  2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
@ 2014-01-28 23:58     ` Rafael J. Wysocki
  2014-01-28 23:59     ` [Resend][PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler() Rafael J. Wysocki
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 23:58 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its
hotplug context objects directly to ACPI namespace nodes representing
hotplug devices.  However, after recent changes causing struct
acpi_device to be created for every namespace node representing a
device (regardless of its status), that is not necessary any more.
Moreover, it's vulnerable to a theoretical issue that the ACPI
handle passed in the context between handle_hotplug_event() and
hotplug_event_work() may become invalid in the meantime (as a
result of a concurrent table unload).

For this reason, modify the code to attach the ACPIPHP's device
hotplug contexts to struct device objects representing hotplug
devices.

This also allows further consolidation of the ACPI hotplug code
to be carried out in subsequent changesets.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |    3 +
 drivers/pci/hotplug/acpiphp.h      |    9 ++-
 drivers/pci/hotplug/acpiphp_glue.c |   99 ++++++++++++++++++++++---------------
 include/acpi/acpi_bus.h            |   11 ++++
 4 files changed, 80 insertions(+), 42 deletions(-)

Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -139,6 +139,16 @@ struct acpi_scan_handler {
 };
 
 /*
+ * ACPI Hotplug Context
+ * --------------------
+ */
+
+struct acpi_hotplug_context {
+	struct acpi_device *self;
+	void (*release)(struct acpi_hotplug_context *);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -331,6 +341,7 @@ struct acpi_device {
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
 	struct acpi_scan_handler *handler;
+	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -1063,6 +1063,9 @@ static void acpi_device_del_work_fn(stru
 		mutex_unlock(&acpi_device_del_lock);
 
 		acpi_device_del(adev);
+		if (adev->hp && adev->hp->release)
+			adev->hp->release(adev->hp);
+
 		/*
 		 * Drop references to all power resources that might have been
 		 * used by the device.
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -116,12 +116,17 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
+	struct acpi_hotplug_context hp;
 	struct acpiphp_func func;
-	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
 
+static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
+{
+	return container_of(hp, struct acpiphp_context, hp);
+}
+
 static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
 {
 	return container_of(func, struct acpiphp_context, func);
@@ -129,7 +134,7 @@ static inline struct acpiphp_context *fu
 
 static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
 {
-	return func_to_context(func)->adev;
+	return func_to_context(func)->hp.self;
 }
 
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -53,9 +53,13 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 
+#include <asm/pgtable.h>
+
 #include "../pci.h"
 #include "acpiphp.h"
 
+#define INVALID_ACPI_HANDLE	((acpi_handle)empty_zero_page)
+
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 static DEFINE_MUTEX(acpiphp_context_lock);
@@ -66,9 +70,9 @@ static void acpiphp_set_hpp_values(struc
 static void hotplug_event(u32 type, void *data);
 static void free_bridge(struct kref *kref);
 
-static void acpiphp_context_handler(acpi_handle handle, void *context)
+static void acpiphp_free_context(struct acpi_hotplug_context *hp)
 {
-	/* Intentionally empty. */
+	kfree(to_acpiphp_context(hp));
 }
 
 /**
@@ -80,39 +84,29 @@ static void acpiphp_context_handler(acpi
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
-	acpi_status status;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return NULL;
 
-	context->adev = adev;
+	context->hp.self = adev;
+	context->hp.release = acpiphp_free_context;
 	context->refcount = 1;
-	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
-	if (ACPI_FAILURE(status)) {
-		kfree(context);
-		return NULL;
-	}
+	adev->hp = &context->hp;
 	return context;
 }
 
 /**
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
- * @handle: ACPI object handle to get the context for.
+ * @adev: ACPI device object to get the context for.
  *
  * Call under acpiphp_context_lock.
  */
-static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = NULL;
-	acpi_status status;
-	void *data;
+	struct acpiphp_context *context = to_acpiphp_context(adev->hp);
 
-	status = acpi_get_data(handle, acpiphp_context_handler, &data);
-	if (ACPI_SUCCESS(status)) {
-		context = data;
-		context->refcount++;
-	}
+	context->refcount++;
 	return context;
 }
 
@@ -130,7 +124,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
+	context->hp.self->hp = NULL;
 	kfree(context);
 }
 
@@ -395,9 +389,13 @@ static struct acpiphp_bridge *acpiphp_ha
 {
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
+	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return NULL;
 
 	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_get_context(handle);
+	context = acpiphp_get_context(adev);
 	if (context) {
 		bridge = context->bridge;
 		if (bridge)
@@ -793,7 +791,7 @@ static void hotplug_event(u32 type, void
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
-	acpi_handle handle = context->adev->handle;
+	acpi_handle handle = context->hp.self->handle;
 	struct acpiphp_bridge *bridge;
 
 	mutex_lock(&acpiphp_context_lock);
@@ -842,18 +840,39 @@ static void hotplug_event(u32 type, void
 
 static void hotplug_event_work(void *data, u32 type)
 {
-	struct acpiphp_context *context = data;
+	struct acpi_device *adev = data;
+	struct acpiphp_context *context;
+	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
 	acpi_scan_lock_acquire();
-	pci_lock_rescan_remove();
+	/*
+	 * The device object's ACPI handle cannot become invalid as long as we
+	 * are holding acpi_scan_lock, but it might have become invalid before
+	 * that lock was acquired.
+	 */
+	if (adev->handle == INVALID_ACPI_HANDLE)
+		goto out;
 
-	hotplug_event(type, context);
+	mutex_lock(&acpiphp_context_lock);
+	context = acpiphp_get_context(adev);
+	if (!context) {
+		mutex_unlock(&acpiphp_context_lock);
+		goto out;
+	}
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
+	mutex_unlock(&acpiphp_context_lock);
 
+	pci_lock_rescan_remove();
+	hotplug_event(type, context);
 	pci_unlock_rescan_remove();
-	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(context->adev->handle, type,
-				  ACPI_OST_SC_SUCCESS, NULL);
 	put_bridge(context->func.parent);
+	ost_code = ACPI_OST_SC_SUCCESS;
+
+ out:
+	acpi_evaluate_hotplug_ost(adev->handle, type, ost_code, NULL);
+	put_device(&adev->dev);
+	acpi_scan_lock_release();
 }
 
 /**
@@ -866,7 +885,8 @@ static void hotplug_event_work(void *dat
  */
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 {
-	struct acpiphp_context *context;
+	struct acpi_device *adev;
+	acpi_status status;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 
 	switch (type) {
@@ -901,17 +921,16 @@ static void handle_hotplug_event(acpi_ha
 		goto out;
 	}
 
-	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_get_context(handle);
-	if (context && !WARN_ON(context->adev->handle != handle)) {
-		get_bridge(context->func.parent);
-		acpiphp_put_context(context);
-		acpi_hotplug_execute(hotplug_event_work, context, type);
-		mutex_unlock(&acpiphp_context_lock);
-		return;
-	}
-	mutex_unlock(&acpiphp_context_lock);
 	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+	if (acpi_bus_get_device(handle, &adev))
+		goto out;
+
+	get_device(&adev->dev);
+	status = acpi_hotplug_execute(hotplug_event_work, adev, type);
+	if (ACPI_SUCCESS(status))
+		return;
+
+	put_device(&adev->dev);
 
  out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
@@ -967,7 +986,7 @@ void acpiphp_enumerate_slots(struct pci_
 		 * bridge is not interesting to us either.
 		 */
 		mutex_lock(&acpiphp_context_lock);
-		context = acpiphp_get_context(handle);
+		context = acpiphp_get_context(adev);
 		if (!context) {
 			mutex_unlock(&acpiphp_context_lock);
 			put_device(&bus->dev);


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

* [Resend][PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler()
  2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  2014-01-28 23:58     ` [Resend][PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
@ 2014-01-28 23:59     ` Rafael J. Wysocki
  2014-01-28 23:59     ` [Update][PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
                       ` (3 subsequent siblings)
  5 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 23:59 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Introduce a helper routine for installing acpi_hotplug_notify_cb()
as an ACPI notify handler for the given ACPI namespace node and make
acpi_scan_init_hotplug() use it.

This is to make subsequent changes easier to follow.

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

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -523,6 +523,18 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+{
+	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				    acpi_hotplug_notify_cb, data);
+}
+
+void acpi_remove_hotplug_notify_handler(acpi_handle handle)
+{
+	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				   acpi_hotplug_notify_cb);
+}
+
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1961,8 +1973,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					acpi_hotplug_notify_cb, handler);
+			acpi_install_hotplug_notify_handler(handle, handler);
 			break;
 		}
 	}
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -434,6 +434,8 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver


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

* [Update][PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
  2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  2014-01-28 23:58     ` [Resend][PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
  2014-01-28 23:59     ` [Resend][PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-01-28 23:59     ` Rafael J. Wysocki
  2014-01-29  0:00     ` [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
                       ` (2 subsequent siblings)
  5 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-28 23:59 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Use the same ACPI notify handler, acpi_hotplug_notify_cb() for both
ACPI-based PCI hotplug (ACPIPHP) and the generic ACPI-based hotplug
of devices.  For PCI devices use the  .hp.event() callback from
their ACPI companions that points to acpiphp_hotplug_event().
For other devices (CPU, memory, containers, PCI host bridges) the
generic ACPI-based device hotplug code is used.

This allows code duplication between ACPIPHP and the ACPI core to be
reduced significantly and makes further ACPI-based device hotplug
consolidation possible.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |   79 +++++++++++++++++---------
 drivers/pci/hotplug/acpiphp_glue.c |  110 +++----------------------------------
 include/acpi/acpi_bus.h            |    1 
 3 files changed, 63 insertions(+), 127 deletions(-)

Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -145,6 +145,7 @@ struct acpi_scan_handler {
 
 struct acpi_hotplug_context {
 	struct acpi_device *self;
+	int (*event)(struct acpi_device *, u32);
 	void (*release)(struct acpi_hotplug_context *);
 };
 
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -439,38 +439,42 @@ static int acpi_scan_bus_check(struct ac
 	return 0;
 }
 
+static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
+{
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		return acpi_scan_bus_check(adev);
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		return acpi_scan_device_check(adev);
+	case ACPI_NOTIFY_EJECT_REQUEST:
+	case ACPI_OST_EC_OSPM_EJECT:
+		return acpi_scan_hot_remove(adev);
+	}
+	return -EINVAL;
+}
+
 static void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
-	int error;
+	int error = -ENODEV;
 
 	lock_device_hotplug();
 	mutex_lock(&acpi_scan_lock);
 
 	/*
 	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it may have become invalid before
+	 * are holding acpi_scan_lock, but it might have become invalid before
 	 * that lock was acquired.
 	 */
 	if (adev->handle == INVALID_ACPI_HANDLE)
 		goto out;
 
-	switch (src) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		error = acpi_scan_bus_check(adev);
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		error = acpi_scan_device_check(adev);
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-	case ACPI_OST_EC_OSPM_EJECT:
-		error = acpi_scan_hot_remove(adev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
-	}
+	if (adev->handler)
+		error = acpi_generic_hotplug_event(adev, src);
+	else if (adev->hp && adev->hp->event)
+		error = adev->hp->event(adev, src);
+
 	if (!error)
 		ost_code = ACPI_OST_SC_SUCCESS;
 
@@ -483,35 +487,58 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_scan_handler *handler = data;
+	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
 
-	if (acpi_bus_get_device(handle, &adev))
-		goto err_out;
-
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (!handler->hotplug.enabled) {
+		if (handler && !handler->hotplug.enabled) {
 			acpi_handle_err(handle, "Eject disabled\n");
 			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto err_out;
+			goto out;
 		}
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
-	default:
-		/* non-hotplug event; possibly handled by other handler */
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
 		return;
+
+	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_POWER_FAULT:
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
+		goto out;
+
+	default:
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto out;
 	}
+
+	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
+	if (acpi_bus_get_device(handle, &adev))
+		goto out;
+
 	get_device(&adev->dev);
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
@@ -519,7 +546,7 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	put_device(&adev->dev);
 
- err_out:
+ out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -53,18 +53,14 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 
-#include <asm/pgtable.h>
-
 #include "../pci.h"
 #include "acpiphp.h"
 
-#define INVALID_ACPI_HANDLE	((acpi_handle)empty_zero_page)
-
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 static DEFINE_MUTEX(acpiphp_context_lock);
 
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
 static void hotplug_event(u32 type, void *data);
@@ -91,6 +87,7 @@ static struct acpiphp_context *acpiphp_i
 
 	context->hp.self = adev;
 	context->hp.release = acpiphp_free_context;
+	context->hp.event = acpiphp_hotplug_event;
 	context->refcount = 1;
 	adev->hp = &context->hp;
 	return context;
@@ -373,14 +370,8 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-						     handle_hotplug_event,
-						     context);
-		if (ACPI_FAILURE(status))
-			acpi_handle_err(handle,
-					"failed to install notify handler\n");
-	}
+	if (!(newfunc->flags & FUNC_HAS_DCK))
+		acpi_install_hotplug_notify_handler(handle, NULL);
 
 	return AE_OK;
 }
@@ -411,7 +402,6 @@ static void cleanup_bridge(struct acpiph
 {
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
-	acpi_status status;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
@@ -420,13 +410,8 @@ static void cleanup_bridge(struct acpiph
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
 
-			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(handle,
-							ACPI_SYSTEM_NOTIFY,
-							handle_hotplug_event);
-				if (ACPI_FAILURE(status))
-					pr_err("failed to remove notify handler\n");
-			}
+			if (!(func->flags & FUNC_HAS_DCK))
+				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
@@ -838,26 +823,15 @@ static void hotplug_event(u32 type, void
 		put_bridge(bridge);
 }
 
-static void hotplug_event_work(void *data, u32 type)
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type)
 {
-	struct acpi_device *adev = data;
 	struct acpiphp_context *context;
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-
-	acpi_scan_lock_acquire();
-	/*
-	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it might have become invalid before
-	 * that lock was acquired.
-	 */
-	if (adev->handle == INVALID_ACPI_HANDLE)
-		goto out;
 
 	mutex_lock(&acpiphp_context_lock);
 	context = acpiphp_get_context(adev);
 	if (!context) {
 		mutex_unlock(&acpiphp_context_lock);
-		goto out;
+		return -ENODATA;
 	}
 	get_bridge(context->func.parent);
 	acpiphp_put_context(context);
@@ -867,73 +841,7 @@ static void hotplug_event_work(void *dat
 	hotplug_event(type, context);
 	pci_unlock_rescan_remove();
 	put_bridge(context->func.parent);
-	ost_code = ACPI_OST_SC_SUCCESS;
-
- out:
-	acpi_evaluate_hotplug_ost(adev->handle, type, ost_code, NULL);
-	put_device(&adev->dev);
-	acpi_scan_lock_release();
-}
-
-/**
- * handle_hotplug_event - handle ACPI hotplug event
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @data: pointer to acpiphp_context structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
-{
-	struct acpi_device *adev;
-	acpi_status status;
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
-		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
-
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-	if (acpi_bus_get_device(handle, &adev))
-		goto out;
-
-	get_device(&adev->dev);
-	status = acpi_hotplug_execute(hotplug_event_work, adev, type);
-	if (ACPI_SUCCESS(status))
-		return;
-
-	put_device(&adev->dev);
-
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
+	return 0;
 }
 
 /**


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

* [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                       ` (2 preceding siblings ...)
  2014-01-28 23:59     ` [Update][PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
@ 2014-01-29  0:00     ` Rafael J. Wysocki
  2014-01-31 15:28       ` Mika Westerberg
  2014-01-29  0:02     ` [Update][PATCH 5/5][RFT] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  5 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-29  0:00 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Use the observation that the ACPI scan handler of the device object
in acpi_hotplug_notify_cb() can be obtained from that device object's
handler pointer and do not pass it as data to
acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().

That allows the second argument of acpi_install_hotplug_notify_handler()
to be dropped, so do it and update its callers accordingly.

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

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_scan_handler *handler = data;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
@@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (handler && !handler->hotplug.enabled) {
-			acpi_handle_err(handle, "Eject disabled\n");
-			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto out;
-		}
-		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
@@ -535,11 +527,24 @@ static void acpi_hotplug_notify_cb(acpi_
 		goto out;
 	}
 
+	mutex_lock(&acpi_scan_lock);
 	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-	if (acpi_bus_get_device(handle, &adev))
+	if (acpi_bus_get_device(handle, &adev)) {
+		mutex_unlock(&acpi_scan_lock);
 		goto out;
-
+	}
+	if (type == ACPI_NOTIFY_EJECT_REQUEST) {
+		if (adev->handler && !adev->handler->hotplug.enabled) {
+			acpi_handle_err(handle, "Eject disabled\n");
+			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+			mutex_unlock(&acpi_scan_lock);
+			goto out;
+		}
+		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
+					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
+	}
 	get_device(&adev->dev);
+	mutex_unlock(&acpi_scan_lock);
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
 		return;
@@ -550,10 +555,10 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+void acpi_install_hotplug_notify_handler(acpi_handle handle)
 {
 	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, data);
+				    acpi_hotplug_notify_cb, NULL);
 }
 
 void acpi_remove_hotplug_notify_handler(acpi_handle handle)
@@ -2000,7 +2005,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_hotplug_notify_handler(handle, handler);
+			acpi_install_hotplug_notify_handler(handle);
 			break;
 		}
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -371,7 +371,7 @@ static acpi_status register_slot(acpi_ha
 
 	/* install notify handler */
 	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle, NULL);
+		acpi_install_hotplug_notify_handler(handle);
 
 	return AE_OK;
 }
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -435,7 +435,7 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_install_hotplug_notify_handler(acpi_handle handle);
 void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**


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

* [Update][PATCH 5/5][RFT] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify()
  2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                       ` (3 preceding siblings ...)
  2014-01-29  0:00     ` [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-01-29  0:02     ` Rafael J. Wysocki
  2014-01-30 15:28       ` [Update 2x][PATCH " Rafael J. Wysocki
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  5 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-29  0:02 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Since acpi_bus_notify() is executed on all notifications for all
devices anyway, rename acpi_hotplug_notify_cb() to acpi_system_notify()
and call it directly from acpi_bus_notify() instead of installing
notify handlers pointing to it for all hotplug devices.

This change reduces both the size and complexity of ACPI-base device
hotplug code.  Moreover, since acpi_system_notify() only does
significant things for devices that either have an ACPI scan handler,
or have a hotplug context with .eject() defined, and those devices
had notify handlers pointing to acpi_hotplug_notify_cb() installed
before anyway, this change shouldn't modify functionality.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/bus.c                 |   42 ----------------------
 drivers/acpi/internal.h            |    1 
 drivers/acpi/scan.c                |   68 +++++++++----------------------------
 drivers/pci/hotplug/acpiphp.h      |    1 
 drivers/pci/hotplug/acpiphp_glue.c |   16 +++-----
 include/acpi/acpi_bus.h            |    2 -
 6 files changed, 26 insertions(+), 104 deletions(-)

Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -345,47 +345,7 @@ static void acpi_bus_notify(acpi_handle
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
 			  type, handle));
 
-	switch (type) {
-
-	case ACPI_NOTIFY_BUS_CHECK:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
-		/* TBD: Exactly what does 'light' mean? */
-		break;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		/* TBD */
-		break;
-
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received unknown/unsupported notification [%08x]\n",
-				  type));
-		break;
-	}
-
+	acpi_system_notify(handle, type);
 	acpi_bus_get_device(handle, &device);
 	if (device) {
 		driver = device->driver;
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -74,6 +74,7 @@ static inline void acpi_lpss_init(void)
 
 bool acpi_queue_hotplug_work(struct work_struct *work);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
+void acpi_system_notify(acpi_handle handle, u32 type);
 
 /* --------------------------------------------------------------------------
                      Device Node Initialization / Removal
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -485,11 +485,11 @@ static void acpi_device_hotplug(void *da
 	unlock_device_hotplug();
 }
 
-static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
+void acpi_system_notify(acpi_handle handle, u32 type)
 {
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
-	acpi_status status;
+	bool execute_ost = true;
 
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
@@ -543,28 +543,24 @@ static void acpi_hotplug_notify_cb(acpi_
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 	}
-	get_device(&adev->dev);
-	mutex_unlock(&acpi_scan_lock);
-	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
-	if (ACPI_SUCCESS(status))
-		return;
-
-	put_device(&adev->dev);
+	if (adev->handler || (adev->hp && adev->hp->event)) {
+		acpi_status status;
 
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-}
+		get_device(&adev->dev);
+		mutex_unlock(&acpi_scan_lock);
+		status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
+		if (ACPI_SUCCESS(status))
+			return;
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, NULL);
-}
+		put_device(&adev->dev);
+	} else {
+		mutex_unlock(&acpi_scan_lock);
+		execute_ost = false;
+	}
 
-void acpi_remove_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				   acpi_hotplug_notify_cb);
+ out:
+	if (execute_ost)
+		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
 static ssize_t real_power_state_show(struct device *dev,
@@ -1986,34 +1982,6 @@ void acpi_scan_hotplug_enabled(struct ac
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
-{
-	struct acpi_device_pnp pnp = {};
-	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
-
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
-
-	if (!pnp.type.hardware_id)
-		goto out;
-
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
-		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (handler) {
-			acpi_install_hotplug_notify_handler(handle);
-			break;
-		}
-	}
-
-out:
-	acpi_free_pnp_ids(&pnp);
-}
-
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 				      void *not_used, void **return_value)
 {
@@ -2035,8 +2003,6 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -292,7 +292,6 @@ static acpi_status register_slot(acpi_ha
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	mutex_unlock(&acpiphp_context_lock);
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -300,8 +299,14 @@ static acpi_status register_slot(acpi_ha
 	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
+	/*
+	 * Dock stations' notify handler should be used for dock devices instead
+	 * of the common one, so clear hp.event in their contexts.
+	 */
 	if (acpi_has_method(handle, "_DCK"))
-		newfunc->flags |= FUNC_HAS_DCK;
+		context->hp.event = NULL;
+
+	mutex_unlock(&acpiphp_context_lock);
 
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
@@ -369,10 +374,6 @@ static acpi_status register_slot(acpi_ha
 			pr_debug("failed to register dock device\n");
 	}
 
-	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle);
-
 	return AE_OK;
 }
 
@@ -409,9 +410,6 @@ static void cleanup_bridge(struct acpiph
 
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
-
-			if (!(func->flags & FUNC_HAS_DCK))
-				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -435,8 +435,6 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle);
-void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -167,7 +167,6 @@ struct acpiphp_attention_info
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 


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

* [Update 2x][PATCH 5/5][RFT] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify()
  2014-01-29  0:02     ` [Update][PATCH 5/5][RFT] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
@ 2014-01-30 15:28       ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-30 15:28 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Since acpi_bus_notify() is executed on all notifications for all
devices anyway, rename acpi_hotplug_notify_cb() to acpi_system_notify()
and call it directly from acpi_bus_notify() instead of installing
notify handlers pointing to it for all hotplug devices.

This change reduces both the size and complexity of ACPI-base device
hotplug code.  Moreover, since acpi_system_notify() only does
significant things for devices that either have an ACPI scan handler,
or have a hotplug context with .eject() defined, and those devices
had notify handlers pointing to acpi_hotplug_notify_cb() installed
before anyway, this change shouldn't modify functionality.

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

Well, I'm not sure why exactly I left the execute_ost variable in
acpi_system_notify() in the previous version.

Guess what, it's a good idea to review your own patches a couple of days
after sending them out. :-)

Rafael

---
 drivers/acpi/bus.c                 |   42 ------------------------
 drivers/acpi/internal.h            |    1 
 drivers/acpi/scan.c                |   64 ++++++++-----------------------------
 drivers/pci/hotplug/acpiphp.h      |    1 
 drivers/pci/hotplug/acpiphp_glue.c |   16 ++++-----
 include/acpi/acpi_bus.h            |    2 -
 6 files changed, 23 insertions(+), 103 deletions(-)

Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -345,47 +345,7 @@ static void acpi_bus_notify(acpi_handle
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
 			  type, handle));
 
-	switch (type) {
-
-	case ACPI_NOTIFY_BUS_CHECK:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
-		/* TBD: Exactly what does 'light' mean? */
-		break;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		/* TBD */
-		break;
-
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received unknown/unsupported notification [%08x]\n",
-				  type));
-		break;
-	}
-
+	acpi_system_notify(handle, type);
 	acpi_bus_get_device(handle, &device);
 	if (device) {
 		driver = device->driver;
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -74,6 +74,7 @@ static inline void acpi_lpss_init(void)
 
 bool acpi_queue_hotplug_work(struct work_struct *work);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
+void acpi_system_notify(acpi_handle handle, u32 type);
 
 /* --------------------------------------------------------------------------
                      Device Node Initialization / Removal
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -485,11 +485,10 @@ static void acpi_device_hotplug(void *da
 	unlock_device_hotplug();
 }
 
-static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
+void acpi_system_notify(acpi_handle handle, u32 type)
 {
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
-	acpi_status status;
 
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
@@ -543,30 +542,25 @@ static void acpi_hotplug_notify_cb(acpi_
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 	}
-	get_device(&adev->dev);
-	mutex_unlock(&acpi_scan_lock);
-	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
-	if (ACPI_SUCCESS(status))
-		return;
+	if (adev->handler || (adev->hp && adev->hp->event)) {
+		acpi_status status;
 
-	put_device(&adev->dev);
+		get_device(&adev->dev);
+		mutex_unlock(&acpi_scan_lock);
+		status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
+		if (ACPI_SUCCESS(status))
+			return;
+
+		put_device(&adev->dev);
+	} else {
+		mutex_unlock(&acpi_scan_lock);
+		return;
+	}
 
  out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, NULL);
-}
-
-void acpi_remove_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				   acpi_hotplug_notify_cb);
-}
-
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1986,34 +1980,6 @@ void acpi_scan_hotplug_enabled(struct ac
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
-{
-	struct acpi_device_pnp pnp = {};
-	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
-
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
-
-	if (!pnp.type.hardware_id)
-		goto out;
-
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
-		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (handler) {
-			acpi_install_hotplug_notify_handler(handle);
-			break;
-		}
-	}
-
-out:
-	acpi_free_pnp_ids(&pnp);
-}
-
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 				      void *not_used, void **return_value)
 {
@@ -2035,8 +2001,6 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -292,7 +292,6 @@ static acpi_status register_slot(acpi_ha
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	mutex_unlock(&acpiphp_context_lock);
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -300,8 +299,14 @@ static acpi_status register_slot(acpi_ha
 	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
+	/*
+	 * Dock stations' notify handler should be used for dock devices instead
+	 * of the common one, so clear hp.event in their contexts.
+	 */
 	if (acpi_has_method(handle, "_DCK"))
-		newfunc->flags |= FUNC_HAS_DCK;
+		context->hp.event = NULL;
+
+	mutex_unlock(&acpiphp_context_lock);
 
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
@@ -369,10 +374,6 @@ static acpi_status register_slot(acpi_ha
 			pr_debug("failed to register dock device\n");
 	}
 
-	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle);
-
 	return AE_OK;
 }
 
@@ -409,9 +410,6 @@ static void cleanup_bridge(struct acpiph
 
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
-
-			if (!(func->flags & FUNC_HAS_DCK))
-				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -435,8 +435,6 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle);
-void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -167,7 +167,6 @@ struct acpiphp_attention_info
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 


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

* Re: [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-29  0:00     ` [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-01-31 15:28       ` Mika Westerberg
  2014-01-31 15:42         ` Rafael J. Wysocki
  0 siblings, 1 reply; 100+ messages in thread
From: Mika Westerberg @ 2014-01-31 15:28 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Wed, Jan 29, 2014 at 01:00:57AM +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Use the observation that the ACPI scan handler of the device object
> in acpi_hotplug_notify_cb() can be obtained from that device object's
> handler pointer and do not pass it as data to
> acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().
> 
> That allows the second argument of acpi_install_hotplug_notify_handler()
> to be dropped, so do it and update its callers accordingly.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/scan.c                |   31 ++++++++++++++++++-------------
>  drivers/pci/hotplug/acpiphp_glue.c |    2 +-
>  include/acpi/acpi_bus.h            |    2 +-
>  3 files changed, 20 insertions(+), 15 deletions(-)
> 
> Index: linux-pm/drivers/acpi/scan.c
> ===================================================================
> --- linux-pm.orig/drivers/acpi/scan.c
> +++ linux-pm/drivers/acpi/scan.c
> @@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
>  
>  static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
>  {
> -	struct acpi_scan_handler *handler = data;
>  	u32 ost_code = ACPI_OST_SC_SUCCESS;
>  	struct acpi_device *adev;
>  	acpi_status status;
> @@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
>  
>  	case ACPI_NOTIFY_EJECT_REQUEST:
>  		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
> -		if (handler && !handler->hotplug.enabled) {
> -			acpi_handle_err(handle, "Eject disabled\n");
> -			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> -			goto out;
> -		}
> -		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> -					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
>  		break;
>  
>  	case ACPI_NOTIFY_DEVICE_WAKE:
> @@ -535,11 +527,24 @@ static void acpi_hotplug_notify_cb(acpi_
>  		goto out;
>  	}
>  
> +	mutex_lock(&acpi_scan_lock);

This is weird. I'm testing against your test-next branch which has this
patch included. If I remove locking here, TBT hotplug works fine. Otherwise
I can see the first hotplug/unplug works but after that I cannot get any
events anymore.

>  	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
> -	if (acpi_bus_get_device(handle, &adev))
> +	if (acpi_bus_get_device(handle, &adev)) {
> +		mutex_unlock(&acpi_scan_lock);
>  		goto out;
> -
> +	}
> +	if (type == ACPI_NOTIFY_EJECT_REQUEST) {
> +		if (adev->handler && !adev->handler->hotplug.enabled) {
> +			acpi_handle_err(handle, "Eject disabled\n");
> +			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> +			mutex_unlock(&acpi_scan_lock);
> +			goto out;
> +		}
> +		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> +					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> +	}
>  	get_device(&adev->dev);
> +	mutex_unlock(&acpi_scan_lock);
>  	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
>  	if (ACPI_SUCCESS(status))
>  		return;

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

* Re: [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-31 15:42         ` Rafael J. Wysocki
@ 2014-01-31 15:40           ` Mika Westerberg
  2014-01-31 16:01             ` Mika Westerberg
  0 siblings, 1 reply; 100+ messages in thread
From: Mika Westerberg @ 2014-01-31 15:40 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Fri, Jan 31, 2014 at 04:42:21PM +0100, Rafael J. Wysocki wrote:
> On Friday, January 31, 2014 05:28:36 PM Mika Westerberg wrote:
> > On Wed, Jan 29, 2014 at 01:00:57AM +0100, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > 
> > > Use the observation that the ACPI scan handler of the device object
> > > in acpi_hotplug_notify_cb() can be obtained from that device object's
> > > handler pointer and do not pass it as data to
> > > acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().
> > > 
> > > That allows the second argument of acpi_install_hotplug_notify_handler()
> > > to be dropped, so do it and update its callers accordingly.
> > > 
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > >  drivers/acpi/scan.c                |   31 ++++++++++++++++++-------------
> > >  drivers/pci/hotplug/acpiphp_glue.c |    2 +-
> > >  include/acpi/acpi_bus.h            |    2 +-
> > >  3 files changed, 20 insertions(+), 15 deletions(-)
> > > 
> > > Index: linux-pm/drivers/acpi/scan.c
> > > ===================================================================
> > > --- linux-pm.orig/drivers/acpi/scan.c
> > > +++ linux-pm/drivers/acpi/scan.c
> > > @@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
> > >  
> > >  static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
> > >  {
> > > -	struct acpi_scan_handler *handler = data;
> > >  	u32 ost_code = ACPI_OST_SC_SUCCESS;
> > >  	struct acpi_device *adev;
> > >  	acpi_status status;
> > > @@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
> > >  
> > >  	case ACPI_NOTIFY_EJECT_REQUEST:
> > >  		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
> > > -		if (handler && !handler->hotplug.enabled) {
> > > -			acpi_handle_err(handle, "Eject disabled\n");
> > > -			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> > > -			goto out;
> > > -		}
> > > -		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> > > -					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> > >  		break;
> > >  
> > >  	case ACPI_NOTIFY_DEVICE_WAKE:
> > > @@ -535,11 +527,24 @@ static void acpi_hotplug_notify_cb(acpi_
> > >  		goto out;
> > >  	}
> > >  
> > > +	mutex_lock(&acpi_scan_lock);
> > 
> > This is weird. I'm testing against your test-next branch which has this
> > patch included. If I remove locking here, TBT hotplug works fine. Otherwise
> > I can see the first hotplug/unplug works but after that I cannot get any
> > events anymore.
> 
> Weird indeed.  I don't seem to be able to reproduce that on my Aspire S5.
> 
> What system are you testing on?

This is Intel NUC. Let me see if I can reproduce this on S5 with longer
chain of devices.

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

* Re: [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-31 15:28       ` Mika Westerberg
@ 2014-01-31 15:42         ` Rafael J. Wysocki
  2014-01-31 15:40           ` Mika Westerberg
  0 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-31 15:42 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Friday, January 31, 2014 05:28:36 PM Mika Westerberg wrote:
> On Wed, Jan 29, 2014 at 01:00:57AM +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > Use the observation that the ACPI scan handler of the device object
> > in acpi_hotplug_notify_cb() can be obtained from that device object's
> > handler pointer and do not pass it as data to
> > acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().
> > 
> > That allows the second argument of acpi_install_hotplug_notify_handler()
> > to be dropped, so do it and update its callers accordingly.
> > 
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  drivers/acpi/scan.c                |   31 ++++++++++++++++++-------------
> >  drivers/pci/hotplug/acpiphp_glue.c |    2 +-
> >  include/acpi/acpi_bus.h            |    2 +-
> >  3 files changed, 20 insertions(+), 15 deletions(-)
> > 
> > Index: linux-pm/drivers/acpi/scan.c
> > ===================================================================
> > --- linux-pm.orig/drivers/acpi/scan.c
> > +++ linux-pm/drivers/acpi/scan.c
> > @@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
> >  
> >  static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
> >  {
> > -	struct acpi_scan_handler *handler = data;
> >  	u32 ost_code = ACPI_OST_SC_SUCCESS;
> >  	struct acpi_device *adev;
> >  	acpi_status status;
> > @@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
> >  
> >  	case ACPI_NOTIFY_EJECT_REQUEST:
> >  		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
> > -		if (handler && !handler->hotplug.enabled) {
> > -			acpi_handle_err(handle, "Eject disabled\n");
> > -			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> > -			goto out;
> > -		}
> > -		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> > -					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> >  		break;
> >  
> >  	case ACPI_NOTIFY_DEVICE_WAKE:
> > @@ -535,11 +527,24 @@ static void acpi_hotplug_notify_cb(acpi_
> >  		goto out;
> >  	}
> >  
> > +	mutex_lock(&acpi_scan_lock);
> 
> This is weird. I'm testing against your test-next branch which has this
> patch included. If I remove locking here, TBT hotplug works fine. Otherwise
> I can see the first hotplug/unplug works but after that I cannot get any
> events anymore.

Weird indeed.  I don't seem to be able to reproduce that on my Aspire S5.

What system are you testing on?

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

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

* Re: [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-31 15:40           ` Mika Westerberg
@ 2014-01-31 16:01             ` Mika Westerberg
  2014-01-31 16:16               ` Rafael J. Wysocki
  0 siblings, 1 reply; 100+ messages in thread
From: Mika Westerberg @ 2014-01-31 16:01 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Fri, Jan 31, 2014 at 05:40:11PM +0200, Mika Westerberg wrote:
> On Fri, Jan 31, 2014 at 04:42:21PM +0100, Rafael J. Wysocki wrote:
> > On Friday, January 31, 2014 05:28:36 PM Mika Westerberg wrote:
> > > On Wed, Jan 29, 2014 at 01:00:57AM +0100, Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > 
> > > > Use the observation that the ACPI scan handler of the device object
> > > > in acpi_hotplug_notify_cb() can be obtained from that device object's
> > > > handler pointer and do not pass it as data to
> > > > acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().
> > > > 
> > > > That allows the second argument of acpi_install_hotplug_notify_handler()
> > > > to be dropped, so do it and update its callers accordingly.
> > > > 
> > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > ---
> > > >  drivers/acpi/scan.c                |   31 ++++++++++++++++++-------------
> > > >  drivers/pci/hotplug/acpiphp_glue.c |    2 +-
> > > >  include/acpi/acpi_bus.h            |    2 +-
> > > >  3 files changed, 20 insertions(+), 15 deletions(-)
> > > > 
> > > > Index: linux-pm/drivers/acpi/scan.c
> > > > ===================================================================
> > > > --- linux-pm.orig/drivers/acpi/scan.c
> > > > +++ linux-pm/drivers/acpi/scan.c
> > > > @@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
> > > >  
> > > >  static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
> > > >  {
> > > > -	struct acpi_scan_handler *handler = data;
> > > >  	u32 ost_code = ACPI_OST_SC_SUCCESS;
> > > >  	struct acpi_device *adev;
> > > >  	acpi_status status;
> > > > @@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
> > > >  
> > > >  	case ACPI_NOTIFY_EJECT_REQUEST:
> > > >  		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
> > > > -		if (handler && !handler->hotplug.enabled) {
> > > > -			acpi_handle_err(handle, "Eject disabled\n");
> > > > -			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> > > > -			goto out;
> > > > -		}
> > > > -		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> > > > -					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> > > >  		break;
> > > >  
> > > >  	case ACPI_NOTIFY_DEVICE_WAKE:
> > > > @@ -535,11 +527,24 @@ static void acpi_hotplug_notify_cb(acpi_
> > > >  		goto out;
> > > >  	}
> > > >  
> > > > +	mutex_lock(&acpi_scan_lock);
> > > 
> > > This is weird. I'm testing against your test-next branch which has this
> > > patch included. If I remove locking here, TBT hotplug works fine. Otherwise
> > > I can see the first hotplug/unplug works but after that I cannot get any
> > > events anymore.
> > 
> > Weird indeed.  I don't seem to be able to reproduce that on my Aspire S5.
> > 
> > What system are you testing on?
> 
> This is Intel NUC. Let me see if I can reproduce this on S5 with longer
> chain of devices.

OK, so on S5 this works even with longer chain. However, exactly the same
kernel image on NUC fails after first hotplug/unplug cycle.

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

* Re: [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-31 16:01             ` Mika Westerberg
@ 2014-01-31 16:16               ` Rafael J. Wysocki
  2014-01-31 17:09                 ` Mika Westerberg
  0 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-31 16:16 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Friday, January 31, 2014 06:01:57 PM Mika Westerberg wrote:
> On Fri, Jan 31, 2014 at 05:40:11PM +0200, Mika Westerberg wrote:
> > On Fri, Jan 31, 2014 at 04:42:21PM +0100, Rafael J. Wysocki wrote:
> > > On Friday, January 31, 2014 05:28:36 PM Mika Westerberg wrote:
> > > > On Wed, Jan 29, 2014 at 01:00:57AM +0100, Rafael J. Wysocki wrote:
> > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > 
> > > > > Use the observation that the ACPI scan handler of the device object
> > > > > in acpi_hotplug_notify_cb() can be obtained from that device object's
> > > > > handler pointer and do not pass it as data to
> > > > > acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().
> > > > > 
> > > > > That allows the second argument of acpi_install_hotplug_notify_handler()
> > > > > to be dropped, so do it and update its callers accordingly.
> > > > > 
> > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > ---
> > > > >  drivers/acpi/scan.c                |   31 ++++++++++++++++++-------------
> > > > >  drivers/pci/hotplug/acpiphp_glue.c |    2 +-
> > > > >  include/acpi/acpi_bus.h            |    2 +-
> > > > >  3 files changed, 20 insertions(+), 15 deletions(-)
> > > > > 
> > > > > Index: linux-pm/drivers/acpi/scan.c
> > > > > ===================================================================
> > > > > --- linux-pm.orig/drivers/acpi/scan.c
> > > > > +++ linux-pm/drivers/acpi/scan.c
> > > > > @@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
> > > > >  
> > > > >  static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
> > > > >  {
> > > > > -	struct acpi_scan_handler *handler = data;
> > > > >  	u32 ost_code = ACPI_OST_SC_SUCCESS;
> > > > >  	struct acpi_device *adev;
> > > > >  	acpi_status status;
> > > > > @@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
> > > > >  
> > > > >  	case ACPI_NOTIFY_EJECT_REQUEST:
> > > > >  		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
> > > > > -		if (handler && !handler->hotplug.enabled) {
> > > > > -			acpi_handle_err(handle, "Eject disabled\n");
> > > > > -			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> > > > > -			goto out;
> > > > > -		}
> > > > > -		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> > > > > -					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> > > > >  		break;
> > > > >  
> > > > >  	case ACPI_NOTIFY_DEVICE_WAKE:
> > > > > @@ -535,11 +527,24 @@ static void acpi_hotplug_notify_cb(acpi_
> > > > >  		goto out;
> > > > >  	}
> > > > >  
> > > > > +	mutex_lock(&acpi_scan_lock);
> > > > 
> > > > This is weird. I'm testing against your test-next branch which has this
> > > > patch included. If I remove locking here, TBT hotplug works fine. Otherwise
> > > > I can see the first hotplug/unplug works but after that I cannot get any
> > > > events anymore.
> > > 
> > > Weird indeed.  I don't seem to be able to reproduce that on my Aspire S5.
> > > 
> > > What system are you testing on?
> > 
> > This is Intel NUC. Let me see if I can reproduce this on S5 with longer
> > chain of devices.
> 
> OK, so on S5 this works even with longer chain. However, exactly the same
> kernel image on NUC fails after first hotplug/unplug cycle.

Well, we need to figure out what happens there.

Please add printks (1) before mutex_lock(), (2) before the if (type == ...)
instruction, (3) before the acpi_evaluate_hotplug_ost() under the if () and (4)
before the get_device() in acpi_notify_hotplug_cb() and check if they are all
printed (on NUC).

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

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

* Re: [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-31 16:16               ` Rafael J. Wysocki
@ 2014-01-31 17:09                 ` Mika Westerberg
  2014-01-31 17:34                   ` Rafael J. Wysocki
  0 siblings, 1 reply; 100+ messages in thread
From: Mika Westerberg @ 2014-01-31 17:09 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Fri, Jan 31, 2014 at 05:16:03PM +0100, Rafael J. Wysocki wrote:
> On Friday, January 31, 2014 06:01:57 PM Mika Westerberg wrote:
> > On Fri, Jan 31, 2014 at 05:40:11PM +0200, Mika Westerberg wrote:
> > > On Fri, Jan 31, 2014 at 04:42:21PM +0100, Rafael J. Wysocki wrote:
> > > > On Friday, January 31, 2014 05:28:36 PM Mika Westerberg wrote:
> > > > > On Wed, Jan 29, 2014 at 01:00:57AM +0100, Rafael J. Wysocki wrote:
> > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > 
> > > > > > Use the observation that the ACPI scan handler of the device object
> > > > > > in acpi_hotplug_notify_cb() can be obtained from that device object's
> > > > > > handler pointer and do not pass it as data to
> > > > > > acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().
> > > > > > 
> > > > > > That allows the second argument of acpi_install_hotplug_notify_handler()
> > > > > > to be dropped, so do it and update its callers accordingly.
> > > > > > 
> > > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > ---
> > > > > >  drivers/acpi/scan.c                |   31 ++++++++++++++++++-------------
> > > > > >  drivers/pci/hotplug/acpiphp_glue.c |    2 +-
> > > > > >  include/acpi/acpi_bus.h            |    2 +-
> > > > > >  3 files changed, 20 insertions(+), 15 deletions(-)
> > > > > > 
> > > > > > Index: linux-pm/drivers/acpi/scan.c
> > > > > > ===================================================================
> > > > > > --- linux-pm.orig/drivers/acpi/scan.c
> > > > > > +++ linux-pm/drivers/acpi/scan.c
> > > > > > @@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
> > > > > >  
> > > > > >  static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
> > > > > >  {
> > > > > > -	struct acpi_scan_handler *handler = data;
> > > > > >  	u32 ost_code = ACPI_OST_SC_SUCCESS;
> > > > > >  	struct acpi_device *adev;
> > > > > >  	acpi_status status;
> > > > > > @@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
> > > > > >  
> > > > > >  	case ACPI_NOTIFY_EJECT_REQUEST:
> > > > > >  		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
> > > > > > -		if (handler && !handler->hotplug.enabled) {
> > > > > > -			acpi_handle_err(handle, "Eject disabled\n");
> > > > > > -			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> > > > > > -			goto out;
> > > > > > -		}
> > > > > > -		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> > > > > > -					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> > > > > >  		break;
> > > > > >  
> > > > > >  	case ACPI_NOTIFY_DEVICE_WAKE:
> > > > > > @@ -535,11 +527,24 @@ static void acpi_hotplug_notify_cb(acpi_
> > > > > >  		goto out;
> > > > > >  	}
> > > > > >  
> > > > > > +	mutex_lock(&acpi_scan_lock);
> > > > > 
> > > > > This is weird. I'm testing against your test-next branch which has this
> > > > > patch included. If I remove locking here, TBT hotplug works fine. Otherwise
> > > > > I can see the first hotplug/unplug works but after that I cannot get any
> > > > > events anymore.
> > > > 
> > > > Weird indeed.  I don't seem to be able to reproduce that on my Aspire S5.
> > > > 
> > > > What system are you testing on?
> > > 
> > > This is Intel NUC. Let me see if I can reproduce this on S5 with longer
> > > chain of devices.
> > 
> > OK, so on S5 this works even with longer chain. However, exactly the same
> > kernel image on NUC fails after first hotplug/unplug cycle.
> 
> Well, we need to figure out what happens there.
> 
> Please add printks (1) before mutex_lock(), (2) before the if (type == ...)
> instruction, (3) before the acpi_evaluate_hotplug_ost() under the if () and (4)
> before the get_device() in acpi_notify_hotplug_cb() and check if they are all
> printed (on NUC).

Looks like something doesn't release that lock. I added printks what you
suggested and after first hotplug/unplug last messages I get are:

[   64.914639] ACPI: \_SB_.PCI0.RP05: ACPI_NOTIFY_BUS_CHECK event
[   64.914640] ACPI: \_SB_.PCI0.RP05: BEFORE mutex_lock()

Then running sysrq-w I get following task as blocked:

[  346.885950] SysRq : Show Blocked State
[  346.887733]   task                        PC stack   pid father
[  346.889535] kworker/0:0     D ffff880100241ae0  5280     4      2 0x00000000
[  346.891355] Workqueue: kacpi_notify acpi_os_execute_deferred
[  346.893171]  ffff8801003c7d30 0000000000000046 ffff880100241710 ffffffff81e10460
[  346.895011]  ffff8801003c7fd8 00000000000129c0 00000000000129c0 ffff880100241710
[  346.896849]  ffffffff81e5db70 ffffffff81e5db74 ffff880100241710 00000000ffffffff
[  346.898702] Call Trace:
[  346.900518]  [<ffffffff81815bc4>] schedule_preempt_disabled+0x24/0x70
[  346.902338]  [<ffffffff818175f2>] __mutex_lock_slowpath+0x132/0x1b0
[  346.904164]  [<ffffffff8181768a>] mutex_lock+0x1a/0x2a
[  346.905993]  [<ffffffff81324845>] acpi_hotplug_notify_cb+0x70/0x227
[  346.907820]  [<ffffffff813384f4>] acpi_ev_notify_dispatch+0x44/0x5c
[  346.909637]  [<ffffffff8131fa8d>] acpi_os_execute_deferred+0xf/0x1b
[  346.911455]  [<ffffffff8105e12a>] process_one_work+0x17a/0x440
[  346.913285]  [<ffffffff8105ed29>] worker_thread+0x119/0x390
[  346.915121]  [<ffffffff8105ec10>] ? manage_workers.isra.25+0x2a0/0x2a0
[  346.916970]  [<ffffffff81064dad>] kthread+0xcd/0xf0
[  346.918809]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
[  346.920653]  [<ffffffff8181fefc>] ret_from_fork+0x7c/0xb0
[  346.922501]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
[  346.924351] kworker/u8:5    D ffff88006ea55860  4696   945      2 0x00000000
[  346.926212] Workqueue: kacpi_hotplug acpi_hotplug_work_fn
[  346.928074]  ffff88006de49a40 0000000000000046 ffff88006ea55490 ffff880100245490
[  346.929978]  ffff88006de49fd8 00000000000129c0 00000000000129c0 ffff88006ea55490
[  346.931872]  ffff88006de49ba0 7fffffffffffffff ffff88006de49b98 ffff88006ea55490
[  346.933753] Call Trace:
[  346.935626]  [<ffffffff81815794>] schedule+0x24/0x70
[  346.937516]  [<ffffffff81814a89>] schedule_timeout+0x1a9/0x2a0
[  346.939415]  [<ffffffff8107dda8>] ? __wake_up_common+0x58/0x90
[  346.941312]  [<ffffffff81816968>] wait_for_completion+0x98/0x100
[  346.943222]  [<ffffffff81071b70>] ? wake_up_state+0x10/0x10
[  346.945133]  [<ffffffff8105ba25>] flush_workqueue+0x115/0x5a0
[  346.947054]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
[  346.948986]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
[  346.950904]  [<ffffffff81320340>] acpi_os_wait_events_complete+0x1c/0x1e
[  346.952829]  [<ffffffff8133a387>] acpi_remove_notify_handler+0x78/0x1ef
[  346.954748]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
[  346.956669]  [<ffffffff813226df>] acpi_remove_pm_notifier+0x39/0x5c
[  346.958592]  [<ffffffff81309ab5>] pci_acpi_cleanup+0x25/0x50
[  346.960508]  [<ffffffff8132368c>] acpi_platform_notify_remove+0x44/0x53
[  346.962427]  [<ffffffff814426f2>] device_del+0x142/0x1b0
[  346.964333]  [<ffffffff812edcfa>] pci_remove_bus_device+0x7a/0x100
[  346.966238]  [<ffffffff812edd95>] pci_stop_and_remove_bus_device+0x15/0x20
[  346.968140]  [<ffffffff8130639e>] disable_slot+0x4e/0xa0
[  346.970030]  [<ffffffff813067b8>] acpiphp_check_bridge.part.10+0xe8/0xf0
[  346.971911]  [<ffffffff81306f92>] hotplug_event+0xf2/0x1a0
[  346.973776]  [<ffffffff813070a1>] acpiphp_hotplug_event+0x61/0xe0
[  346.975630]  [<ffffffff8132634e>] acpi_device_hotplug+0x37c/0x3c2
[  346.977471]  [<ffffffff81320359>] acpi_hotplug_work_fn+0x17/0x22
[  346.979299]  [<ffffffff8105e12a>] process_one_work+0x17a/0x440
[  346.981122]  [<ffffffff8105ed29>] worker_thread+0x119/0x390
[  346.982956]  [<ffffffff8105ec10>] ? manage_workers.isra.25+0x2a0/0x2a0
[  346.984762]  [<ffffffff81064dad>] kthread+0xcd/0xf0
[  346.986581]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
[  346.988419]  [<ffffffff8181fefc>] ret_from_fork+0x7c/0xb0
[  346.990221]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180

I have to leave now but I can continue debugging tomorrow if needed.

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

* Re: [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-31 17:09                 ` Mika Westerberg
@ 2014-01-31 17:34                   ` Rafael J. Wysocki
  2014-02-02  0:12                     ` Rafael J. Wysocki
  0 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-01-31 17:34 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Friday, January 31, 2014 07:09:51 PM Mika Westerberg wrote:
> On Fri, Jan 31, 2014 at 05:16:03PM +0100, Rafael J. Wysocki wrote:
> > On Friday, January 31, 2014 06:01:57 PM Mika Westerberg wrote:
> > > On Fri, Jan 31, 2014 at 05:40:11PM +0200, Mika Westerberg wrote:
> > > > On Fri, Jan 31, 2014 at 04:42:21PM +0100, Rafael J. Wysocki wrote:
> > > > > On Friday, January 31, 2014 05:28:36 PM Mika Westerberg wrote:
> > > > > > On Wed, Jan 29, 2014 at 01:00:57AM +0100, Rafael J. Wysocki wrote:
> > > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > > 
> > > > > > > Use the observation that the ACPI scan handler of the device object
> > > > > > > in acpi_hotplug_notify_cb() can be obtained from that device object's
> > > > > > > handler pointer and do not pass it as data to
> > > > > > > acpi_install_hotplug_notify_handler() in acpi_scan_init_hotplug().
> > > > > > > 
> > > > > > > That allows the second argument of acpi_install_hotplug_notify_handler()
> > > > > > > to be dropped, so do it and update its callers accordingly.
> > > > > > > 
> > > > > > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > > ---
> > > > > > >  drivers/acpi/scan.c                |   31 ++++++++++++++++++-------------
> > > > > > >  drivers/pci/hotplug/acpiphp_glue.c |    2 +-
> > > > > > >  include/acpi/acpi_bus.h            |    2 +-
> > > > > > >  3 files changed, 20 insertions(+), 15 deletions(-)
> > > > > > > 
> > > > > > > Index: linux-pm/drivers/acpi/scan.c
> > > > > > > ===================================================================
> > > > > > > --- linux-pm.orig/drivers/acpi/scan.c
> > > > > > > +++ linux-pm/drivers/acpi/scan.c
> > > > > > > @@ -487,7 +487,6 @@ static void acpi_device_hotplug(void *da
> > > > > > >  
> > > > > > >  static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
> > > > > > >  {
> > > > > > > -	struct acpi_scan_handler *handler = data;
> > > > > > >  	u32 ost_code = ACPI_OST_SC_SUCCESS;
> > > > > > >  	struct acpi_device *adev;
> > > > > > >  	acpi_status status;
> > > > > > > @@ -503,13 +502,6 @@ static void acpi_hotplug_notify_cb(acpi_
> > > > > > >  
> > > > > > >  	case ACPI_NOTIFY_EJECT_REQUEST:
> > > > > > >  		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
> > > > > > > -		if (handler && !handler->hotplug.enabled) {
> > > > > > > -			acpi_handle_err(handle, "Eject disabled\n");
> > > > > > > -			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
> > > > > > > -			goto out;
> > > > > > > -		}
> > > > > > > -		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
> > > > > > > -					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
> > > > > > >  		break;
> > > > > > >  
> > > > > > >  	case ACPI_NOTIFY_DEVICE_WAKE:
> > > > > > > @@ -535,11 +527,24 @@ static void acpi_hotplug_notify_cb(acpi_
> > > > > > >  		goto out;
> > > > > > >  	}
> > > > > > >  
> > > > > > > +	mutex_lock(&acpi_scan_lock);
> > > > > > 
> > > > > > This is weird. I'm testing against your test-next branch which has this
> > > > > > patch included. If I remove locking here, TBT hotplug works fine. Otherwise
> > > > > > I can see the first hotplug/unplug works but after that I cannot get any
> > > > > > events anymore.
> > > > > 
> > > > > Weird indeed.  I don't seem to be able to reproduce that on my Aspire S5.
> > > > > 
> > > > > What system are you testing on?
> > > > 
> > > > This is Intel NUC. Let me see if I can reproduce this on S5 with longer
> > > > chain of devices.
> > > 
> > > OK, so on S5 this works even with longer chain. However, exactly the same
> > > kernel image on NUC fails after first hotplug/unplug cycle.
> > 
> > Well, we need to figure out what happens there.
> > 
> > Please add printks (1) before mutex_lock(), (2) before the if (type == ...)
> > instruction, (3) before the acpi_evaluate_hotplug_ost() under the if () and (4)
> > before the get_device() in acpi_notify_hotplug_cb() and check if they are all
> > printed (on NUC).
> 
> Looks like something doesn't release that lock. I added printks what you
> suggested and after first hotplug/unplug last messages I get are:
> 
> [   64.914639] ACPI: \_SB_.PCI0.RP05: ACPI_NOTIFY_BUS_CHECK event
> [   64.914640] ACPI: \_SB_.PCI0.RP05: BEFORE mutex_lock()
> 
> Then running sysrq-w I get following task as blocked:
> 
> [  346.885950] SysRq : Show Blocked State
> [  346.887733]   task                        PC stack   pid father
> [  346.889535] kworker/0:0     D ffff880100241ae0  5280     4      2 0x00000000
> [  346.891355] Workqueue: kacpi_notify acpi_os_execute_deferred
> [  346.893171]  ffff8801003c7d30 0000000000000046 ffff880100241710 ffffffff81e10460
> [  346.895011]  ffff8801003c7fd8 00000000000129c0 00000000000129c0 ffff880100241710
> [  346.896849]  ffffffff81e5db70 ffffffff81e5db74 ffff880100241710 00000000ffffffff
> [  346.898702] Call Trace:
> [  346.900518]  [<ffffffff81815bc4>] schedule_preempt_disabled+0x24/0x70
> [  346.902338]  [<ffffffff818175f2>] __mutex_lock_slowpath+0x132/0x1b0
> [  346.904164]  [<ffffffff8181768a>] mutex_lock+0x1a/0x2a
> [  346.905993]  [<ffffffff81324845>] acpi_hotplug_notify_cb+0x70/0x227
> [  346.907820]  [<ffffffff813384f4>] acpi_ev_notify_dispatch+0x44/0x5c
> [  346.909637]  [<ffffffff8131fa8d>] acpi_os_execute_deferred+0xf/0x1b
> [  346.911455]  [<ffffffff8105e12a>] process_one_work+0x17a/0x440
> [  346.913285]  [<ffffffff8105ed29>] worker_thread+0x119/0x390
> [  346.915121]  [<ffffffff8105ec10>] ? manage_workers.isra.25+0x2a0/0x2a0
> [  346.916970]  [<ffffffff81064dad>] kthread+0xcd/0xf0
> [  346.918809]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
> [  346.920653]  [<ffffffff8181fefc>] ret_from_fork+0x7c/0xb0
> [  346.922501]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
> [  346.924351] kworker/u8:5    D ffff88006ea55860  4696   945      2 0x00000000
> [  346.926212] Workqueue: kacpi_hotplug acpi_hotplug_work_fn
> [  346.928074]  ffff88006de49a40 0000000000000046 ffff88006ea55490 ffff880100245490
> [  346.929978]  ffff88006de49fd8 00000000000129c0 00000000000129c0 ffff88006ea55490
> [  346.931872]  ffff88006de49ba0 7fffffffffffffff ffff88006de49b98 ffff88006ea55490
> [  346.933753] Call Trace:
> [  346.935626]  [<ffffffff81815794>] schedule+0x24/0x70
> [  346.937516]  [<ffffffff81814a89>] schedule_timeout+0x1a9/0x2a0
> [  346.939415]  [<ffffffff8107dda8>] ? __wake_up_common+0x58/0x90
> [  346.941312]  [<ffffffff81816968>] wait_for_completion+0x98/0x100
> [  346.943222]  [<ffffffff81071b70>] ? wake_up_state+0x10/0x10
> [  346.945133]  [<ffffffff8105ba25>] flush_workqueue+0x115/0x5a0
> [  346.947054]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
> [  346.948986]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
> [  346.950904]  [<ffffffff81320340>] acpi_os_wait_events_complete+0x1c/0x1e
> [  346.952829]  [<ffffffff8133a387>] acpi_remove_notify_handler+0x78/0x1ef
> [  346.954748]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
> [  346.956669]  [<ffffffff813226df>] acpi_remove_pm_notifier+0x39/0x5c
> [  346.958592]  [<ffffffff81309ab5>] pci_acpi_cleanup+0x25/0x50
> [  346.960508]  [<ffffffff8132368c>] acpi_platform_notify_remove+0x44/0x53
> [  346.962427]  [<ffffffff814426f2>] device_del+0x142/0x1b0
> [  346.964333]  [<ffffffff812edcfa>] pci_remove_bus_device+0x7a/0x100
> [  346.966238]  [<ffffffff812edd95>] pci_stop_and_remove_bus_device+0x15/0x20
> [  346.968140]  [<ffffffff8130639e>] disable_slot+0x4e/0xa0
> [  346.970030]  [<ffffffff813067b8>] acpiphp_check_bridge.part.10+0xe8/0xf0
> [  346.971911]  [<ffffffff81306f92>] hotplug_event+0xf2/0x1a0
> [  346.973776]  [<ffffffff813070a1>] acpiphp_hotplug_event+0x61/0xe0
> [  346.975630]  [<ffffffff8132634e>] acpi_device_hotplug+0x37c/0x3c2
> [  346.977471]  [<ffffffff81320359>] acpi_hotplug_work_fn+0x17/0x22
> [  346.979299]  [<ffffffff8105e12a>] process_one_work+0x17a/0x440
> [  346.981122]  [<ffffffff8105ed29>] worker_thread+0x119/0x390
> [  346.982956]  [<ffffffff8105ec10>] ? manage_workers.isra.25+0x2a0/0x2a0
> [  346.984762]  [<ffffffff81064dad>] kthread+0xcd/0xf0
> [  346.986581]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
> [  346.988419]  [<ffffffff8181fefc>] ret_from_fork+0x7c/0xb0
> [  346.990221]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
> 
> I have to leave now but I can continue debugging tomorrow if needed.

No need for now, I think I know what's happening.  I'll follow up later.

Thanks!

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

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

* Re: [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-01-31 17:34                   ` Rafael J. Wysocki
@ 2014-02-02  0:12                     ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:12 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Friday, January 31, 2014 06:34:22 PM Rafael J. Wysocki wrote:
> On Friday, January 31, 2014 07:09:51 PM Mika Westerberg wrote:
> > On Fri, Jan 31, 2014 at 05:16:03PM +0100, Rafael J. Wysocki wrote:

[...]

> > 
> > [   64.914639] ACPI: \_SB_.PCI0.RP05: ACPI_NOTIFY_BUS_CHECK event
> > [   64.914640] ACPI: \_SB_.PCI0.RP05: BEFORE mutex_lock()
> > 
> > Then running sysrq-w I get following task as blocked:
> > 
> > [  346.885950] SysRq : Show Blocked State
> > [  346.887733]   task                        PC stack   pid father
> > [  346.889535] kworker/0:0     D ffff880100241ae0  5280     4      2 0x00000000
> > [  346.891355] Workqueue: kacpi_notify acpi_os_execute_deferred
> > [  346.893171]  ffff8801003c7d30 0000000000000046 ffff880100241710 ffffffff81e10460
> > [  346.895011]  ffff8801003c7fd8 00000000000129c0 00000000000129c0 ffff880100241710
> > [  346.896849]  ffffffff81e5db70 ffffffff81e5db74 ffff880100241710 00000000ffffffff
> > [  346.898702] Call Trace:
> > [  346.900518]  [<ffffffff81815bc4>] schedule_preempt_disabled+0x24/0x70
> > [  346.902338]  [<ffffffff818175f2>] __mutex_lock_slowpath+0x132/0x1b0
> > [  346.904164]  [<ffffffff8181768a>] mutex_lock+0x1a/0x2a
> > [  346.905993]  [<ffffffff81324845>] acpi_hotplug_notify_cb+0x70/0x227
> > [  346.907820]  [<ffffffff813384f4>] acpi_ev_notify_dispatch+0x44/0x5c
> > [  346.909637]  [<ffffffff8131fa8d>] acpi_os_execute_deferred+0xf/0x1b
> > [  346.911455]  [<ffffffff8105e12a>] process_one_work+0x17a/0x440
> > [  346.913285]  [<ffffffff8105ed29>] worker_thread+0x119/0x390
> > [  346.915121]  [<ffffffff8105ec10>] ? manage_workers.isra.25+0x2a0/0x2a0
> > [  346.916970]  [<ffffffff81064dad>] kthread+0xcd/0xf0
> > [  346.918809]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
> > [  346.920653]  [<ffffffff8181fefc>] ret_from_fork+0x7c/0xb0
> > [  346.922501]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
> > [  346.924351] kworker/u8:5    D ffff88006ea55860  4696   945      2 0x00000000
> > [  346.926212] Workqueue: kacpi_hotplug acpi_hotplug_work_fn
> > [  346.928074]  ffff88006de49a40 0000000000000046 ffff88006ea55490 ffff880100245490
> > [  346.929978]  ffff88006de49fd8 00000000000129c0 00000000000129c0 ffff88006ea55490
> > [  346.931872]  ffff88006de49ba0 7fffffffffffffff ffff88006de49b98 ffff88006ea55490
> > [  346.933753] Call Trace:
> > [  346.935626]  [<ffffffff81815794>] schedule+0x24/0x70
> > [  346.937516]  [<ffffffff81814a89>] schedule_timeout+0x1a9/0x2a0
> > [  346.939415]  [<ffffffff8107dda8>] ? __wake_up_common+0x58/0x90
> > [  346.941312]  [<ffffffff81816968>] wait_for_completion+0x98/0x100
> > [  346.943222]  [<ffffffff81071b70>] ? wake_up_state+0x10/0x10
> > [  346.945133]  [<ffffffff8105ba25>] flush_workqueue+0x115/0x5a0
> > [  346.947054]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
> > [  346.948986]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
> > [  346.950904]  [<ffffffff81320340>] acpi_os_wait_events_complete+0x1c/0x1e
> > [  346.952829]  [<ffffffff8133a387>] acpi_remove_notify_handler+0x78/0x1ef
> > [  346.954748]  [<ffffffff81309b20>] ? acpi_pci_find_companion+0x40/0x40
> > [  346.956669]  [<ffffffff813226df>] acpi_remove_pm_notifier+0x39/0x5c
> > [  346.958592]  [<ffffffff81309ab5>] pci_acpi_cleanup+0x25/0x50
> > [  346.960508]  [<ffffffff8132368c>] acpi_platform_notify_remove+0x44/0x53
> > [  346.962427]  [<ffffffff814426f2>] device_del+0x142/0x1b0
> > [  346.964333]  [<ffffffff812edcfa>] pci_remove_bus_device+0x7a/0x100
> > [  346.966238]  [<ffffffff812edd95>] pci_stop_and_remove_bus_device+0x15/0x20
> > [  346.968140]  [<ffffffff8130639e>] disable_slot+0x4e/0xa0
> > [  346.970030]  [<ffffffff813067b8>] acpiphp_check_bridge.part.10+0xe8/0xf0
> > [  346.971911]  [<ffffffff81306f92>] hotplug_event+0xf2/0x1a0
> > [  346.973776]  [<ffffffff813070a1>] acpiphp_hotplug_event+0x61/0xe0
> > [  346.975630]  [<ffffffff8132634e>] acpi_device_hotplug+0x37c/0x3c2
> > [  346.977471]  [<ffffffff81320359>] acpi_hotplug_work_fn+0x17/0x22
> > [  346.979299]  [<ffffffff8105e12a>] process_one_work+0x17a/0x440
> > [  346.981122]  [<ffffffff8105ed29>] worker_thread+0x119/0x390
> > [  346.982956]  [<ffffffff8105ec10>] ? manage_workers.isra.25+0x2a0/0x2a0
> > [  346.984762]  [<ffffffff81064dad>] kthread+0xcd/0xf0
> > [  346.986581]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
> > [  346.988419]  [<ffffffff8181fefc>] ret_from_fork+0x7c/0xb0
> > [  346.990221]  [<ffffffff81064ce0>] ? kthread_create_on_node+0x180/0x180
> > 
> > I have to leave now but I can continue debugging tomorrow if needed.
> 
> No need for now, I think I know what's happening.  I'll follow up later.

acpi_remove_notify_handler() which is called from acpi_remove_pm_notifier()
executes acpi_os_wait_events_complete() which does flush_workqueue(kacpi_notify_wq)
and all that happens under acpi_scan_lock acquired by acpi_device_hotplug().

Now, acpi_hotplug_notify_cb() runs from kacpi_notify_wq, so effectively
acpi_os_wait_events_complete() waits for it to return, so if it attempts
to acquire acpi_scan_lock, it will deadlock.  Which happens on the NUC.

The good news is that we can use a different lock to eliminate the race
I wanted to deal with using acpi_scan_lock, but that required me to rework
the whole patchset.  I'll send a new version shortly, but I need to update
the ACPIPHP updates it is on top of.

Thanks!

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

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

* [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (11 preceding siblings ...)
  2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
@ 2014-02-02  0:19 ` Rafael J. Wysocki
  2014-02-02  0:21   ` [PATCH v2 1/13] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
                     ` (14 more replies)
  2014-02-11  0:19 ` [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Bjorn Helgaas
  13 siblings, 15 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:19 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

On Monday, January 27, 2014 01:37:17 AM Rafael J. Wysocki wrote:
> Hi All,
> 
> ACPIPHP can be simplified a bit on top of some PCI and ACPI changes merged
> recently and the following series of patches implements those simplifications:
> 
> [1/11] Fix up two kerneldoc comments in acpiphp_glue.c.
> [2/11] Get rid of an unnecessary label in register_slot().
> [3/11] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
> [4/11] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
> [5/11] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
> [6/11] Drop acpiphp_bus_add() (which has only one user).
> [7/11] Drop crit_sect mutexes (that are redundant).
> [8/11] Clean up the usage of the slot variable in hotplug_event().
> [9/11] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
> [10/11] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
> [11/11] Drop handle argument from the member functions of struct acpi_dock_ops.
> 
> All of that is relateively straightforward, but I have some more intrusive changes
> on top of it in the works.  They will be posted separately later this week.

I've learned a couple of things since I sent this patchset.  First, all
bus->devices list walks that may remove PCI devices should be done in reverse
order or they can crash if virtual functions are involved.  Second, hotplug_event()
(in acpiphp_glue.c) has to acquire pci_rescan_remove_lock by itself, because it
may be called from multiple places and all of them need that lock to be held.
That is done by patches [1-2/13] which I'm planning to push as fixes for 3.14-rc2.

The rest is pretty much the same as last time except that the old patch [9/11]
became [3/13] in this series and it has been changed so that the list is walked in
reverse order.

Thanks!

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

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

* [PATCH v2 1/13] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
@ 2014-02-02  0:21   ` Rafael J. Wysocki
  2014-02-02  0:22   ` [PATCH v2 2/13] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() Rafael J. Wysocki
                     ` (13 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:21 UTC (permalink / raw)
  To: ACPI Devel Maling List, Linux PCI
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Mika Westerberg

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

According to the changelog of commit 29ed1f29b68a (PCI: pciehp: Fix null
pointer deref when hot-removing SR-IOV device) it is unsafe to walk the
bus->devices list of a PCI bus and remove devices from it in direct order,
because that may lead to NULL pointer dereferences related to virtual
functions.

For this reason, change all of the bus->devices list walks in
acpiphp_glue.c during which devices may be removed to be carried out in
reverse order.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -742,7 +742,7 @@ static void trim_stale_devices(struct pc
 
 		/* The device is a bridge. so check the bus below it. */
 		pm_runtime_get_sync(&dev->dev);
-		list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+		list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list)
 			trim_stale_devices(child);
 
 		pm_runtime_put(&dev->dev);
@@ -773,8 +773,8 @@ static void acpiphp_check_bridge(struct
 			; /* do nothing */
 		} else if (get_slot_status(slot) == ACPI_STA_ALL) {
 			/* remove stale devices if any */
-			list_for_each_entry_safe(dev, tmp, &bus->devices,
-						 bus_list)
+			list_for_each_entry_safe_reverse(dev, tmp,
+							 &bus->devices, bus_list)
 				if (PCI_SLOT(dev->devfn) == slot->device)
 					trim_stale_devices(dev);
 
@@ -805,7 +805,7 @@ static void acpiphp_sanitize_bus(struct
 	int i;
 	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
 
-	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+	list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
 		for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
 			struct resource *res = &dev->resource[i];
 			if ((res->flags & type_mask) && !res->start &&


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

* [PATCH v2 2/13] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event()
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
  2014-02-02  0:21   ` [PATCH v2 1/13] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
@ 2014-02-02  0:22   ` Rafael J. Wysocki
  2014-02-02  0:23   ` [PATCH v2 3/13] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
                     ` (12 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:22 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Commit 9217a984671e (ACPI / hotplug / PCI: Use global PCI rescan-remove
locking) modified ACPIPHP to protect its PCI device removal and addition
code paths from races against sysfs-driven rescan and remove operations
with the help of PCI rescan-remove locking.  However, it overlooked the
fact that hotplug_event_work() is not the only caller of hotplug_event()
which may also be called by dock_hotplug_event() and that code path
is missing the PCI rescan-remove locking.  This means that, although
the PCI rescan-remove lock is held as appropriate during the handling
of events originating from handle_hotplug_event(), the ACPIPHP's
operations resulting from dock events may still suffer the race
conditions that commit 9217a984671e was supposed to eliminate.

To address that problem, move the PCI rescan-remove locking from
hotplug_event_work() to hotplug_event() so that it is used regardless
of the way that function is invoked.

Revamps: 9217a984671e (ACPI / hotplug / PCI: Use global PCI rescan-remove locking)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -852,6 +852,7 @@ static void hotplug_event(acpi_handle ha
 
 	mutex_unlock(&acpiphp_context_lock);
 
+	pci_lock_rescan_remove();
 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
 	switch (type) {
@@ -905,6 +906,7 @@ static void hotplug_event(acpi_handle ha
 		break;
 	}
 
+	pci_unlock_rescan_remove();
 	if (bridge)
 		put_bridge(bridge);
 }
@@ -915,11 +917,9 @@ static void hotplug_event_work(void *dat
 	acpi_handle handle = context->handle;
 
 	acpi_scan_lock_acquire();
-	pci_lock_rescan_remove();
 
 	hotplug_event(handle, type, context);
 
-	pci_unlock_rescan_remove();
 	acpi_scan_lock_release();
 	acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
 	put_bridge(context->func.parent);


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

* [PATCH v2 3/13] ACPI / hotplug / PCI: Simplify disable_slot()
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
  2014-02-02  0:21   ` [PATCH v2 1/13] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
  2014-02-02  0:22   ` [PATCH v2 2/13] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() Rafael J. Wysocki
@ 2014-02-02  0:23   ` Rafael J. Wysocki
  2014-02-02  0:24   ` [PATCH v2 4/13] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
                     ` (11 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:23 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

After recent PCI core changes related to the rescan/remove locking,
the ACPIPHP's disable_slot() function is only called under the
general PCI rescan/remove lock, so it doesn't have to use
dev_in_slot() any more to avoid race conditions.  Make it simply
walk the devices on the bus and drop the ones in the slot being
disabled and drop dev_in_slot() which has no more users.

Moreover, to avoid problems described in the changelog of commit
29ed1f29b68a (PCI: pciehp: Fix null pointer deref when hot-removing
SR-IOV device), make disable_slot() carry out the list walk in
reverse order.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   28 +++++-----------------------
 1 file changed, 5 insertions(+), 23 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -604,32 +604,15 @@ static void __ref enable_slot(struct acp
 	}
 }
 
-/* return first device in slot, acquiring a reference on it */
-static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
-{
-	struct pci_bus *bus = slot->bus;
-	struct pci_dev *dev;
-	struct pci_dev *ret = NULL;
-
-	down_read(&pci_bus_sem);
-	list_for_each_entry(dev, &bus->devices, bus_list)
-		if (PCI_SLOT(dev->devfn) == slot->device) {
-			ret = pci_dev_get(dev);
-			break;
-		}
-	up_read(&pci_bus_sem);
-
-	return ret;
-}
-
 /**
  * disable_slot - disable a slot
  * @slot: ACPI PHP slot
  */
 static void disable_slot(struct acpiphp_slot *slot)
 {
+	struct pci_bus *bus = slot->bus;
+	struct pci_dev *dev, *prev;
 	struct acpiphp_func *func;
-	struct pci_dev *pdev;
 
 	/*
 	 * enable_slot() enumerates all functions in this device via
@@ -637,10 +620,9 @@ static void disable_slot(struct acpiphp_
 	 * methods (_EJ0, etc.) or not.  Therefore, we remove all functions
 	 * here.
 	 */
-	while ((pdev = dev_in_slot(slot))) {
-		pci_stop_and_remove_bus_device(pdev);
-		pci_dev_put(pdev);
-	}
+	list_for_each_entry_safe_reverse(dev, prev, &bus->devices, bus_list)
+		if (PCI_SLOT(dev->devfn) == slot->device)
+			pci_stop_and_remove_bus_device(dev);
 
 	list_for_each_entry(func, &slot->funcs, sibling)
 		acpiphp_bus_trim(func_to_handle(func));


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

* [PATCH v2 4/13] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (2 preceding siblings ...)
  2014-02-02  0:23   ` [PATCH v2 3/13] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
@ 2014-02-02  0:24   ` Rafael J. Wysocki
  2014-02-02  0:25   ` [PATCH v2 5/13] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
                     ` (10 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:24 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Add proper kerneldoc comments describing acpiphp_enumerate_slots()
and acpiphp_remove_slots().

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -968,9 +968,12 @@ static void handle_hotplug_event(acpi_ha
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-/*
- * Create hotplug slots for the PCI bus.
- * It should always return 0 to avoid skipping following notifiers.
+/**
+ * acpiphp_enumerate_slots - Enumerate PCI slots for a given bus.
+ * @bus: PCI bus to enumerate the slots for.
+ *
+ * A "slot" is an object associated with a PCI device number.  All functions
+ * (PCI devices) with the same bus and device number belong to the same slot.
  */
 void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
@@ -1043,7 +1046,10 @@ void acpiphp_enumerate_slots(struct pci_
 	}
 }
 
-/* Destroy hotplug slots associated with the PCI bus */
+/**
+ * acpiphp_remove_slots - Remove slot objects associated with a given bus.
+ * @bus: PCI bus to remove the slot objects for.
+ */
 void acpiphp_remove_slots(struct pci_bus *bus)
 {
 	struct acpiphp_bridge *bridge;


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

* [PATCH v2 5/13] ACPI / hotplug / PCI: Simplify register_slot()
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (3 preceding siblings ...)
  2014-02-02  0:24   ` [PATCH v2 4/13] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
@ 2014-02-02  0:25   ` Rafael J. Wysocki
  2014-02-02  0:26   ` [PATCH v2 6/13] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
                     ` (9 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:25 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

The err label in register_slot() is only jumped to from one place,
so move the code under the label to that place and drop the label.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -316,8 +316,10 @@ static acpi_status register_slot(acpi_ha
 
 	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 	if (!slot) {
-		status = AE_NO_MEMORY;
-		goto err;
+		mutex_lock(&acpiphp_context_lock);
+		acpiphp_put_context(context);
+		mutex_unlock(&acpiphp_context_lock);
+		return AE_NO_MEMORY;
 	}
 
 	slot->bus = bridge->pci_bus;
@@ -385,12 +387,6 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	return AE_OK;
-
- err:
-	mutex_lock(&acpiphp_context_lock);
-	acpiphp_put_context(context);
-	mutex_unlock(&acpiphp_context_lock);
-	return status;
 }
 
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)


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

* [PATCH v2 6/13] ACPI / hotplug / PCI: Drop acpiphp_bus_trim()
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (4 preceding siblings ...)
  2014-02-02  0:25   ` [PATCH v2 5/13] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
@ 2014-02-02  0:26   ` Rafael J. Wysocki
  2014-02-02  0:27   ` [PATCH v2 7/13] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
                     ` (8 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:26 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

If trim_stale_devices() calls acpi_bus_trim() directly, we can
save a potentially costly acpi_bus_get_device() invocation.  After
making that change acpiphp_bus_trim() would only be called from one
place, so move the code from it to that place and drop it.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -468,19 +468,6 @@ static unsigned char acpiphp_max_busnr(s
 }
 
 /**
- * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree.
- * @handle: ACPI device object handle to start from.
- */
-static void acpiphp_bus_trim(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
-	if (adev)
-		acpi_bus_trim(adev);
-}
-
-/**
  * acpiphp_bus_add - Scan ACPI namespace subtree.
  * @handle: ACPI object handle to start the scan from.
  */
@@ -620,8 +607,12 @@ static void disable_slot(struct acpiphp_
 		if (PCI_SLOT(dev->devfn) == slot->device)
 			pci_stop_and_remove_bus_device(dev);
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_trim(func_to_handle(func));
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev;
+
+		if (!acpi_bus_get_device(func_to_handle(func), &adev))
+			acpi_bus_trim(adev);
+	}
 
 	slot->flags &= (~SLOT_ENABLED);
 }
@@ -693,11 +684,12 @@ static unsigned int get_slot_status(stru
  */
 static void trim_stale_devices(struct pci_dev *dev)
 {
-	acpi_handle handle = ACPI_HANDLE(&dev->dev);
+	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
 	struct pci_bus *bus = dev->subordinate;
 	bool alive = false;
 
-	if (handle) {
+	if (adev) {
+		acpi_handle handle = adev->handle;
 		acpi_status status;
 		unsigned long long sta;
 
@@ -713,8 +705,8 @@ static void trim_stale_devices(struct pc
 	}
 	if (!alive) {
 		pci_stop_and_remove_bus_device(dev);
-		if (handle)
-			acpiphp_bus_trim(handle);
+		if (adev)
+			acpi_bus_trim(adev);
 	} else if (bus) {
 		struct pci_dev *child, *tmp;
 


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

* [PATCH v2 7/13] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug()
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (5 preceding siblings ...)
  2014-02-02  0:26   ` [PATCH v2 6/13] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
@ 2014-02-02  0:27   ` Rafael J. Wysocki
  2014-02-02  0:27   ` [PATCH v2 8/13] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
                     ` (7 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:27 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

If a struct acpi_device pointer is passed to acpiphp_no_hotplug()
instead of an ACPI handle, the function won't need to call
acpi_bus_get_device(), which may be costly, any more.  Then,
trim_stale_devices() can call acpiphp_no_hotplug() passing
the struct acpi_device object it already has directly to that
function.

Make those changes and update slot_no_hotplug() accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -617,11 +617,8 @@ static void disable_slot(struct acpiphp_
 	slot->flags &= (~SLOT_ENABLED);
 }
 
-static bool acpiphp_no_hotplug(acpi_handle handle)
+static bool acpiphp_no_hotplug(struct acpi_device *adev)
 {
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
 	return adev && adev->flags.no_hotplug;
 }
 
@@ -629,10 +626,13 @@ static bool slot_no_hotplug(struct acpip
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		if (acpiphp_no_hotplug(func_to_handle(func)))
-			return true;
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev = NULL;
 
+		acpi_bus_get_device(func_to_handle(func), &adev);
+		if (acpiphp_no_hotplug(adev))
+			return true;
+	}
 	return false;
 }
 
@@ -689,13 +689,12 @@ static void trim_stale_devices(struct pc
 	bool alive = false;
 
 	if (adev) {
-		acpi_handle handle = adev->handle;
 		acpi_status status;
 		unsigned long long sta;
 
-		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+		status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
 		alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
-			|| acpiphp_no_hotplug(handle);
+			|| acpiphp_no_hotplug(adev);
 	}
 	if (!alive) {
 		u32 v;


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

* [PATCH v2 8/13] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (6 preceding siblings ...)
  2014-02-02  0:27   ` [PATCH v2 7/13] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
@ 2014-02-02  0:27   ` Rafael J. Wysocki
  2014-02-02  0:28   ` [PATCH v2 9/13] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
                     ` (6 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:27 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

After recent modifications of the ACPI core making it create a struct
acpi_device object for every namespace node representing a device
regardless of the current status of that device the ACPIPHP code
can store a struct acpi_device pointer instead of an ACPI handle
in struct acpiphp_context.  This immediately makes it possible to
avoid making potentially costly calls to acpi_bus_get_device() in
two places and allows some more simplifications to be made going
forward.

The reason why that is correct is because ACPIPHP only installs
hotify handlers for namespace nodes that exist when
acpiphp_enumerate_slots() is called for their parent bridge.
That only happens if the parent bridge has an ACPI companion
associated with it, which means that the ACPI namespace scope
in question has been scanned already at that point.  That, in
turn, means that struct acpi_device objects have been created
for all namespace nodes in that scope and pointers to those
objects can be stored directly instead of their ACPI handles.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp.h      |    9 +++++--
 drivers/pci/hotplug/acpiphp_glue.c |   44 +++++++++++++++++--------------------
 2 files changed, 28 insertions(+), 25 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -117,8 +117,8 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
-	acpi_handle handle;
 	struct acpiphp_func func;
+	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
@@ -128,9 +128,14 @@ static inline struct acpiphp_context *fu
 	return container_of(func, struct acpiphp_context, func);
 }
 
+static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
+{
+	return func_to_context(func)->adev;
+}
+
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
 {
-	return func_to_context(func)->handle;
+	return func_to_acpi_device(func)->handle;
 }
 
 /*
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -73,11 +73,11 @@ static void acpiphp_context_handler(acpi
 
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
- * @handle: ACPI object handle to create the context for.
+ * @adev: ACPI device object to create the context for.
  *
  * Call under acpiphp_context_lock.
  */
-static struct acpiphp_context *acpiphp_init_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
 	acpi_status status;
@@ -86,9 +86,9 @@ static struct acpiphp_context *acpiphp_i
 	if (!context)
 		return NULL;
 
-	context->handle = handle;
+	context->adev = adev;
 	context->refcount = 1;
-	status = acpi_attach_data(handle, acpiphp_context_handler, context);
+	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
 	if (ACPI_FAILURE(status)) {
 		kfree(context);
 		return NULL;
@@ -118,7 +118,7 @@ static struct acpiphp_context *acpiphp_g
 
 /**
  * acpiphp_put_context - Drop a reference to ACPI hotplug context.
- * @handle: ACPI object handle to put the context for.
+ * @context: ACPI hotplug context to drop a reference to.
  *
  * The context object is removed if there are no more references to it.
  *
@@ -130,7 +130,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->handle, acpiphp_context_handler);
+	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
 	kfree(context);
 }
 
@@ -265,6 +265,7 @@ static acpi_status register_slot(acpi_ha
 {
 	struct acpiphp_bridge *bridge = data;
 	struct acpiphp_context *context;
+	struct acpi_device *adev;
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *newfunc;
 	acpi_status status = AE_OK;
@@ -284,12 +285,14 @@ static acpi_status register_slot(acpi_ha
 				"can't evaluate _ADR (%#x)\n", status);
 		return AE_OK;
 	}
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
 
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 
 	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_init_context(handle);
+	context = acpiphp_init_context(adev);
 	if (!context) {
 		mutex_unlock(&acpiphp_context_lock);
 		acpi_handle_err(handle, "No hotplug context\n");
@@ -607,12 +610,8 @@ static void disable_slot(struct acpiphp_
 		if (PCI_SLOT(dev->devfn) == slot->device)
 			pci_stop_and_remove_bus_device(dev);
 
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		struct acpi_device *adev;
-
-		if (!acpi_bus_get_device(func_to_handle(func), &adev))
-			acpi_bus_trim(adev);
-	}
+	list_for_each_entry(func, &slot->funcs, sibling)
+		acpi_bus_trim(func_to_acpi_device(func));
 
 	slot->flags &= (~SLOT_ENABLED);
 }
@@ -626,13 +625,10 @@ static bool slot_no_hotplug(struct acpip
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		struct acpi_device *adev = NULL;
-
-		acpi_bus_get_device(func_to_handle(func), &adev);
-		if (acpiphp_no_hotplug(adev))
+	list_for_each_entry(func, &slot->funcs, sibling)
+		if (acpiphp_no_hotplug(func_to_acpi_device(func)))
 			return true;
-	}
+
 	return false;
 }
 
@@ -883,7 +879,7 @@ static void hotplug_event(acpi_handle ha
 static void hotplug_event_work(void *data, u32 type)
 {
 	struct acpiphp_context *context = data;
-	acpi_handle handle = context->handle;
+	acpi_handle handle = context->adev->handle;
 
 	acpi_scan_lock_acquire();
 
@@ -941,7 +937,7 @@ static void handle_hotplug_event(acpi_ha
 
 	mutex_lock(&acpiphp_context_lock);
 	context = acpiphp_get_context(handle);
-	if (context && !WARN_ON(context->handle != handle)) {
+	if (context && !WARN_ON(context->adev->handle != handle)) {
 		get_bridge(context->func.parent);
 		acpiphp_put_context(context);
 		acpi_hotplug_execute(hotplug_event_work, context, type);
@@ -965,16 +961,18 @@ static void handle_hotplug_event(acpi_ha
 void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
 	struct acpiphp_bridge *bridge;
+	struct acpi_device *adev;
 	acpi_handle handle;
 	acpi_status status;
 
 	if (acpiphp_disabled)
 		return;
 
-	handle = ACPI_HANDLE(bus->bridge);
-	if (!handle)
+	adev = ACPI_COMPANION(bus->bridge);
+	if (!adev)
 		return;
 
+	handle = adev->handle;
 	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 	if (!bridge) {
 		acpi_handle_err(handle, "No memory for bridge object\n");


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

* [PATCH v2 9/13] ACPI / hotplug / PCI: Drop acpiphp_bus_add()
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (7 preceding siblings ...)
  2014-02-02  0:27   ` [PATCH v2 8/13] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
@ 2014-02-02  0:28   ` Rafael J. Wysocki
  2014-02-02  0:29   ` [PATCH v2 10/13] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
                     ` (5 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:28 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

acpiphp_bus_add() is only called from one place, so move the code out
of it into that place and drop it.  Also make that code use
func_to_acpi_device() to get the struct acpi_device pointer it needs
instead of calling acpi_bus_get_device() which may be costly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -470,20 +470,6 @@ static unsigned char acpiphp_max_busnr(s
 	return max;
 }
 
-/**
- * acpiphp_bus_add - Scan ACPI namespace subtree.
- * @handle: ACPI object handle to start the scan from.
- */
-static void acpiphp_bus_add(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_scan(handle);
-	acpi_bus_get_device(handle, &adev);
-	if (acpi_device_enumerated(adev))
-		acpi_device_set_power(adev, ACPI_STATE_D0);
-}
-
 static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
 {
 	struct acpiphp_func *func;
@@ -523,9 +509,13 @@ static int acpiphp_rescan_slot(struct ac
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_add(func_to_handle(func));
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev = func_to_acpi_device(func);
 
+		acpi_bus_scan(adev->handle);
+		if (acpi_device_enumerated(adev))
+			acpi_device_set_power(adev, ACPI_STATE_D0);
+	}
 	return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0));
 }
 


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

* [PATCH v2 10/13] ACPI / hotplug / PCI: Drop crit_sect locking
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (8 preceding siblings ...)
  2014-02-02  0:28   ` [PATCH v2 9/13] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
@ 2014-02-02  0:29   ` Rafael J. Wysocki
  2014-02-02  0:30   ` [PATCH v2 11/13] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
                     ` (4 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:29 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

After recent PCI core changes related to the rescan/remove locking,
the code sections under crit_sect mutexes from ACPIPHP slot objects
are always executed under the general PCI rescan/remove lock.
For this reason, the crit_sect mutexes are simply redundant, so drop
them.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp.h      |    1 -
 drivers/pci/hotplug/acpiphp_glue.c |   23 +++--------------------
 2 files changed, 3 insertions(+), 21 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -328,7 +328,6 @@ static acpi_status register_slot(acpi_ha
 	slot->bus = bridge->pci_bus;
 	slot->device = device;
 	INIT_LIST_HEAD(&slot->funcs);
-	mutex_init(&slot->crit_sect);
 
 	list_add_tail(&slot->node, &bridge->slots);
 
@@ -723,7 +722,6 @@ static void acpiphp_check_bridge(struct
 		struct pci_bus *bus = slot->bus;
 		struct pci_dev *dev, *tmp;
 
-		mutex_lock(&slot->crit_sect);
 		if (slot_no_hotplug(slot)) {
 			; /* do nothing */
 		} else if (get_slot_status(slot) == ACPI_STA_ALL) {
@@ -738,7 +736,6 @@ static void acpiphp_check_bridge(struct
 		} else {
 			disable_slot(slot);
 		}
-		mutex_unlock(&slot->crit_sect);
 	}
 }
 
@@ -821,12 +818,8 @@ static void hotplug_event(acpi_handle ha
 		} else {
 			struct acpiphp_slot *slot = func->slot;
 
-			if (slot->flags & SLOT_IS_GOING_AWAY)
-				break;
-
-			mutex_lock(&slot->crit_sect);
-			enable_slot(slot);
-			mutex_unlock(&slot->crit_sect);
+			if (!(slot->flags & SLOT_IS_GOING_AWAY))
+				enable_slot(slot);
 		}
 		break;
 
@@ -837,7 +830,6 @@ static void hotplug_event(acpi_handle ha
 			acpiphp_check_bridge(bridge);
 		} else {
 			struct acpiphp_slot *slot = func->slot;
-			int ret;
 
 			if (slot->flags & SLOT_IS_GOING_AWAY)
 				break;
@@ -846,10 +838,7 @@ static void hotplug_event(acpi_handle ha
 			 * Check if anything has changed in the slot and rescan
 			 * from the parent if that's the case.
 			 */
-			mutex_lock(&slot->crit_sect);
-			ret = acpiphp_rescan_slot(slot);
-			mutex_unlock(&slot->crit_sect);
-			if (ret)
+			if (acpiphp_rescan_slot(slot))
 				acpiphp_check_bridge(func->parent);
 		}
 		break;
@@ -1055,13 +1044,10 @@ int acpiphp_enable_slot(struct acpiphp_s
 	if (slot->flags & SLOT_IS_GOING_AWAY)
 		return -ENODEV;
 
-	mutex_lock(&slot->crit_sect);
 	/* configure all functions */
 	if (!(slot->flags & SLOT_ENABLED))
 		enable_slot(slot);
 
-	mutex_unlock(&slot->crit_sect);
-
 	pci_unlock_rescan_remove();
 	return 0;
 }
@@ -1077,8 +1063,6 @@ static int acpiphp_disable_and_eject_slo
 	if (slot->flags & SLOT_IS_GOING_AWAY)
 		return -ENODEV;
 
-	mutex_lock(&slot->crit_sect);
-
 	/* unconfigure all functions */
 	disable_slot(slot);
 
@@ -1092,7 +1076,6 @@ static int acpiphp_disable_and_eject_slo
 			break;
 		}
 
-	mutex_unlock(&slot->crit_sect);
 	return 0;
 }
 
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -93,7 +93,6 @@ struct acpiphp_slot {
 	struct list_head funcs;		/* one slot may have different
 					   objects (i.e. for each function) */
 	struct slot *slot;
-	struct mutex crit_sect;
 
 	u8		device;		/* pci device# */
 	u32		flags;		/* see below */


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

* [PATCH v2 11/13] ACPI / hotplug / PCI: Simplify hotplug_event()
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (9 preceding siblings ...)
  2014-02-02  0:29   ` [PATCH v2 10/13] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
@ 2014-02-02  0:30   ` Rafael J. Wysocki
  2014-02-02  0:31   ` [PATCH v2 12/13] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
                     ` (3 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:30 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

A few lines of code can be cut from hotplug_event() by defining
and initializing the slot variable at the top of the function,
so do that.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -792,6 +792,7 @@ static void hotplug_event(acpi_handle ha
 {
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
+	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
 	char objname[64];
 	struct acpi_buffer buffer = { .length = sizeof(objname),
@@ -813,14 +814,11 @@ static void hotplug_event(acpi_handle ha
 		pr_debug("%s: Bus check notify on %s\n", __func__, objname);
 		pr_debug("%s: re-enumerating slots under %s\n",
 			 __func__, objname);
-		if (bridge) {
+		if (bridge)
 			acpiphp_check_bridge(bridge);
-		} else {
-			struct acpiphp_slot *slot = func->slot;
+		else if (!(slot->flags & SLOT_IS_GOING_AWAY))
+			enable_slot(slot);
 
-			if (!(slot->flags & SLOT_IS_GOING_AWAY))
-				enable_slot(slot);
-		}
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
@@ -828,12 +826,7 @@ static void hotplug_event(acpi_handle ha
 		pr_debug("%s: Device check notify on %s\n", __func__, objname);
 		if (bridge) {
 			acpiphp_check_bridge(bridge);
-		} else {
-			struct acpiphp_slot *slot = func->slot;
-
-			if (slot->flags & SLOT_IS_GOING_AWAY)
-				break;
-
+		} else if (!(slot->flags & SLOT_IS_GOING_AWAY)) {
 			/*
 			 * Check if anything has changed in the slot and rescan
 			 * from the parent if that's the case.
@@ -846,7 +839,7 @@ static void hotplug_event(acpi_handle ha
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
 		pr_debug("%s: Device eject notify on %s\n", __func__, objname);
-		acpiphp_disable_and_eject_slot(func->slot);
+		acpiphp_disable_and_eject_slot(slot);
 		break;
 	}
 


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

* [PATCH v2 12/13] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event()
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (10 preceding siblings ...)
  2014-02-02  0:30   ` [PATCH v2 11/13] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
@ 2014-02-02  0:31   ` Rafael J. Wysocki
  2014-02-02  0:31   ` [PATCH v2 13/13] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations Rafael J. Wysocki
                     ` (2 subsequent siblings)
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:31 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Make hotplug_event() use acpi_handle_debug() instead of an open-coded
debug message printing and clean up the messages printed by it.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -794,9 +794,6 @@ static void hotplug_event(acpi_handle ha
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
-	char objname[64];
-	struct acpi_buffer buffer = { .length = sizeof(objname),
-				      .pointer = objname };
 
 	mutex_lock(&acpiphp_context_lock);
 	bridge = context->bridge;
@@ -806,14 +803,11 @@ static void hotplug_event(acpi_handle ha
 	mutex_unlock(&acpiphp_context_lock);
 
 	pci_lock_rescan_remove();
-	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		/* bus re-enumerate */
-		pr_debug("%s: Bus check notify on %s\n", __func__, objname);
-		pr_debug("%s: re-enumerating slots under %s\n",
-			 __func__, objname);
+		acpi_handle_debug(handle, "Bus check in %s()\n", __func__);
 		if (bridge)
 			acpiphp_check_bridge(bridge);
 		else if (!(slot->flags & SLOT_IS_GOING_AWAY))
@@ -823,7 +817,7 @@ static void hotplug_event(acpi_handle ha
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		/* device check */
-		pr_debug("%s: Device check notify on %s\n", __func__, objname);
+		acpi_handle_debug(handle, "Device check in %s()\n", __func__);
 		if (bridge) {
 			acpiphp_check_bridge(bridge);
 		} else if (!(slot->flags & SLOT_IS_GOING_AWAY)) {
@@ -838,7 +832,7 @@ static void hotplug_event(acpi_handle ha
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
-		pr_debug("%s: Device eject notify on %s\n", __func__, objname);
+		acpi_handle_debug(handle, "Eject request in %s()\n", __func__);
 		acpiphp_disable_and_eject_slot(slot);
 		break;
 	}


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

* [PATCH v2 13/13] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (11 preceding siblings ...)
  2014-02-02  0:31   ` [PATCH v2 12/13] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
@ 2014-02-02  0:31   ` Rafael J. Wysocki
  2014-02-03  1:47   ` [PATCH] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock Rafael J. Wysocki
  2014-02-03 10:44   ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Mika Westerberg
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:31 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

None of the existing users of struct acpi_dock_ops actually needs the
first argument of its member functions, so redefine those functions
to take only two arguments, the event type and data pointer, and
update the users of struct acpi_dock_ops accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/dock.c                |    4 ++--
 drivers/ata/libata-acpi.c          |    8 ++++----
 drivers/pci/hotplug/acpiphp_glue.c |   13 +++++++------
 include/acpi/acpi_drivers.h        |    6 +++---
 4 files changed, 16 insertions(+), 15 deletions(-)

Index: linux-pm/include/acpi/acpi_drivers.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_drivers.h
+++ linux-pm/include/acpi/acpi_drivers.h
@@ -110,9 +110,9 @@ void pci_acpi_crs_quirks(void);
                                   Dock Station
   -------------------------------------------------------------------------- */
 struct acpi_dock_ops {
-	acpi_notify_handler fixup;
-	acpi_notify_handler handler;
-	acpi_notify_handler uevent;
+	void (*handler)(u32 event_type, void *data);
+	void (*fixup)(u32 event_type, void *data);
+	void (*uevent)(u32 event_type, void *data);
 };
 
 #ifdef CONFIG_ACPI_DOCK
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -63,7 +63,7 @@ static DEFINE_MUTEX(acpiphp_context_lock
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
-static void hotplug_event(acpi_handle handle, u32 type, void *data);
+static void hotplug_event(u32 type, void *data);
 static void free_bridge(struct kref *kref);
 
 static void acpiphp_context_handler(acpi_handle handle, void *context)
@@ -185,7 +185,7 @@ static void free_bridge(struct kref *kre
  * TBD - figure out a way to only call fixups for
  * systems that require them.
  */
-static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
+static void post_dock_fixups(u32 event, void *data)
 {
 	struct acpiphp_context *context = data;
 	struct pci_bus *bus = context->func.slot->bus;
@@ -788,11 +788,12 @@ void acpiphp_check_host_bridge(acpi_hand
 
 static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot);
 
-static void hotplug_event(acpi_handle handle, u32 type, void *data)
+static void hotplug_event(u32 type, void *data)
 {
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
+	acpi_handle handle = context->adev->handle;
 	struct acpiphp_bridge *bridge;
 
 	mutex_lock(&acpiphp_context_lock);
@@ -845,14 +846,14 @@ static void hotplug_event(acpi_handle ha
 static void hotplug_event_work(void *data, u32 type)
 {
 	struct acpiphp_context *context = data;
-	acpi_handle handle = context->adev->handle;
 
 	acpi_scan_lock_acquire();
 
-	hotplug_event(handle, type, context);
+	hotplug_event(type, context);
 
 	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
+	acpi_evaluate_hotplug_ost(context->adev->handle, type,
+				  ACPI_OST_SC_SUCCESS, NULL);
 	put_bridge(context->func.parent);
 }
 
Index: linux-pm/drivers/acpi/dock.c
===================================================================
--- linux-pm.orig/drivers/acpi/dock.c
+++ linux-pm/drivers/acpi/dock.c
@@ -185,7 +185,7 @@ static void dock_release_hotplug(struct
 static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
 			       enum dock_callback_type cb_type)
 {
-	acpi_notify_handler cb = NULL;
+	void (*cb)(u32, void *) = NULL;
 	bool run = false;
 
 	mutex_lock(&hotplug_lock);
@@ -213,7 +213,7 @@ static void dock_hotplug_event(struct do
 		return;
 
 	if (cb)
-		cb(dd->handle, event, dd->hp_context);
+		cb(event, dd->hp_context);
 
 	dock_release_hotplug(dd);
 }
Index: linux-pm/drivers/ata/libata-acpi.c
===================================================================
--- linux-pm.orig/drivers/ata/libata-acpi.c
+++ linux-pm/drivers/ata/libata-acpi.c
@@ -121,14 +121,14 @@ static void ata_acpi_handle_hotplug(stru
 		ata_port_wait_eh(ap);
 }
 
-static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_dev_notify_dock(u32 event, void *data)
 {
 	struct ata_device *dev = data;
 
 	ata_acpi_handle_hotplug(dev->link->ap, dev, event);
 }
 
-static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_ap_notify_dock(u32 event, void *data)
 {
 	struct ata_port *ap = data;
 
@@ -154,12 +154,12 @@ static void ata_acpi_uevent(struct ata_p
 	}
 }
 
-static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_ap_uevent(u32 event, void *data)
 {
 	ata_acpi_uevent(data, NULL, event);
 }
 
-static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
+static void ata_acpi_dev_uevent(u32 event, void *data)
 {
 	struct ata_device *dev = data;
 	ata_acpi_uevent(dev->link->ap, dev, event);


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

* [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug
  2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                       ` (4 preceding siblings ...)
  2014-01-29  0:02     ` [Update][PATCH 5/5][RFT] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
@ 2014-02-02  0:52     ` Rafael J. Wysocki
  2014-02-02  0:54       ` [PATCH v2 1/6] ACPI / hotplug: Fix theoretical race in acpi_hotplug_notify_cb() Rafael J. Wysocki
                         ` (6 more replies)
  5 siblings, 7 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:52 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

On Wednesday, January 29, 2014 12:57:06 AM Rafael J. Wysocki wrote:
> On Tuesday, January 28, 2014 11:10:30 PM Rafael J. Wysocki wrote:
> > Hi All,
> > 
> > It looks like there's time for more adventurous stuff. :-)
> > 
> > The following series is on top of the one I sent on Sunday:
> > 
> > https://lkml.org/lkml/2014/1/26/191
> > 
> > The final outcome of the patches below is that all ACPI hotplug notifications
> > for PCI devices and for core system things like CPU, memory, PCI roots etc.,
> > will be dispatched from acpi_bus_notify() and it is not necessary to install a
> > separate hotplug notify handler for each device any more.
> > 
> > [1/5] Attach ACPIPHP hotplug contexts to struct acpi_device objects.
> > [2/5] Introduce wrappers for installing and removing hotplug notify handlers
> >       (those wrappers go away later on, but they are useful for separating
> >        changes).
> > [3/5] Consolidate ACPI hotplug signaling for PCI and ACPI core.
> > [4/5] Simplify notify handle registration wrapper.
> > [5/5] Dispatch ACPI hotplug notifications for "core" devices and PCI from acpi_bus_notify().
> 
> Unfortunately, I realized that patches [3-5/5] were buggy.  The bugs were
> kind of subtle and might not be easy to reproduce, but they were bugs anyway. :-)
> 
> A respin of the whole series follows.

After the Mika's testing it turned out that they were more buggy than I had
though.  Oh well.

The following patchset is a reworked version of the previous one.  Functionality-wise
the final result should be very similar, but not exactly the same.

[1/6] Fix a theoretical race condition in acpi_hotplug_notify_cb().
[2/6] Move the hotplug context lock definition to the ACPI core (from ACPIPHP).
[3/6] Consolidate ACPI hotplug signaling for PCI and ACPI core (this is a combination
      of patches [1-3/5] from the previous series).
[4/6] Rework the handling of eject requests in the ACPI core.
[5/6] Simplify a routine for installing hotplug notify handlers.
[6/6] Dispatch ACPI hotplug notifications for "core" devices and PCI from acpi_bus_notify().

This is on top of https://lkml.org/lkml/2014/2/1/123 which in turn is on top of
the current mainline.

For the adventurous all this stuff is on the test-next branch of linux-pm.git.

Thanks!

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

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

* [PATCH v2 1/6] ACPI / hotplug: Fix theoretical race in acpi_hotplug_notify_cb()
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
@ 2014-02-02  0:54       ` Rafael J. Wysocki
  2014-02-02 17:01         ` Rafael J. Wysocki
  2014-02-02  0:55       ` [PATCH v2 2/6] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
                         ` (5 subsequent siblings)
  6 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:54 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

There is a slight possibility for the ACPI device object pointed to
by adev in acpi_hotplug_notify_cb() to become invalid between the
acpi_bus_get_device() that it comes from and the subsequent get_device().
Namely, if acpi_scan_drop_device() runs concurrently with respect to
acpi_hotplug_notify_cb() and acpi_device_del_list is not empty,
acpi_device_del_work_fn() may delete the device object in question
without waiting for the ACPI events workqueue to drain, which very
well may happen right after a successful execution of
acpi_bus_get_device() in acpi_hotplug_notify_cb().

To prevent that from happening, run acpi_bus_get_device() and the
subsequent get_device() in acpi_hotplug_notify_cb() under
acpi_device_del_lock, so that the deletion of the given device
object cannot be queued up by acpi_scan_drop_device() between the
two.

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

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -41,6 +41,8 @@ static DEFINE_MUTEX(acpi_scan_lock);
 static LIST_HEAD(acpi_scan_handlers_list);
 DEFINE_MUTEX(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
+static LIST_HEAD(acpi_device_del_list);
+static DEFINE_MUTEX(acpi_device_del_lock);
 
 struct acpi_device_bus_id{
 	char bus_id[15];
@@ -488,9 +490,6 @@ static void acpi_hotplug_notify_cb(acpi_
 	struct acpi_device *adev;
 	acpi_status status;
 
-	if (acpi_bus_get_device(handle, &adev))
-		goto err_out;
-
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
@@ -512,7 +511,13 @@ static void acpi_hotplug_notify_cb(acpi_
 		/* non-hotplug event; possibly handled by other handler */
 		return;
 	}
+	mutex_lock(&acpi_device_del_lock);
+	if (acpi_bus_get_device(handle, &adev)) {
+		mutex_unlock(&acpi_device_del_lock);
+		goto err_out;
+	}
 	get_device(&adev->dev);
+	mutex_unlock(&acpi_device_del_lock);
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
 		return;
@@ -1042,9 +1047,6 @@ static void acpi_device_del(struct acpi_
 	device_del(&device->dev);
 }
 
-static LIST_HEAD(acpi_device_del_list);
-static DEFINE_MUTEX(acpi_device_del_lock);
-
 static void acpi_device_del_work_fn(struct work_struct *work_not_used)
 {
 	for (;;) {


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

* [PATCH v2 2/6] ACPI / hotplug / PCI: Define hotplug context lock in the core
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  2014-02-02  0:54       ` [PATCH v2 1/6] ACPI / hotplug: Fix theoretical race in acpi_hotplug_notify_cb() Rafael J. Wysocki
@ 2014-02-02  0:55       ` Rafael J. Wysocki
  2014-02-02  0:56       ` [PATCH v2 3/6] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
                         ` (4 subsequent siblings)
  6 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:55 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Subsequent changes will require the ACPI core to acquire the lock
protecting the ACPIPHP hotplug contexts, so move the definition of
the lock to the core and change its name to be more generic.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |   11 +++++++++
 drivers/pci/hotplug/acpiphp_glue.c |   41 ++++++++++++++++++-------------------
 include/acpi/acpi_bus.h            |    2 +
 3 files changed, 33 insertions(+), 21 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -43,6 +43,7 @@ DEFINE_MUTEX(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
 static LIST_HEAD(acpi_device_del_list);
 static DEFINE_MUTEX(acpi_device_del_lock);
+static DEFINE_MUTEX(acpi_hp_context_lock);
 
 struct acpi_device_bus_id{
 	char bus_id[15];
@@ -62,6 +63,16 @@ void acpi_scan_lock_release(void)
 }
 EXPORT_SYMBOL_GPL(acpi_scan_lock_release);
 
+void acpi_lock_hp_context(void)
+{
+	mutex_lock(&acpi_hp_context_lock);
+}
+
+void acpi_unlock_hp_context(void)
+{
+	mutex_unlock(&acpi_hp_context_lock);
+}
+
 int acpi_scan_add_handler(struct acpi_scan_handler *handler)
 {
 	if (!handler || !handler->attach)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -58,7 +58,6 @@
 
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
-static DEFINE_MUTEX(acpiphp_context_lock);
 
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
@@ -75,7 +74,7 @@ static void acpiphp_context_handler(acpi
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
  * @adev: ACPI device object to create the context for.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
@@ -100,7 +99,7 @@ static struct acpiphp_context *acpiphp_i
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
  * @handle: ACPI object handle to get the context for.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
 {
@@ -122,7 +121,7 @@ static struct acpiphp_context *acpiphp_g
  *
  * The context object is removed if there are no more references to it.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static void acpiphp_put_context(struct acpiphp_context *context)
 {
@@ -151,7 +150,7 @@ static void free_bridge(struct kref *kre
 	struct acpiphp_slot *slot, *next;
 	struct acpiphp_func *func, *tmp;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 
 	bridge = container_of(kref, struct acpiphp_bridge, ref);
 
@@ -175,7 +174,7 @@ static void free_bridge(struct kref *kre
 	pci_dev_put(bridge->pci_dev);
 	kfree(bridge);
 
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 }
 
 /*
@@ -291,17 +290,17 @@ static acpi_status register_slot(acpi_ha
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_init_context(adev);
 	if (!context) {
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		acpi_handle_err(handle, "No hotplug context\n");
 		return AE_NOT_EXIST;
 	}
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -319,9 +318,9 @@ static acpi_status register_slot(acpi_ha
 
 	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 	if (!slot) {
-		mutex_lock(&acpiphp_context_lock);
+		acpi_lock_hp_context();
 		acpiphp_put_context(context);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		return AE_NO_MEMORY;
 	}
 
@@ -396,7 +395,7 @@ static struct acpiphp_bridge *acpiphp_ha
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_get_context(handle);
 	if (context) {
 		bridge = context->bridge;
@@ -405,7 +404,7 @@ static struct acpiphp_bridge *acpiphp_ha
 
 		acpiphp_put_context(context);
 	}
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 	return bridge;
 }
 
@@ -796,12 +795,12 @@ static void hotplug_event(u32 type, void
 	acpi_handle handle = context->adev->handle;
 	struct acpiphp_bridge *bridge;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	bridge = context->bridge;
 	if (bridge)
 		get_bridge(bridge);
 
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
 	pci_lock_rescan_remove();
 
@@ -902,16 +901,16 @@ static void handle_hotplug_event(acpi_ha
 		goto out;
 	}
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_get_context(handle);
 	if (context && !WARN_ON(context->adev->handle != handle)) {
 		get_bridge(context->func.parent);
 		acpiphp_put_context(context);
 		acpi_hotplug_execute(hotplug_event_work, context, type);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		return;
 	}
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
  out:
@@ -967,10 +966,10 @@ void acpiphp_enumerate_slots(struct pci_
 		 * parent is going to be handled by pciehp, in which case this
 		 * bridge is not interesting to us either.
 		 */
-		mutex_lock(&acpiphp_context_lock);
+		acpi_lock_hp_context();
 		context = acpiphp_get_context(handle);
 		if (!context) {
-			mutex_unlock(&acpiphp_context_lock);
+			acpi_unlock_hp_context();
 			put_device(&bus->dev);
 			pci_dev_put(bridge->pci_dev);
 			kfree(bridge);
@@ -980,7 +979,7 @@ void acpiphp_enumerate_slots(struct pci_
 		context->bridge = bridge;
 		/* Get a reference to the parent bridge. */
 		get_bridge(context->func.parent);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 	}
 
 	/* must be added to the list prior to calling register_slot */
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -402,6 +402,8 @@ static inline bool acpi_bus_can_wakeup(a
 
 void acpi_scan_lock_acquire(void);
 void acpi_scan_lock_release(void);
+void acpi_lock_hp_context(void);
+void acpi_unlock_hp_context(void);
 int acpi_scan_add_handler(struct acpi_scan_handler *handler);
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);


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

* [PATCH v2 3/6] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  2014-02-02  0:54       ` [PATCH v2 1/6] ACPI / hotplug: Fix theoretical race in acpi_hotplug_notify_cb() Rafael J. Wysocki
  2014-02-02  0:55       ` [PATCH v2 2/6] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
@ 2014-02-02  0:56       ` Rafael J. Wysocki
  2014-02-02  0:57       ` [PATCH v2 4/6] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
                         ` (3 subsequent siblings)
  6 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:56 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its
hotplug context objects directly to ACPI namespace nodes representing
hotplug devices.  However, after recent changes causing struct
acpi_device to be created for every namespace node representing a
device (regardless of its status), that is not necessary any more.
Moreover, it's vulnerable to a theoretical issue that the ACPI
handle passed in the context between handle_hotplug_event() and
hotplug_event_work() may become invalid in the meantime (as a
result of a concurrent table unload).

In principle, this issue might be addressed by adding a non-empty
release handler for ACPIPHP hotplug context objects analogous to
acpi_scan_drop_device(), but that would duplicate the code in that
function and in acpi_device_del_work_fn().  For this reason, it's
better to modify ACPIPHP to attach its device hotplug contexts to
struct device objects representing hotplug devices and make it
use acpi_hotplug_notify_cb() as its notify handler.  At the same
time, acpi_device_hotplug() can be modified to dispatch the new
.hp.event() callback pointing to acpiphp_hotplug_event() from ACPI
device objects associated with PCI devices and use the generic
ACPI device hotplug code for device objects with scan handlers
attached to them.

This allows the existing code duplication between ACPIPHP and the
ACPI core to be reduced too and makes further ACPI-based device
hotplug consolidation possible.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |  106 +++++++++++++++++++++-------
 drivers/pci/hotplug/acpiphp.h      |    9 +-
 drivers/pci/hotplug/acpiphp_glue.c |  136 +++++++------------------------------
 include/acpi/acpi_bus.h            |   22 +++++
 4 files changed, 136 insertions(+), 137 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -452,43 +452,61 @@ static int acpi_scan_bus_check(struct ac
 	return 0;
 }
 
+static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
+{
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		return acpi_scan_bus_check(adev);
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		return acpi_scan_device_check(adev);
+	case ACPI_NOTIFY_EJECT_REQUEST:
+	case ACPI_OST_EC_OSPM_EJECT:
+		return acpi_scan_hot_remove(adev);
+	}
+	return -EINVAL;
+}
+
 static void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
-	int error;
+	int error = -ENODEV;
 
 	lock_device_hotplug();
 	mutex_lock(&acpi_scan_lock);
 
 	/*
 	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it may have become invalid before
+	 * are holding acpi_scan_lock, but it might have become invalid before
 	 * that lock was acquired.
 	 */
 	if (adev->handle == INVALID_ACPI_HANDLE)
-		goto out;
+		goto err_out;
 
-	switch (src) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		error = acpi_scan_bus_check(adev);
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		error = acpi_scan_device_check(adev);
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-	case ACPI_OST_EC_OSPM_EJECT:
-		error = acpi_scan_hot_remove(adev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
+	if (adev->handler) {
+		error = acpi_generic_hotplug_event(adev, src);
+	} else {
+		int (*event)(struct acpi_device *, u32);
+
+		acpi_lock_hp_context();
+		event = adev->hp ? adev->hp->event : NULL;
+		acpi_unlock_hp_context();
+		/*
+		 * There may be additional notify handlers for device objects
+		 * without the .event() callback, so ignore them here.
+		 */
+		if (event)
+			error = event(adev, src);
+		else
+			goto out;
 	}
 	if (!error)
 		ost_code = ACPI_OST_SC_SUCCESS;
 
- out:
+ err_out:
 	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
+
+ out:
 	put_device(&adev->dev);
 	mutex_unlock(&acpi_scan_lock);
 	unlock_device_hotplug();
@@ -496,8 +514,8 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_scan_handler *handler = data;
+	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
 
@@ -505,27 +523,50 @@ static void acpi_hotplug_notify_cb(acpi_
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (!handler->hotplug.enabled) {
+		if (handler && !handler->hotplug.enabled) {
 			acpi_handle_err(handle, "Eject disabled\n");
 			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto err_out;
+			goto out;
 		}
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
-	default:
-		/* non-hotplug event; possibly handled by other handler */
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
 		return;
+
+	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_POWER_FAULT:
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
+		goto out;
+
+	default:
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto out;
 	}
+
+	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	mutex_lock(&acpi_device_del_lock);
 	if (acpi_bus_get_device(handle, &adev)) {
 		mutex_unlock(&acpi_device_del_lock);
-		goto err_out;
+		goto out;
 	}
 	get_device(&adev->dev);
 	mutex_unlock(&acpi_device_del_lock);
@@ -535,10 +576,22 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	put_device(&adev->dev);
 
- err_out:
+ out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+{
+	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				    acpi_hotplug_notify_cb, data);
+}
+
+void acpi_remove_hotplug_notify_handler(acpi_handle handle)
+{
+	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				   acpi_hotplug_notify_cb);
+}
+
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1971,8 +2024,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					acpi_hotplug_notify_cb, handler);
+			acpi_install_hotplug_notify_handler(handle, handler);
 			break;
 		}
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -116,12 +116,17 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
+	struct acpi_hotplug_context hp;
 	struct acpiphp_func func;
-	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
 
+static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
+{
+	return container_of(hp, struct acpiphp_context, hp);
+}
+
 static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
 {
 	return container_of(func, struct acpiphp_context, func);
@@ -129,7 +134,7 @@ static inline struct acpiphp_context *fu
 
 static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
 {
-	return func_to_context(func)->adev;
+	return func_to_context(func)->hp.self;
 }
 
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -59,17 +59,12 @@
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
 static void hotplug_event(u32 type, void *data);
 static void free_bridge(struct kref *kref);
 
-static void acpiphp_context_handler(acpi_handle handle, void *context)
-{
-	/* Intentionally empty. */
-}
-
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
  * @adev: ACPI device object to create the context for.
@@ -79,39 +74,27 @@ static void acpiphp_context_handler(acpi
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
-	acpi_status status;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return NULL;
 
-	context->adev = adev;
 	context->refcount = 1;
-	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
-	if (ACPI_FAILURE(status)) {
-		kfree(context);
-		return NULL;
-	}
+	acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_event);
 	return context;
 }
 
 /**
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
- * @handle: ACPI object handle to get the context for.
+ * @adev: ACPI device object to get the context for.
  *
  * Call under acpi_hp_context_lock.
  */
-static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = NULL;
-	acpi_status status;
-	void *data;
+	struct acpiphp_context *context = to_acpiphp_context(adev->hp);
 
-	status = acpi_get_data(handle, acpiphp_context_handler, &data);
-	if (ACPI_SUCCESS(status)) {
-		context = data;
-		context->refcount++;
-	}
+	context->refcount++;
 	return context;
 }
 
@@ -129,7 +112,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
+	context->hp.self->hp = NULL;
 	kfree(context);
 }
 
@@ -378,14 +361,8 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-						     handle_hotplug_event,
-						     context);
-		if (ACPI_FAILURE(status))
-			acpi_handle_err(handle,
-					"failed to install notify handler\n");
-	}
+	if (!(newfunc->flags & FUNC_HAS_DCK))
+		acpi_install_hotplug_notify_handler(handle, NULL);
 
 	return AE_OK;
 }
@@ -394,9 +371,13 @@ static struct acpiphp_bridge *acpiphp_ha
 {
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
+	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return NULL;
 
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
+	context = acpiphp_get_context(adev);
 	if (context) {
 		bridge = context->bridge;
 		if (bridge)
@@ -412,7 +393,6 @@ static void cleanup_bridge(struct acpiph
 {
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
-	acpi_status status;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
@@ -421,13 +401,8 @@ static void cleanup_bridge(struct acpiph
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
 
-			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(handle,
-							ACPI_SYSTEM_NOTIFY,
-							handle_hotplug_event);
-				if (ACPI_FAILURE(status))
-					pr_err("failed to remove notify handler\n");
-			}
+			if (!(func->flags & FUNC_HAS_DCK))
+				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
@@ -792,7 +767,7 @@ static void hotplug_event(u32 type, void
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
-	acpi_handle handle = context->adev->handle;
+	acpi_handle handle = context->hp.self->handle;
 	struct acpiphp_bridge *bridge;
 
 	acpi_lock_hp_context();
@@ -842,79 +817,24 @@ static void hotplug_event(u32 type, void
 		put_bridge(bridge);
 }
 
-static void hotplug_event_work(void *data, u32 type)
-{
-	struct acpiphp_context *context = data;
-
-	acpi_scan_lock_acquire();
-
-	hotplug_event(type, context);
-
-	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(context->adev->handle, type,
-				  ACPI_OST_SC_SUCCESS, NULL);
-	put_bridge(context->func.parent);
-}
-
-/**
- * handle_hotplug_event - handle ACPI hotplug event
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @data: pointer to acpiphp_context structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type)
 {
 	struct acpiphp_context *context;
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
-		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
 
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
-	if (context && !WARN_ON(context->adev->handle != handle)) {
-		get_bridge(context->func.parent);
-		acpiphp_put_context(context);
-		acpi_hotplug_execute(hotplug_event_work, context, type);
+	context = acpiphp_get_context(adev);
+	if (!context) {
 		acpi_unlock_hp_context();
-		return;
+		return -ENODATA;
 	}
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
 	acpi_unlock_hp_context();
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
+	hotplug_event(type, context);
+
+	put_bridge(context->func.parent);
+	return 0;
 }
 
 /**
@@ -967,7 +887,7 @@ void acpiphp_enumerate_slots(struct pci_
 		 * bridge is not interesting to us either.
 		 */
 		acpi_lock_hp_context();
-		context = acpiphp_get_context(handle);
+		context = acpiphp_get_context(adev);
 		if (!context) {
 			acpi_unlock_hp_context();
 			put_device(&bus->dev);
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -137,6 +137,16 @@ struct acpi_scan_handler {
 };
 
 /*
+ * ACPI Hotplug Context
+ * --------------------
+ */
+
+struct acpi_hotplug_context {
+	struct acpi_device *self;
+	int (*event)(struct acpi_device *, u32);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -329,6 +339,7 @@ struct acpi_device {
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
 	struct acpi_scan_handler *handler;
+	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
@@ -351,6 +362,15 @@ static inline void acpi_set_device_statu
 	*((u32 *)&adev->status) = sta;
 }
 
+static inline void acpi_set_hp_context(struct acpi_device *adev,
+				       struct acpi_hotplug_context *hp,
+				       int (*event)(struct acpi_device *, u32))
+{
+	hp->self = adev;
+	hp->event = event;
+	adev->hp = hp;
+}
+
 /* acpi_device.dev.bus == &acpi_bus_type */
 extern struct bus_type acpi_bus_type;
 
@@ -423,6 +443,8 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver


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

* [PATCH v2 4/6] ACPI / hotplug / PCI: Rework the handling of eject requests
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                         ` (2 preceding siblings ...)
  2014-02-02  0:56       ` [PATCH v2 3/6] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
@ 2014-02-02  0:57       ` Rafael J. Wysocki
  2014-02-02  0:58       ` [PATCH v2 5/6] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
                         ` (2 subsequent siblings)
  6 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:57 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

To avoid the need to install a hotplug notify handler for each ACPI
namespace node representing a device and having a matching scan
handler, move the check whether or not the ejection of the given
device is enabled through its scan handler from acpi_hotplug_notify_cb()
to acpi_generic_hotplug_event().  Also, move the execution of
ACPI_OST_SC_EJECT_IN_PROGRESS _OST to acpi_generic_hotplug_event(),
because in acpi_hotplug_notify_cb() or in acpi_eject_store() we really
don't know whether or not the eject is going to be in progress (for
example, acpi_hotplug_execute() may still fail without queuing up the
work item).

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

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -461,6 +461,12 @@ static int acpi_generic_hotplug_event(st
 		return acpi_scan_device_check(adev);
 	case ACPI_NOTIFY_EJECT_REQUEST:
 	case ACPI_OST_EC_OSPM_EJECT:
+		if (adev->handler && !adev->handler->hotplug.enabled) {
+			dev_info(&adev->dev, "Eject disabled\n");
+			return -EPERM;
+		}
+		acpi_evaluate_hotplug_ost(adev->handle, ACPI_NOTIFY_EJECT_REQUEST,
+					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		return acpi_scan_hot_remove(adev);
 	}
 	return -EINVAL;
@@ -485,6 +491,10 @@ static void acpi_device_hotplug(void *da
 
 	if (adev->handler) {
 		error = acpi_generic_hotplug_event(adev, src);
+		if (error == -EPERM) {
+			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+			goto err_out;
+		}
 	} else {
 		int (*event)(struct acpi_device *, u32);
 
@@ -514,7 +524,6 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_scan_handler *handler = data;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
@@ -530,13 +539,6 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (handler && !handler->hotplug.enabled) {
-			acpi_handle_err(handle, "Eject disabled\n");
-			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto out;
-		}
-		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
@@ -637,8 +639,6 @@ acpi_eject_store(struct device *d, struc
 	if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
 		return -ENODEV;
 
-	acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
-				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 	get_device(&acpi_device->dev);
 	status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device,
 				      ACPI_OST_EC_OSPM_EJECT);


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

* [PATCH v2 5/6] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                         ` (3 preceding siblings ...)
  2014-02-02  0:57       ` [PATCH v2 4/6] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
@ 2014-02-02  0:58       ` Rafael J. Wysocki
  2014-02-02  0:58       ` [PATCH v2 6/6] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  6 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:58 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Since acpi_hotplug_notify_cb() does not use its data argument any
more, the second argument of acpi_install_hotplug_notify_handler()
can be dropped, so do that and update its callers accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |    6 +++---
 drivers/pci/hotplug/acpiphp_glue.c |    2 +-
 include/acpi/acpi_bus.h            |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -582,10 +582,10 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+void acpi_install_hotplug_notify_handler(acpi_handle handle)
 {
 	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, data);
+				    acpi_hotplug_notify_cb, NULL);
 }
 
 void acpi_remove_hotplug_notify_handler(acpi_handle handle)
@@ -2024,7 +2024,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_hotplug_notify_handler(handle, handler);
+			acpi_install_hotplug_notify_handler(handle);
 			break;
 		}
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -362,7 +362,7 @@ static acpi_status register_slot(acpi_ha
 
 	/* install notify handler */
 	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle, NULL);
+		acpi_install_hotplug_notify_handler(handle);
 
 	return AE_OK;
 }
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -443,7 +443,7 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_install_hotplug_notify_handler(acpi_handle handle);
 void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**


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

* [PATCH v2 6/6] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify()
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                         ` (4 preceding siblings ...)
  2014-02-02  0:58       ` [PATCH v2 5/6] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-02-02  0:58       ` Rafael J. Wysocki
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  6 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02  0:58 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg

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

Since acpi_bus_notify() is executed on all notifications for all
devices anyway, rename acpi_hotplug_notify_cb() to acpi_system_notify()
and call it directly from acpi_bus_notify() instead of installing
notify handlers pointing to it for all hotplug devices.

This change reduces both the size and complexity of ACPI-based device
hotplug code.  Moreover, since acpi_system_notify() only does
significant things for devices that either have an ACPI scan handler,
or have a hotplug context with .eject() defined, and those devices
had notify handlers pointing to acpi_hotplug_notify_cb() installed
before anyway, this modification shouldn't change functionality.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/bus.c                 |   42 -------------------------------
 drivers/acpi/internal.h            |    1 
 drivers/acpi/scan.c                |   49 ++++---------------------------------
 drivers/pci/hotplug/acpiphp.h      |    1 
 drivers/pci/hotplug/acpiphp_glue.c |   16 +++++-------
 include/acpi/acpi_bus.h            |    2 -
 6 files changed, 15 insertions(+), 96 deletions(-)

Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -346,47 +346,7 @@ static void acpi_bus_notify(acpi_handle
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
 			  type, handle));
 
-	switch (type) {
-
-	case ACPI_NOTIFY_BUS_CHECK:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
-		/* TBD: Exactly what does 'light' mean? */
-		break;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		/* TBD */
-		break;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		/* TBD */
-		break;
-
-	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received unknown/unsupported notification [%08x]\n",
-				  type));
-		break;
-	}
-
+	acpi_system_notify(handle, type);
 	acpi_bus_get_device(handle, &device);
 	if (device) {
 		driver = device->driver;
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -74,6 +74,7 @@ static inline void acpi_lpss_init(void)
 
 bool acpi_queue_hotplug_work(struct work_struct *work);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
+void acpi_system_notify(acpi_handle handle, u32 type);
 
 /* --------------------------------------------------------------------------
                      Device Node Initialization / Removal
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -522,7 +522,7 @@ static void acpi_device_hotplug(void *da
 	unlock_device_hotplug();
 }
 
-static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
+void acpi_system_notify(acpi_handle handle, u32 type)
 {
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
@@ -537,6 +537,11 @@ static void acpi_hotplug_notify_cb(acpi_
 		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
 
+	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
+		/* TBD: Exactly what does 'light' mean? */
+		break;
+
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
 		break;
@@ -582,18 +587,6 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, NULL);
-}
-
-void acpi_remove_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				   acpi_hotplug_notify_cb);
-}
-
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -2005,34 +1998,6 @@ void acpi_scan_hotplug_enabled(struct ac
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
-{
-	struct acpi_device_pnp pnp = {};
-	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
-
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
-
-	if (!pnp.type.hardware_id)
-		goto out;
-
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
-		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (handler) {
-			acpi_install_hotplug_notify_handler(handle);
-			break;
-		}
-	}
-
-out:
-	acpi_free_pnp_ids(&pnp);
-}
-
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 				      void *not_used, void **return_value)
 {
@@ -2054,8 +2019,6 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -283,7 +283,6 @@ static acpi_status register_slot(acpi_ha
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	acpi_unlock_hp_context();
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -291,8 +290,14 @@ static acpi_status register_slot(acpi_ha
 	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
+	/*
+	 * Dock stations' notify handler should be used for dock devices instead
+	 * of the common one, so clear hp.event in their contexts.
+	 */
 	if (acpi_has_method(handle, "_DCK"))
-		newfunc->flags |= FUNC_HAS_DCK;
+		context->hp.event = NULL;
+
+	acpi_unlock_hp_context();
 
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
@@ -360,10 +365,6 @@ static acpi_status register_slot(acpi_ha
 			pr_debug("failed to register dock device\n");
 	}
 
-	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle);
-
 	return AE_OK;
 }
 
@@ -400,9 +401,6 @@ static void cleanup_bridge(struct acpiph
 
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
-
-			if (!(func->flags & FUNC_HAS_DCK))
-				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -443,8 +443,6 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle);
-void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -167,7 +167,6 @@ struct acpiphp_attention_info
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 


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

* Re: [PATCH v2 1/6] ACPI / hotplug: Fix theoretical race in acpi_hotplug_notify_cb()
  2014-02-02  0:54       ` [PATCH v2 1/6] ACPI / hotplug: Fix theoretical race in acpi_hotplug_notify_cb() Rafael J. Wysocki
@ 2014-02-02 17:01         ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:01 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

On Sunday, February 02, 2014 01:54:02 AM Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> There is a slight possibility for the ACPI device object pointed to
> by adev in acpi_hotplug_notify_cb() to become invalid between the
> acpi_bus_get_device() that it comes from and the subsequent get_device().
> Namely, if acpi_scan_drop_device() runs concurrently with respect to
> acpi_hotplug_notify_cb() and acpi_device_del_list is not empty,
> acpi_device_del_work_fn() may delete the device object in question
> without waiting for the ACPI events workqueue to drain, which very
> well may happen right after a successful execution of
> acpi_bus_get_device() in acpi_hotplug_notify_cb().
> 
> To prevent that from happening, run acpi_bus_get_device() and the
> subsequent get_device() in acpi_hotplug_notify_cb() under
> acpi_device_del_lock, so that the deletion of the given device
> object cannot be queued up by acpi_scan_drop_device() between the
> two.
> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/scan.c |   14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
> 
> Index: linux-pm/drivers/acpi/scan.c
> ===================================================================
> --- linux-pm.orig/drivers/acpi/scan.c
> +++ linux-pm/drivers/acpi/scan.c
> @@ -41,6 +41,8 @@ static DEFINE_MUTEX(acpi_scan_lock);
>  static LIST_HEAD(acpi_scan_handlers_list);
>  DEFINE_MUTEX(acpi_device_lock);
>  LIST_HEAD(acpi_wakeup_device_list);
> +static LIST_HEAD(acpi_device_del_list);
> +static DEFINE_MUTEX(acpi_device_del_lock);
>  
>  struct acpi_device_bus_id{
>  	char bus_id[15];
> @@ -488,9 +490,6 @@ static void acpi_hotplug_notify_cb(acpi_
>  	struct acpi_device *adev;
>  	acpi_status status;
>  
> -	if (acpi_bus_get_device(handle, &adev))
> -		goto err_out;
> -
>  	switch (type) {
>  	case ACPI_NOTIFY_BUS_CHECK:
>  		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
> @@ -512,7 +511,13 @@ static void acpi_hotplug_notify_cb(acpi_
>  		/* non-hotplug event; possibly handled by other handler */
>  		return;
>  	}
> +	mutex_lock(&acpi_device_del_lock);
> +	if (acpi_bus_get_device(handle, &adev)) {
> +		mutex_unlock(&acpi_device_del_lock);
> +		goto err_out;
> +	}
>  	get_device(&adev->dev);
> +	mutex_unlock(&acpi_device_del_lock);
>  	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
>  	if (ACPI_SUCCESS(status))
>  		return;

Well, that would have been good if it hand't been broken. :-(

acpi_scan_drop_device() which acquires acpi_device_del_lock is called under
the ACPICA's namespace mutex and acpi_bus_get_device() above acquires that
mutex, so this leads to a classical ABBA deadlock scenario.  Bummer.

And I haven't been able to convince myself that what we're doing in
acpi_hotplug_notify_cb() is actually safe without any locking.  Not to
mention acpi_bus_notify() for that matter.  Moreover, the *only* safe
way to do that I'm seeing at the moment is to call the get_device()
under the ACPICA's namespace mutex, before it is released in
acpi_get_data().

Of course, ACPICA will need to be modified slightly for that to be
possible (sorry, Bob), but at least that *should* work, so I have a
new version of this patchset doing just that.  I'll send it out
shortly.

Thanks!

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

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

* [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug
  2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                         ` (5 preceding siblings ...)
  2014-02-02  0:58       ` [PATCH v2 6/6] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
@ 2014-02-02 17:11       ` Rafael J. Wysocki
  2014-02-02 17:12         ` [PATCH v3 1/7] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
                           ` (7 more replies)
  6 siblings, 8 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:11 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

On Sunday, February 02, 2014 01:52:26 AM Rafael J. Wysocki wrote:
> On Wednesday, January 29, 2014 12:57:06 AM Rafael J. Wysocki wrote:
> > On Tuesday, January 28, 2014 11:10:30 PM Rafael J. Wysocki wrote:
> > > Hi All,
> > > 
> > > It looks like there's time for more adventurous stuff. :-)
> > > 
> > > The following series is on top of the one I sent on Sunday:
> > > 
> > > https://lkml.org/lkml/2014/1/26/191
> > > 
> > > The final outcome of the patches below is that all ACPI hotplug notifications
> > > for PCI devices and for core system things like CPU, memory, PCI roots etc.,
> > > will be dispatched from acpi_bus_notify() and it is not necessary to install a
> > > separate hotplug notify handler for each device any more.
> > > 
> > > [1/5] Attach ACPIPHP hotplug contexts to struct acpi_device objects.
> > > [2/5] Introduce wrappers for installing and removing hotplug notify handlers
> > >       (those wrappers go away later on, but they are useful for separating
> > >        changes).
> > > [3/5] Consolidate ACPI hotplug signaling for PCI and ACPI core.
> > > [4/5] Simplify notify handle registration wrapper.
> > > [5/5] Dispatch ACPI hotplug notifications for "core" devices and PCI from acpi_bus_notify().
> > 
> > Unfortunately, I realized that patches [3-5/5] were buggy.  The bugs were
> > kind of subtle and might not be easy to reproduce, but they were bugs anyway. :-)
> > 
> > A respin of the whole series follows.
> 
> After the Mika's testing it turned out that they were more buggy than I had
> though.  Oh well.
> 
> The following patchset is a reworked version of the previous one.  Functionality-wise
> the final result should be very similar, but not exactly the same.
> 
> [1/6] Fix a theoretical race condition in acpi_hotplug_notify_cb().
> [2/6] Move the hotplug context lock definition to the ACPI core (from ACPIPHP).
> [3/6] Consolidate ACPI hotplug signaling for PCI and ACPI core (this is a combination
>       of patches [1-3/5] from the previous series).
> [4/6] Rework the handling of eject requests in the ACPI core.
> [5/6] Simplify a routine for installing hotplug notify handlers.
> [6/6] Dispatch ACPI hotplug notifications for "core" devices and PCI from acpi_bus_notify().
> 
> This is on top of https://lkml.org/lkml/2014/2/1/123 which in turn is on top of
> the current mainline.
> 
> For the adventurous all this stuff is on the test-next branch of linux-pm.git.

As stated in the message at http://marc.info/?l=linux-acpi&m=139135963030012&w=4 ,
patch [1/6] was actaully wrong and the whole patchset had to be reworked for that
reason.  What follows is an entirely new version:

[1/7] Add a new function to ACPICA allowing a callback to be executed under the
      namespace mutex after calling acpi_ns_get_attached_data().

[2/7] Use the new ACPICA's function to fix a couple of potential races related
      to ACPI notifies.

[3/7] Same as [2/6] above.
[4/7] Same as [3/6] above, rebased.
[5/7] Same as [4/6] above.
[6/7] Same as [5/6] above.
[7/7] Dispatch ACPI hotplug notifications for "core" devices and PCI from
      acpi_bus_notify().  This actually is different from [6/6] above, although
      it serves the same purpose.

Thanks!

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

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

* [PATCH v3 1/7] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data()
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
@ 2014-02-02 17:12         ` Rafael J. Wysocki
  2014-02-02 17:15         ` [PATCH v3 2/7] ACPI / hotplug: Fix potential races in notify handlers Rafael J. Wysocki
                           ` (6 subsequent siblings)
  7 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:12 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

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

Introduce a new function, acpi_get_data_full(), working in analogy
with acpi_get_data() except that it can execute a callback provided
as its 4th argument right after acpi_ns_get_attached_data() has
returned a success.

That will allow Linux to reference count the object pointed to by
*data before the namespace mutex is released so as to ensure that it
will not be freed going forward until the reference to it acquired
by acpi_get_data_full() is dropped.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/acpica/nsxfeval.c |   33 ++++++++++++++++++++++++++++++---
 include/acpi/acpixf.h          |    4 ++++
 2 files changed, 34 insertions(+), 3 deletions(-)

Index: linux-pm/drivers/acpi/acpica/nsxfeval.c
===================================================================
--- linux-pm.orig/drivers/acpi/acpica/nsxfeval.c
+++ linux-pm/drivers/acpi/acpica/nsxfeval.c
@@ -923,19 +923,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_get_data
+ * FUNCTION:    acpi_get_data_full
  *
  * PARAMETERS:  obj_handle          - Namespace node
  *              handler             - Handler used in call to attach_data
  *              data                - Where the data is returned
+ *              callback            - function to execute before returning
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
+ * DESCRIPTION: Retrieve data that was previously attached to a namespace node
+ *              and execute a callback before returning.
  *
  ******************************************************************************/
 acpi_status
-acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
+acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler,
+		   void **data, void (*callback)(void *))
 {
 	struct acpi_namespace_node *node;
 	acpi_status status;
@@ -960,10 +963,34 @@ acpi_get_data(acpi_handle obj_handle, ac
 	}
 
 	status = acpi_ns_get_attached_data(node, handler, data);
+	if (ACPI_SUCCESS(status) && callback) {
+		callback(*data);
+	}
 
 unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return (status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_get_data_full)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_get_data
+ *
+ * PARAMETERS:  obj_handle          - Namespace node
+ *              handler             - Handler used in call to attach_data
+ *              data                - Where the data is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
+{
+	return acpi_get_data_full(obj_handle, handler, data, NULL);
+}
+
 ACPI_EXPORT_SYMBOL(acpi_get_data)
Index: linux-pm/include/acpi/acpixf.h
===================================================================
--- linux-pm.orig/include/acpi/acpixf.h
+++ linux-pm/include/acpi/acpixf.h
@@ -230,6 +230,10 @@ acpi_attach_data(acpi_handle object, acp
 acpi_status acpi_detach_data(acpi_handle object, acpi_object_handler handler);
 
 acpi_status
+acpi_get_data_full(acpi_handle object, acpi_object_handler handler, void **data,
+		   void (*callback)(void *));
+
+acpi_status
 acpi_get_data(acpi_handle object, acpi_object_handler handler, void **data);
 
 acpi_status


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

* [PATCH v3 2/7] ACPI / hotplug: Fix potential races in notify handlers
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  2014-02-02 17:12         ` [PATCH v3 1/7] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
@ 2014-02-02 17:15         ` Rafael J. Wysocki
  2014-02-02 17:16         ` [PATCH v3 3/7] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
                           ` (5 subsequent siblings)
  7 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:15 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

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

There is a slight possibility for the ACPI device object pointed to
by adev in acpi_hotplug_notify_cb() to become invalid between the
acpi_bus_get_device() that it comes from and the subsequent dereference
of that pointer under get_device().  Namely, if acpi_scan_drop_device()
runs in parallel with acpi_hotplug_notify_cb(), acpi_device_del_work_fn()
queued up by it may delete the device object in question right after
a successful execution of acpi_bus_get_device() in acpi_bus_notify().

An analogous problem is present in acpi_bus_notify() where the device
pointer coming from acpi_bus_get_device() may become invalid before
it subsequent dereference in the "if" block.

To prevent that from happening, introduce a new function,
acpi_bus_get_acpi_device(), working analogously to acpi_bus_get_device()
except that it will grab a reference to the ACPI device object returned
by it and it will do that under the ACPICA's namespace mutex.  Then,
make both acpi_hotplug_notify_cb() and acpi_bus_notify() use
acpi_bus_get_acpi_device() instead of acpi_bus_get_device() so as to
ensure that the pointers used by them will not become stale at one
point.

In addition to that, introduce acpi_bus_put_acpi_device() as a wrapper
around put_device() to be used along with acpi_bus_get_acpi_device()
and make the (new) users of the latter use acpi_bus_put_acpi_device()
too.

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

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -476,7 +476,7 @@ static void acpi_device_hotplug(void *da
 
  out:
 	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
-	put_device(&adev->dev);
+	acpi_bus_put_acpi_device(adev);
 	mutex_unlock(&acpi_scan_lock);
 	unlock_device_hotplug();
 }
@@ -488,9 +488,6 @@ static void acpi_hotplug_notify_cb(acpi_
 	struct acpi_device *adev;
 	acpi_status status;
 
-	if (acpi_bus_get_device(handle, &adev))
-		goto err_out;
-
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
@@ -512,12 +509,14 @@ static void acpi_hotplug_notify_cb(acpi_
 		/* non-hotplug event; possibly handled by other handler */
 		return;
 	}
-	get_device(&adev->dev);
+	if (acpi_bus_get_acpi_device(handle, &adev))
+		goto err_out;
+
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
 		return;
 
-	put_device(&adev->dev);
+	acpi_bus_put_acpi_device(adev);
 
  err_out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
@@ -1112,14 +1111,16 @@ static void acpi_scan_drop_device(acpi_h
 	mutex_unlock(&acpi_device_del_lock);
 }
 
-int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device,
+				void (*callback)(void *))
 {
 	acpi_status status;
 
 	if (!device)
 		return -EINVAL;
 
-	status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device);
+	status = acpi_get_data_full(handle, acpi_scan_drop_device,
+				    (void **)device, callback);
 	if (ACPI_FAILURE(status) || !*device) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
 				  handle));
@@ -1127,8 +1128,29 @@ int acpi_bus_get_device(acpi_handle hand
 	}
 	return 0;
 }
+
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+{
+	return acpi_get_device_data(handle, device, NULL);
+}
 EXPORT_SYMBOL(acpi_bus_get_device);
 
+static void get_acpi_device(void *dev)
+{
+	if (dev)
+		get_device(&((struct acpi_device *)dev)->dev);
+}
+
+int acpi_bus_get_acpi_device(acpi_handle handle, struct acpi_device **adev_p)
+{
+	return acpi_get_device_data(handle, adev_p, get_acpi_device);
+}
+
+void acpi_bus_put_acpi_device(struct acpi_device *adev)
+{
+	put_device(&adev->dev);
+}
+
 int acpi_device_add(struct acpi_device *device,
 		    void (*release)(struct device *))
 {
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -81,6 +81,8 @@ bool acpi_scan_is_offline(struct acpi_de
 #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
 			  ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
 
+int acpi_bus_get_acpi_device(acpi_handle handle, struct acpi_device **adev_p);
+void acpi_bus_put_acpi_device(struct acpi_device *adev);
 int acpi_device_add(struct acpi_device *device,
 		    void (*release)(struct device *));
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -387,12 +387,14 @@ static void acpi_bus_notify(acpi_handle
 		break;
 	}
 
-	acpi_bus_get_device(handle, &device);
+	acpi_bus_get_acpi_device(handle, &device);
 	if (device) {
 		driver = device->driver;
 		if (driver && driver->ops.notify &&
 		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
 			driver->ops.notify(device, type);
+
+		acpi_bus_put_acpi_device(device);
 	}
 }
 


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

* [PATCH v3 3/7] ACPI / hotplug / PCI: Define hotplug context lock in the core
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
  2014-02-02 17:12         ` [PATCH v3 1/7] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
  2014-02-02 17:15         ` [PATCH v3 2/7] ACPI / hotplug: Fix potential races in notify handlers Rafael J. Wysocki
@ 2014-02-02 17:16         ` Rafael J. Wysocki
  2014-02-02 17:17         ` [PATCH v3 4/7] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
                           ` (4 subsequent siblings)
  7 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:16 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

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

Subsequent changes will require the ACPI core to acquire the lock
protecting the ACPIPHP hotplug contexts, so move the definition of
the lock to the core and change its name to be more generic.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |   11 +++++++++
 drivers/pci/hotplug/acpiphp_glue.c |   41 ++++++++++++++++++-------------------
 include/acpi/acpi_bus.h            |    2 +
 3 files changed, 33 insertions(+), 21 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -41,6 +41,7 @@ static DEFINE_MUTEX(acpi_scan_lock);
 static LIST_HEAD(acpi_scan_handlers_list);
 DEFINE_MUTEX(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
+static DEFINE_MUTEX(acpi_hp_context_lock);
 
 struct acpi_device_bus_id{
 	char bus_id[15];
@@ -60,6 +61,16 @@ void acpi_scan_lock_release(void)
 }
 EXPORT_SYMBOL_GPL(acpi_scan_lock_release);
 
+void acpi_lock_hp_context(void)
+{
+	mutex_lock(&acpi_hp_context_lock);
+}
+
+void acpi_unlock_hp_context(void)
+{
+	mutex_unlock(&acpi_hp_context_lock);
+}
+
 int acpi_scan_add_handler(struct acpi_scan_handler *handler)
 {
 	if (!handler || !handler->attach)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -58,7 +58,6 @@
 
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
-static DEFINE_MUTEX(acpiphp_context_lock);
 
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
@@ -75,7 +74,7 @@ static void acpiphp_context_handler(acpi
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
  * @adev: ACPI device object to create the context for.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
@@ -100,7 +99,7 @@ static struct acpiphp_context *acpiphp_i
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
  * @handle: ACPI object handle to get the context for.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
 {
@@ -122,7 +121,7 @@ static struct acpiphp_context *acpiphp_g
  *
  * The context object is removed if there are no more references to it.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static void acpiphp_put_context(struct acpiphp_context *context)
 {
@@ -151,7 +150,7 @@ static void free_bridge(struct kref *kre
 	struct acpiphp_slot *slot, *next;
 	struct acpiphp_func *func, *tmp;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 
 	bridge = container_of(kref, struct acpiphp_bridge, ref);
 
@@ -175,7 +174,7 @@ static void free_bridge(struct kref *kre
 	pci_dev_put(bridge->pci_dev);
 	kfree(bridge);
 
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 }
 
 /*
@@ -291,17 +290,17 @@ static acpi_status register_slot(acpi_ha
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_init_context(adev);
 	if (!context) {
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		acpi_handle_err(handle, "No hotplug context\n");
 		return AE_NOT_EXIST;
 	}
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -319,9 +318,9 @@ static acpi_status register_slot(acpi_ha
 
 	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 	if (!slot) {
-		mutex_lock(&acpiphp_context_lock);
+		acpi_lock_hp_context();
 		acpiphp_put_context(context);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		return AE_NO_MEMORY;
 	}
 
@@ -396,7 +395,7 @@ static struct acpiphp_bridge *acpiphp_ha
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_get_context(handle);
 	if (context) {
 		bridge = context->bridge;
@@ -405,7 +404,7 @@ static struct acpiphp_bridge *acpiphp_ha
 
 		acpiphp_put_context(context);
 	}
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 	return bridge;
 }
 
@@ -796,12 +795,12 @@ static void hotplug_event(u32 type, void
 	acpi_handle handle = context->adev->handle;
 	struct acpiphp_bridge *bridge;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	bridge = context->bridge;
 	if (bridge)
 		get_bridge(bridge);
 
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
 	pci_lock_rescan_remove();
 
@@ -902,16 +901,16 @@ static void handle_hotplug_event(acpi_ha
 		goto out;
 	}
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_get_context(handle);
 	if (context && !WARN_ON(context->adev->handle != handle)) {
 		get_bridge(context->func.parent);
 		acpiphp_put_context(context);
 		acpi_hotplug_execute(hotplug_event_work, context, type);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		return;
 	}
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
  out:
@@ -967,10 +966,10 @@ void acpiphp_enumerate_slots(struct pci_
 		 * parent is going to be handled by pciehp, in which case this
 		 * bridge is not interesting to us either.
 		 */
-		mutex_lock(&acpiphp_context_lock);
+		acpi_lock_hp_context();
 		context = acpiphp_get_context(handle);
 		if (!context) {
-			mutex_unlock(&acpiphp_context_lock);
+			acpi_unlock_hp_context();
 			put_device(&bus->dev);
 			pci_dev_put(bridge->pci_dev);
 			kfree(bridge);
@@ -980,7 +979,7 @@ void acpiphp_enumerate_slots(struct pci_
 		context->bridge = bridge;
 		/* Get a reference to the parent bridge. */
 		get_bridge(context->func.parent);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 	}
 
 	/* must be added to the list prior to calling register_slot */
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -402,6 +402,8 @@ static inline bool acpi_bus_can_wakeup(a
 
 void acpi_scan_lock_acquire(void);
 void acpi_scan_lock_release(void);
+void acpi_lock_hp_context(void);
+void acpi_unlock_hp_context(void);
 int acpi_scan_add_handler(struct acpi_scan_handler *handler);
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);


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

* [PATCH v3 4/7] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                           ` (2 preceding siblings ...)
  2014-02-02 17:16         ` [PATCH v3 3/7] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
@ 2014-02-02 17:17         ` Rafael J. Wysocki
  2014-02-02 17:18         ` [PATCH v3 5/7] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
                           ` (3 subsequent siblings)
  7 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:17 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

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

The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its
hotplug context objects directly to ACPI namespace nodes representing
hotplug devices.  However, after recent changes causing struct
acpi_device to be created for every namespace node representing a
device (regardless of its status), that is not necessary any more.
Moreover, it's vulnerable to a theoretical issue that the ACPI
handle passed in the context between handle_hotplug_event() and
hotplug_event_work() may become invalid in the meantime (as a
result of a concurrent table unload).

In principle, this issue might be addressed by adding a non-empty
release handler for ACPIPHP hotplug context objects analogous to
acpi_scan_drop_device(), but that would duplicate the code in that
function and in acpi_device_del_work_fn().  For this reason, it's
better to modify ACPIPHP to attach its device hotplug contexts to
struct device objects representing hotplug devices and make it
use acpi_hotplug_notify_cb() as its notify handler.  At the same
time, acpi_device_hotplug() can be modified to dispatch the new
.hp.event() callback pointing to acpiphp_hotplug_event() from ACPI
device objects associated with PCI devices and use the generic
ACPI device hotplug code for device objects with scan handlers
attached to them.

This allows the existing code duplication between ACPIPHP and the
ACPI core to be reduced too and makes further ACPI-based device
hotplug consolidation possible.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |  106 +++++++++++++++++++++-------
 drivers/pci/hotplug/acpiphp.h      |    9 +-
 drivers/pci/hotplug/acpiphp_glue.c |  136 +++++++------------------------------
 include/acpi/acpi_bus.h            |   22 +++++
 4 files changed, 136 insertions(+), 137 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -450,43 +450,61 @@ static int acpi_scan_bus_check(struct ac
 	return 0;
 }
 
+static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
+{
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		return acpi_scan_bus_check(adev);
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		return acpi_scan_device_check(adev);
+	case ACPI_NOTIFY_EJECT_REQUEST:
+	case ACPI_OST_EC_OSPM_EJECT:
+		return acpi_scan_hot_remove(adev);
+	}
+	return -EINVAL;
+}
+
 static void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
-	int error;
+	int error = -ENODEV;
 
 	lock_device_hotplug();
 	mutex_lock(&acpi_scan_lock);
 
 	/*
 	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it may have become invalid before
+	 * are holding acpi_scan_lock, but it might have become invalid before
 	 * that lock was acquired.
 	 */
 	if (adev->handle == INVALID_ACPI_HANDLE)
-		goto out;
+		goto err_out;
 
-	switch (src) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		error = acpi_scan_bus_check(adev);
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		error = acpi_scan_device_check(adev);
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-	case ACPI_OST_EC_OSPM_EJECT:
-		error = acpi_scan_hot_remove(adev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
+	if (adev->handler) {
+		error = acpi_generic_hotplug_event(adev, src);
+	} else {
+		int (*event)(struct acpi_device *, u32);
+
+		acpi_lock_hp_context();
+		event = adev->hp ? adev->hp->event : NULL;
+		acpi_unlock_hp_context();
+		/*
+		 * There may be additional notify handlers for device objects
+		 * without the .event() callback, so ignore them here.
+		 */
+		if (event)
+			error = event(adev, src);
+		else
+			goto out;
 	}
 	if (!error)
 		ost_code = ACPI_OST_SC_SUCCESS;
 
- out:
+ err_out:
 	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
+
+ out:
 	acpi_bus_put_acpi_device(adev);
 	mutex_unlock(&acpi_scan_lock);
 	unlock_device_hotplug();
@@ -494,8 +512,8 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_scan_handler *handler = data;
+	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
 
@@ -503,25 +521,48 @@ static void acpi_hotplug_notify_cb(acpi_
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (!handler->hotplug.enabled) {
+		if (handler && !handler->hotplug.enabled) {
 			acpi_handle_err(handle, "Eject disabled\n");
 			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto err_out;
+			goto out;
 		}
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
-	default:
-		/* non-hotplug event; possibly handled by other handler */
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
 		return;
+
+	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_POWER_FAULT:
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
+		goto out;
+
+	default:
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto out;
 	}
+
+	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	if (acpi_bus_get_acpi_device(handle, &adev))
-		goto err_out;
+		goto out;
 
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
@@ -529,10 +570,22 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	acpi_bus_put_acpi_device(adev);
 
- err_out:
+ out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+{
+	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				    acpi_hotplug_notify_cb, data);
+}
+
+void acpi_remove_hotplug_notify_handler(acpi_handle handle)
+{
+	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				   acpi_hotplug_notify_cb);
+}
+
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1991,8 +2044,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					acpi_hotplug_notify_cb, handler);
+			acpi_install_hotplug_notify_handler(handle, handler);
 			break;
 		}
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -116,12 +116,17 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
+	struct acpi_hotplug_context hp;
 	struct acpiphp_func func;
-	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
 
+static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
+{
+	return container_of(hp, struct acpiphp_context, hp);
+}
+
 static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
 {
 	return container_of(func, struct acpiphp_context, func);
@@ -129,7 +134,7 @@ static inline struct acpiphp_context *fu
 
 static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
 {
-	return func_to_context(func)->adev;
+	return func_to_context(func)->hp.self;
 }
 
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -59,17 +59,12 @@
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
 static void hotplug_event(u32 type, void *data);
 static void free_bridge(struct kref *kref);
 
-static void acpiphp_context_handler(acpi_handle handle, void *context)
-{
-	/* Intentionally empty. */
-}
-
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
  * @adev: ACPI device object to create the context for.
@@ -79,39 +74,27 @@ static void acpiphp_context_handler(acpi
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
-	acpi_status status;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return NULL;
 
-	context->adev = adev;
 	context->refcount = 1;
-	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
-	if (ACPI_FAILURE(status)) {
-		kfree(context);
-		return NULL;
-	}
+	acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_event);
 	return context;
 }
 
 /**
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
- * @handle: ACPI object handle to get the context for.
+ * @adev: ACPI device object to get the context for.
  *
  * Call under acpi_hp_context_lock.
  */
-static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = NULL;
-	acpi_status status;
-	void *data;
+	struct acpiphp_context *context = to_acpiphp_context(adev->hp);
 
-	status = acpi_get_data(handle, acpiphp_context_handler, &data);
-	if (ACPI_SUCCESS(status)) {
-		context = data;
-		context->refcount++;
-	}
+	context->refcount++;
 	return context;
 }
 
@@ -129,7 +112,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
+	context->hp.self->hp = NULL;
 	kfree(context);
 }
 
@@ -378,14 +361,8 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-						     handle_hotplug_event,
-						     context);
-		if (ACPI_FAILURE(status))
-			acpi_handle_err(handle,
-					"failed to install notify handler\n");
-	}
+	if (!(newfunc->flags & FUNC_HAS_DCK))
+		acpi_install_hotplug_notify_handler(handle, NULL);
 
 	return AE_OK;
 }
@@ -394,9 +371,13 @@ static struct acpiphp_bridge *acpiphp_ha
 {
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
+	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return NULL;
 
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
+	context = acpiphp_get_context(adev);
 	if (context) {
 		bridge = context->bridge;
 		if (bridge)
@@ -412,7 +393,6 @@ static void cleanup_bridge(struct acpiph
 {
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
-	acpi_status status;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
@@ -421,13 +401,8 @@ static void cleanup_bridge(struct acpiph
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
 
-			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(handle,
-							ACPI_SYSTEM_NOTIFY,
-							handle_hotplug_event);
-				if (ACPI_FAILURE(status))
-					pr_err("failed to remove notify handler\n");
-			}
+			if (!(func->flags & FUNC_HAS_DCK))
+				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
@@ -792,7 +767,7 @@ static void hotplug_event(u32 type, void
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
-	acpi_handle handle = context->adev->handle;
+	acpi_handle handle = context->hp.self->handle;
 	struct acpiphp_bridge *bridge;
 
 	acpi_lock_hp_context();
@@ -842,79 +817,24 @@ static void hotplug_event(u32 type, void
 		put_bridge(bridge);
 }
 
-static void hotplug_event_work(void *data, u32 type)
-{
-	struct acpiphp_context *context = data;
-
-	acpi_scan_lock_acquire();
-
-	hotplug_event(type, context);
-
-	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(context->adev->handle, type,
-				  ACPI_OST_SC_SUCCESS, NULL);
-	put_bridge(context->func.parent);
-}
-
-/**
- * handle_hotplug_event - handle ACPI hotplug event
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @data: pointer to acpiphp_context structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type)
 {
 	struct acpiphp_context *context;
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
-		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
 
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
-	if (context && !WARN_ON(context->adev->handle != handle)) {
-		get_bridge(context->func.parent);
-		acpiphp_put_context(context);
-		acpi_hotplug_execute(hotplug_event_work, context, type);
+	context = acpiphp_get_context(adev);
+	if (!context) {
 		acpi_unlock_hp_context();
-		return;
+		return -ENODATA;
 	}
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
 	acpi_unlock_hp_context();
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
+	hotplug_event(type, context);
+
+	put_bridge(context->func.parent);
+	return 0;
 }
 
 /**
@@ -967,7 +887,7 @@ void acpiphp_enumerate_slots(struct pci_
 		 * bridge is not interesting to us either.
 		 */
 		acpi_lock_hp_context();
-		context = acpiphp_get_context(handle);
+		context = acpiphp_get_context(adev);
 		if (!context) {
 			acpi_unlock_hp_context();
 			put_device(&bus->dev);
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -137,6 +137,16 @@ struct acpi_scan_handler {
 };
 
 /*
+ * ACPI Hotplug Context
+ * --------------------
+ */
+
+struct acpi_hotplug_context {
+	struct acpi_device *self;
+	int (*event)(struct acpi_device *, u32);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -329,6 +339,7 @@ struct acpi_device {
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
 	struct acpi_scan_handler *handler;
+	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
@@ -351,6 +362,15 @@ static inline void acpi_set_device_statu
 	*((u32 *)&adev->status) = sta;
 }
 
+static inline void acpi_set_hp_context(struct acpi_device *adev,
+				       struct acpi_hotplug_context *hp,
+				       int (*event)(struct acpi_device *, u32))
+{
+	hp->self = adev;
+	hp->event = event;
+	adev->hp = hp;
+}
+
 /* acpi_device.dev.bus == &acpi_bus_type */
 extern struct bus_type acpi_bus_type;
 
@@ -423,6 +443,8 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver


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

* [PATCH v3 5/7] ACPI / hotplug / PCI: Rework the handling of eject requests
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                           ` (3 preceding siblings ...)
  2014-02-02 17:17         ` [PATCH v3 4/7] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
@ 2014-02-02 17:18         ` Rafael J. Wysocki
  2014-02-02 17:19         ` [PATCH v3 6/7] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
                           ` (2 subsequent siblings)
  7 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:18 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

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

To avoid the need to install a hotplug notify handler for each ACPI
namespace node representing a device and having a matching scan
handler, move the check whether or not the ejection of the given
device is enabled through its scan handler from acpi_hotplug_notify_cb()
to acpi_generic_hotplug_event().  Also, move the execution of
ACPI_OST_SC_EJECT_IN_PROGRESS _OST to acpi_generic_hotplug_event(),
because in acpi_hotplug_notify_cb() or in acpi_eject_store() we really
don't know whether or not the eject is going to be in progress (for
example, acpi_hotplug_execute() may still fail without queuing up the
work item).

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

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -459,6 +459,12 @@ static int acpi_generic_hotplug_event(st
 		return acpi_scan_device_check(adev);
 	case ACPI_NOTIFY_EJECT_REQUEST:
 	case ACPI_OST_EC_OSPM_EJECT:
+		if (adev->handler && !adev->handler->hotplug.enabled) {
+			dev_info(&adev->dev, "Eject disabled\n");
+			return -EPERM;
+		}
+		acpi_evaluate_hotplug_ost(adev->handle, ACPI_NOTIFY_EJECT_REQUEST,
+					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		return acpi_scan_hot_remove(adev);
 	}
 	return -EINVAL;
@@ -483,6 +489,10 @@ static void acpi_device_hotplug(void *da
 
 	if (adev->handler) {
 		error = acpi_generic_hotplug_event(adev, src);
+		if (error == -EPERM) {
+			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+			goto err_out;
+		}
 	} else {
 		int (*event)(struct acpi_device *, u32);
 
@@ -512,7 +522,6 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_scan_handler *handler = data;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
@@ -528,13 +537,6 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (handler && !handler->hotplug.enabled) {
-			acpi_handle_err(handle, "Eject disabled\n");
-			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto out;
-		}
-		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
@@ -631,8 +633,6 @@ acpi_eject_store(struct device *d, struc
 	if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
 		return -ENODEV;
 
-	acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
-				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 	get_device(&acpi_device->dev);
 	status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device,
 				      ACPI_OST_EC_OSPM_EJECT);


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

* [PATCH v3 6/7] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                           ` (4 preceding siblings ...)
  2014-02-02 17:18         ` [PATCH v3 5/7] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
@ 2014-02-02 17:19         ` Rafael J. Wysocki
  2014-02-02 17:20         ` [PATCH v3 7/7] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
  2014-02-03 10:45         ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Mika Westerberg
  7 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:19 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

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

Since acpi_hotplug_notify_cb() does not use its data argument any
more, the second argument of acpi_install_hotplug_notify_handler()
can be dropped, so do that and update its callers accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |    6 +++---
 drivers/pci/hotplug/acpiphp_glue.c |    2 +-
 include/acpi/acpi_bus.h            |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -576,10 +576,10 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+void acpi_install_hotplug_notify_handler(acpi_handle handle)
 {
 	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, data);
+				    acpi_hotplug_notify_cb, NULL);
 }
 
 void acpi_remove_hotplug_notify_handler(acpi_handle handle)
@@ -2044,7 +2044,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_hotplug_notify_handler(handle, handler);
+			acpi_install_hotplug_notify_handler(handle);
 			break;
 		}
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -362,7 +362,7 @@ static acpi_status register_slot(acpi_ha
 
 	/* install notify handler */
 	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle, NULL);
+		acpi_install_hotplug_notify_handler(handle);
 
 	return AE_OK;
 }
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -443,7 +443,7 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_install_hotplug_notify_handler(acpi_handle handle);
 void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**


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

* [PATCH v3 7/7] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify()
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                           ` (5 preceding siblings ...)
  2014-02-02 17:19         ` [PATCH v3 6/7] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-02-02 17:20         ` Rafael J. Wysocki
  2014-02-03 10:45         ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Mika Westerberg
  7 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-02 17:20 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Linux PCI,
	Mika Westerberg, Robert Moore

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

Since acpi_bus_notify() is executed on all notifications for all
devices anyway, make it execute acpi_device_hotplug() for all
hotplug events instead of installing notify handlers pointing to
the same function for all hotplug devices.

This change reduces both the size and complexity of ACPI-based device
hotplug code.  Moreover, since acpi_device_hotplug() only does
significant things for devices that have either an ACPI scan handler,
or a hotplug context with .eject() defined, and those devices
had notify handlers pointing to acpi_hotplug_notify_cb() installed
before anyway, this modification shouldn't change functionality.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/bus.c                 |   60 +++++++++++++---------
 drivers/acpi/internal.h            |    1 
 drivers/acpi/scan.c                |  100 -------------------------------------
 drivers/pci/hotplug/acpiphp.h      |    1 
 drivers/pci/hotplug/acpiphp_glue.c |   16 ++---
 include/acpi/acpi_bus.h            |    2 
 6 files changed, 46 insertions(+), 134 deletions(-)

Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -340,62 +340,76 @@ static void acpi_bus_osc_support(void)
  */
 static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_device *device = NULL;
+	struct acpi_device *adev;
 	struct acpi_driver *driver;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
-			  type, handle));
+	acpi_status status;
+	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
 	switch (type) {
-
 	case ACPI_NOTIFY_BUS_CHECK:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n");
 		break;
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
 		/* TBD: Exactly what does 'light' mean? */
 		break;
 
 	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		/* TBD */
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
 		break;
 
 	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		/* TBD */
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
 		break;
 
 	case ACPI_NOTIFY_POWER_FAULT:
-		/* TBD */
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received unknown/unsupported notification [%08x]\n",
-				  type));
-		break;
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto err;
 	}
 
-	acpi_bus_get_acpi_device(handle, &device);
-	if (device) {
-		driver = device->driver;
-		if (driver && driver->ops.notify &&
-		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
-			driver->ops.notify(device, type);
+	if (acpi_bus_get_acpi_device(handle, &adev))
+		goto err;
 
-		acpi_bus_put_acpi_device(device);
+	driver = adev->driver;
+	if (driver && driver->ops.notify &&
+	    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
+		driver->ops.notify(adev, type);
+
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+	case ACPI_NOTIFY_DEVICE_CHECK:
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
+		if (ACPI_SUCCESS(status))
+			return;
+	default:
+		break;
 	}
+	acpi_bus_put_acpi_device(adev);
+	return;
+
+ err:
+	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
 /* --------------------------------------------------------------------------
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -73,6 +73,7 @@ static inline void acpi_lpss_init(void)
 #endif
 
 bool acpi_queue_hotplug_work(struct work_struct *work);
+void acpi_device_hotplug(void *data, u32 src);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
 
 /* --------------------------------------------------------------------------
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -470,7 +470,7 @@ static int acpi_generic_hotplug_event(st
 	return -EINVAL;
 }
 
-static void acpi_device_hotplug(void *data, u32 src)
+void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
@@ -520,74 +520,6 @@ static void acpi_device_hotplug(void *da
 	unlock_device_hotplug();
 }
 
-static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
-{
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-	struct acpi_device *adev;
-	acpi_status status;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
-
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-	if (acpi_bus_get_acpi_device(handle, &adev))
-		goto out;
-
-	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
-	if (ACPI_SUCCESS(status))
-		return;
-
-	acpi_bus_put_acpi_device(adev);
-
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-}
-
-void acpi_install_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, NULL);
-}
-
-void acpi_remove_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				   acpi_hotplug_notify_cb);
-}
-
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -2025,34 +1957,6 @@ void acpi_scan_hotplug_enabled(struct ac
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
-{
-	struct acpi_device_pnp pnp = {};
-	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
-
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
-
-	if (!pnp.type.hardware_id)
-		goto out;
-
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
-		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (handler) {
-			acpi_install_hotplug_notify_handler(handle);
-			break;
-		}
-	}
-
-out:
-	acpi_free_pnp_ids(&pnp);
-}
-
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 				      void *not_used, void **return_value)
 {
@@ -2074,8 +1978,6 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -283,7 +283,6 @@ static acpi_status register_slot(acpi_ha
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	acpi_unlock_hp_context();
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -291,8 +290,14 @@ static acpi_status register_slot(acpi_ha
 	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
+	/*
+	 * Dock stations' notify handler should be used for dock devices instead
+	 * of the common one, so clear hp.event in their contexts.
+	 */
 	if (acpi_has_method(handle, "_DCK"))
-		newfunc->flags |= FUNC_HAS_DCK;
+		context->hp.event = NULL;
+
+	acpi_unlock_hp_context();
 
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
@@ -360,10 +365,6 @@ static acpi_status register_slot(acpi_ha
 			pr_debug("failed to register dock device\n");
 	}
 
-	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle);
-
 	return AE_OK;
 }
 
@@ -400,9 +401,6 @@ static void cleanup_bridge(struct acpiph
 
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
-
-			if (!(func->flags & FUNC_HAS_DCK))
-				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -443,8 +443,6 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle);
-void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -167,7 +167,6 @@ struct acpiphp_attention_info
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 


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

* [PATCH] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (12 preceding siblings ...)
  2014-02-02  0:31   ` [PATCH v2 13/13] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations Rafael J. Wysocki
@ 2014-02-03  1:47   ` Rafael J. Wysocki
  2014-02-03 10:44   ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Mika Westerberg
  14 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03  1:47 UTC (permalink / raw)
  To: ACPI Devel Maling List, Linux PCI
  Cc: Bjorn Helgaas, Aaron Lu, Linux Kernel Mailing List, Mika Westerberg

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

Since acpiphp_check_bridge() called by acpiphp_check_host_bridge()
does things that require PCI rescan-remove locking around it,
make acpiphp_check_host_bridge() use that locking.

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

One more thing I overlooked in the PCI rescan-remove locking patchset.

I just found it sitting there in a dark dusty corner and staring at me in
horror when I approached it with a vacuum cleaner ...

Anyway, 3.14-rc2 material on top of patches [1-2/13] from this series:
https://lkml.org/lkml/2014/2/1/123

Thanks,
Rafael

---
 drivers/pci/hotplug/acpiphp_glue.c |    4 ++++
 1 file changed, 4 insertions(+)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -829,7 +829,11 @@ void acpiphp_check_host_bridge(acpi_hand
 
 	bridge = acpiphp_handle_to_bridge(handle);
 	if (bridge) {
+		pci_lock_rescan_remove();
+
 		acpiphp_check_bridge(bridge);
+
+		pci_unlock_rescan_remove();
 		put_bridge(bridge);
 	}
 }


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

* Re: [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                     ` (13 preceding siblings ...)
  2014-02-03  1:47   ` [PATCH] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock Rafael J. Wysocki
@ 2014-02-03 10:44   ` Mika Westerberg
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
  14 siblings, 1 reply; 100+ messages in thread
From: Mika Westerberg @ 2014-02-03 10:44 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Sun, Feb 02, 2014 at 01:19:33AM +0100, Rafael J. Wysocki wrote:
> On Monday, January 27, 2014 01:37:17 AM Rafael J. Wysocki wrote:
> > Hi All,
> > 
> > ACPIPHP can be simplified a bit on top of some PCI and ACPI changes merged
> > recently and the following series of patches implements those simplifications:
> > 
> > [1/11] Fix up two kerneldoc comments in acpiphp_glue.c.
> > [2/11] Get rid of an unnecessary label in register_slot().
> > [3/11] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
> > [4/11] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
> > [5/11] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
> > [6/11] Drop acpiphp_bus_add() (which has only one user).
> > [7/11] Drop crit_sect mutexes (that are redundant).
> > [8/11] Clean up the usage of the slot variable in hotplug_event().
> > [9/11] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
> > [10/11] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
> > [11/11] Drop handle argument from the member functions of struct acpi_dock_ops.
> > 
> > All of that is relateively straightforward, but I have some more intrusive changes
> > on top of it in the works.  They will be posted separately later this week.
> 
> I've learned a couple of things since I sent this patchset.  First, all
> bus->devices list walks that may remove PCI devices should be done in reverse
> order or they can crash if virtual functions are involved.  Second, hotplug_event()
> (in acpiphp_glue.c) has to acquire pci_rescan_remove_lock by itself, because it
> may be called from multiple places and all of them need that lock to be held.
> That is done by patches [1-2/13] which I'm planning to push as fixes for 3.14-rc2.
> 
> The rest is pretty much the same as last time except that the old patch [9/11]
> became [3/13] in this series and it has been changed so that the list is walked in
> reverse order.

On Intel NUC and DZ77RE-75K,

Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

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

* Re: [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug
  2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
                           ` (6 preceding siblings ...)
  2014-02-02 17:20         ` [PATCH v3 7/7] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
@ 2014-02-03 10:45         ` Mika Westerberg
  2014-02-03 21:51           ` Rafael J. Wysocki
  7 siblings, 1 reply; 100+ messages in thread
From: Mika Westerberg @ 2014-02-03 10:45 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI, Robert Moore

On Sun, Feb 02, 2014 at 06:11:19PM +0100, Rafael J. Wysocki wrote:
> As stated in the message at http://marc.info/?l=linux-acpi&m=139135963030012&w=4 ,
> patch [1/6] was actaully wrong and the whole patchset had to be reworked for that
> reason.  What follows is an entirely new version:
> 
> [1/7] Add a new function to ACPICA allowing a callback to be executed under the
>       namespace mutex after calling acpi_ns_get_attached_data().
> 
> [2/7] Use the new ACPICA's function to fix a couple of potential races related
>       to ACPI notifies.
> 
> [3/7] Same as [2/6] above.
> [4/7] Same as [3/6] above, rebased.
> [5/7] Same as [4/6] above.
> [6/7] Same as [5/6] above.
> [7/7] Dispatch ACPI hotplug notifications for "core" devices and PCI from
>       acpi_bus_notify().  This actually is different from [6/6] above, although
>       it serves the same purpose.
> 

On Intel NUC and DZ77RE-75K,

Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

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

* Re: [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug
  2014-02-03 10:45         ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Mika Westerberg
@ 2014-02-03 21:51           ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 21:51 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI, Robert Moore

On Monday, February 03, 2014 12:45:11 PM Mika Westerberg wrote:
> On Sun, Feb 02, 2014 at 06:11:19PM +0100, Rafael J. Wysocki wrote:
> > As stated in the message at http://marc.info/?l=linux-acpi&m=139135963030012&w=4 ,
> > patch [1/6] was actaully wrong and the whole patchset had to be reworked for that
> > reason.  What follows is an entirely new version:
> > 
> > [1/7] Add a new function to ACPICA allowing a callback to be executed under the
> >       namespace mutex after calling acpi_ns_get_attached_data().
> > 
> > [2/7] Use the new ACPICA's function to fix a couple of potential races related
> >       to ACPI notifies.
> > 
> > [3/7] Same as [2/6] above.
> > [4/7] Same as [3/6] above, rebased.
> > [5/7] Same as [4/6] above.
> > [6/7] Same as [5/6] above.
> > [7/7] Dispatch ACPI hotplug notifications for "core" devices and PCI from
> >       acpi_bus_notify().  This actually is different from [6/6] above, although
> >       it serves the same purpose.
> > 
> 
> On Intel NUC and DZ77RE-75K,
> 
> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Thanks a lot for testing!

In the meantime, though, I found two more race conditions in ACPIPHP related to
races with sysfs-triggered device remove.  I have patches to fix them, but then
I had to rebase this series (and the ACPIPHP one this is based on) on top of
those fixes.

I'm going to resend the two patchsets as one series including the fixes
mentioned above.  I tried to avoid sending out a series of 20+ patches, because
then it's almost guaranteed that no one will look at them unless they happen to
break things in testing, but I guess I have no choice but to do that at this
point.

Thanks!

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

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

* [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core
  2014-02-03 10:44   ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Mika Westerberg
@ 2014-02-03 23:12     ` Rafael J. Wysocki
  2014-02-03 23:14       ` [PATCH 1/24][Resend] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
                         ` (24 more replies)
  0 siblings, 25 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:12 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Monday, February 03, 2014 12:44:08 PM Mika Westerberg wrote:
> On Sun, Feb 02, 2014 at 01:19:33AM +0100, Rafael J. Wysocki wrote:
> > On Monday, January 27, 2014 01:37:17 AM Rafael J. Wysocki wrote:
> > > Hi All,
> > > 
> > > ACPIPHP can be simplified a bit on top of some PCI and ACPI changes merged
> > > recently and the following series of patches implements those simplifications:
> > > 
> > > [1/11] Fix up two kerneldoc comments in acpiphp_glue.c.
> > > [2/11] Get rid of an unnecessary label in register_slot().
> > > [3/11] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
> > > [4/11] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
> > > [5/11] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
> > > [6/11] Drop acpiphp_bus_add() (which has only one user).
> > > [7/11] Drop crit_sect mutexes (that are redundant).
> > > [8/11] Clean up the usage of the slot variable in hotplug_event().
> > > [9/11] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
> > > [10/11] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
> > > [11/11] Drop handle argument from the member functions of struct acpi_dock_ops.
> > > 
> > > All of that is relateively straightforward, but I have some more intrusive changes
> > > on top of it in the works.  They will be posted separately later this week.
> > 
> > I've learned a couple of things since I sent this patchset.  First, all
> > bus->devices list walks that may remove PCI devices should be done in reverse
> > order or they can crash if virtual functions are involved.  Second, hotplug_event()
> > (in acpiphp_glue.c) has to acquire pci_rescan_remove_lock by itself, because it
> > may be called from multiple places and all of them need that lock to be held.
> > That is done by patches [1-2/13] which I'm planning to push as fixes for 3.14-rc2.
> > 
> > The rest is pretty much the same as last time except that the old patch [9/11]
> > became [3/13] in this series and it has been changed so that the list is walked in
> > reverse order.
> 
> On Intel NUC and DZ77RE-75K,
> 
> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Thanks!

As I said previously, I have found two concurrency-related bugs more in ACPIPHP
and I needed to put fixes for those bugs at the top of the series (after previous
[1-2/13] and the patch at https://patchwork.kernel.org/patch/3567701/).  For this
reason, I also had to rebase the ACPI/PCI hotplug consolidation patchset
(https://lkml.org/lkml/2014/2/2/87) which got a few additional cosmetic changes too.

The following is a combination of the two series with one patch dropped (it would
conflict with [4-5/24]) and a few patches added.  It is on top of 3.14-rc1.

Patches [1-5/24], that are regarded as 3.14-rc2 material, are on the bleeding-edge
branch of linux-pm.git.  The remaining patches will show up in bleeding-edge
shortly.

[1/24] Remove entries from bus->devices in reverse order (in ACPIPHP).
[2/24] Move PCI rescan-remove locking to hotplug_event().
[3/24] Scan root bus under the PCI rescan-remove lock
[4/24] Fix race in handle_hotplug_event() related to concurrent bridge removal.
[5/24] Fix race in hotplug_event() related to dock events and concurrent bridge removal.
[6/24] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
[7/24] Fix up two kerneldoc comments in acpiphp_glue.c.
[8/24] Get rid of an unnecessary label in register_slot().
[9/24] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
[10/24] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
[11/24] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
[12/24] Drop acpiphp_bus_add() (which has only one user).
[13/24] Drop crit_sect mutexes (that are redundant).
[14/24] Clean up the usage of the slot variable in hotplug_event().
[15/24] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
[16/24] Do not pass ACPI handle to hotplug_event().
[17/24] Add a new function to ACPICA allowing a callback to be executed under the
        namespace mutex after calling acpi_ns_get_attached_data().
[18/24] Use the new ACPICA's function to fix a couple of potential races related
        to ACPI notifies.
[19/24] Move the hotplug context lock definition to the ACPI core (from ACPIPHP).
[20/24] Consolidate ACPI hotplug signaling for PCI and ACPI core.
[21/24] Rework the handling of eject requests in the ACPI core.
[22/24] Simplify a routine for installing hotplug notify handlers.
[23/24] Dispatch ACPI hotplug notifications for "core" devices and PCI from
        acpi_bus_notify().
[24/24] Pass struct acpi_device pointer to acpiphp_check_host_bridge().

Thanks!

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

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

* [PATCH 1/24][Resend] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
@ 2014-02-03 23:14       ` Rafael J. Wysocki
  2014-02-03 23:15       ` [PATCH 2/24][Resend] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() Rafael J. Wysocki
                         ` (23 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:14 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

According to the changelog of commit 29ed1f29b68a (PCI: pciehp: Fix null
pointer deref when hot-removing SR-IOV device) it is unsafe to walk the
bus->devices list of a PCI bus and remove devices from it in direct order,
because that may lead to NULL pointer dereferences related to virtual
functions.

For this reason, change all of the bus->devices list walks in
acpiphp_glue.c during which devices may be removed to be carried out in
reverse order.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -742,7 +742,7 @@ static void trim_stale_devices(struct pc
 
 		/* The device is a bridge. so check the bus below it. */
 		pm_runtime_get_sync(&dev->dev);
-		list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+		list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list)
 			trim_stale_devices(child);
 
 		pm_runtime_put(&dev->dev);
@@ -773,8 +773,8 @@ static void acpiphp_check_bridge(struct
 			; /* do nothing */
 		} else if (get_slot_status(slot) == ACPI_STA_ALL) {
 			/* remove stale devices if any */
-			list_for_each_entry_safe(dev, tmp, &bus->devices,
-						 bus_list)
+			list_for_each_entry_safe_reverse(dev, tmp,
+							 &bus->devices, bus_list)
 				if (PCI_SLOT(dev->devfn) == slot->device)
 					trim_stale_devices(dev);
 
@@ -805,7 +805,7 @@ static void acpiphp_sanitize_bus(struct
 	int i;
 	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
 
-	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+	list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
 		for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
 			struct resource *res = &dev->resource[i];
 			if ((res->flags & type_mask) && !res->start &&

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

* [PATCH 2/24][Resend] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
  2014-02-03 23:14       ` [PATCH 1/24][Resend] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
@ 2014-02-03 23:15       ` Rafael J. Wysocki
  2014-02-03 23:16       ` [PATCH 3/24][Resend] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock Rafael J. Wysocki
                         ` (22 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:15 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Commit 9217a984671e (ACPI / hotplug / PCI: Use global PCI rescan-remove
locking) modified ACPIPHP to protect its PCI device removal and addition
code paths from races against sysfs-driven rescan and remove operations
with the help of PCI rescan-remove locking.  However, it overlooked the
fact that hotplug_event_work() is not the only caller of hotplug_event()
which may also be called by dock_hotplug_event() and that code path
is missing the PCI rescan-remove locking.  This means that, although
the PCI rescan-remove lock is held as appropriate during the handling
of events originating from handle_hotplug_event(), the ACPIPHP's
operations resulting from dock events may still suffer the race
conditions that commit 9217a984671e was supposed to eliminate.

To address that problem, move the PCI rescan-remove locking from
hotplug_event_work() to hotplug_event() so that it is used regardless
of the way that function is invoked.

Revamps: 9217a984671e (ACPI / hotplug / PCI: Use global PCI rescan-remove locking)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -852,6 +852,7 @@ static void hotplug_event(acpi_handle ha
 
 	mutex_unlock(&acpiphp_context_lock);
 
+	pci_lock_rescan_remove();
 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
 	switch (type) {
@@ -905,6 +906,7 @@ static void hotplug_event(acpi_handle ha
 		break;
 	}
 
+	pci_unlock_rescan_remove();
 	if (bridge)
 		put_bridge(bridge);
 }
@@ -915,11 +917,9 @@ static void hotplug_event_work(void *dat
 	acpi_handle handle = context->handle;
 
 	acpi_scan_lock_acquire();
-	pci_lock_rescan_remove();
 
 	hotplug_event(handle, type, context);
 
-	pci_unlock_rescan_remove();
 	acpi_scan_lock_release();
 	acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
 	put_bridge(context->func.parent);


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

* [PATCH 3/24][Resend] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
  2014-02-03 23:14       ` [PATCH 1/24][Resend] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
  2014-02-03 23:15       ` [PATCH 2/24][Resend] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() Rafael J. Wysocki
@ 2014-02-03 23:16       ` Rafael J. Wysocki
  2014-02-03 23:18       ` [PATCH 4/24][New] ACPI / hotplug / PCI: Fix bridge removal race in handle_hotplug_event() Rafael J. Wysocki
                         ` (21 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:16 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Since acpiphp_check_bridge() called by acpiphp_check_host_bridge()
does things that require PCI rescan-remove locking around it,
make acpiphp_check_host_bridge() use that locking.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |    4 ++++
 1 file changed, 4 insertions(+)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -829,7 +829,11 @@ void acpiphp_check_host_bridge(acpi_hand
 
 	bridge = acpiphp_handle_to_bridge(handle);
 	if (bridge) {
+		pci_lock_rescan_remove();
+
 		acpiphp_check_bridge(bridge);
+
+		pci_unlock_rescan_remove();
 		put_bridge(bridge);
 	}
 }


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

* [PATCH 4/24][New] ACPI / hotplug / PCI: Fix bridge removal race in handle_hotplug_event()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (2 preceding siblings ...)
  2014-02-03 23:16       ` [PATCH 3/24][Resend] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock Rafael J. Wysocki
@ 2014-02-03 23:18       ` Rafael J. Wysocki
  2014-02-03 23:18       ` [PATCH 5/24][New] ACPI / hotplug / PCI: Fix bridge removal race vs dock events Rafael J. Wysocki
                         ` (20 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:18 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

If a PCI bridge with an ACPIPHP context attached is removed via
sysfs, the code path executed as a result is the following:

pci_stop_and_remove_bus_device_locked
 pci_remove_bus
  pcibios_remove_bus
   acpi_pci_remove_bus
    acpiphp_remove_slots
     cleanup_bridge
     put_bridge
      free_bridge
       acpiphp_put_context (for each child, under context lock)
        kfree (child context)

Now, if a hotplug notify is dispatched for one of the bridge's
children and the timing is such that handle_hotplug_event() for
that notify is executed while free_bridge() above is running,
the get_bridge(context->func.parent) in handle_hotplug_event()
will not really help, because it is too late to prevent the bridge
from going away and the child's context may be freed before
hotplug_event_work() scheduled from handle_hotplug_event()
dereferences the pointer to it passed via the data argument.
That will cause a kernel crash to happpen in hotplug_event_work().

To prevent that from happening, make handle_hotplug_event()
check the is_going_away flag of the function's parent bridge
(under acpiphp_context_lock) and bail out if it's set.  Also,
make cleanup_bridge() set the bridge's is_going_away flag under
acpiphp_context_lock so that it cannot be changed between the
check and the subsequent get_bridge(context->func.parent) in
handle_hotplug_event().

Then, in the above scenario, handle_hotplug_event() will notice
that context->func.parent->is_going_away is already set and it
will exit immediately preventing the crash from happening.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -441,7 +441,9 @@ static void cleanup_bridge(struct acpiph
 	list_del(&bridge->list);
 	mutex_unlock(&bridge_mutex);
 
+	mutex_lock(&acpiphp_context_lock);
 	bridge->is_going_away = true;
+	mutex_unlock(&acpiphp_context_lock);
 }
 
 /**
@@ -941,6 +943,7 @@ static void handle_hotplug_event(acpi_ha
 {
 	struct acpiphp_context *context;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
+	acpi_status status;
 
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
@@ -976,13 +979,20 @@ static void handle_hotplug_event(acpi_ha
 
 	mutex_lock(&acpiphp_context_lock);
 	context = acpiphp_get_context(handle);
-	if (context && !WARN_ON(context->handle != handle)) {
-		get_bridge(context->func.parent);
-		acpiphp_put_context(context);
-		acpi_hotplug_execute(hotplug_event_work, context, type);
+	if (!context || WARN_ON(context->handle != handle)
+	    || context->func.parent->is_going_away)
+		goto err_out;
+
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
+	status = acpi_hotplug_execute(hotplug_event_work, context, type);
+	if (ACPI_SUCCESS(status)) {
 		mutex_unlock(&acpiphp_context_lock);
 		return;
 	}
+	put_bridge(context->func.parent);
+
+ err_out:
 	mutex_unlock(&acpiphp_context_lock);
 	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 


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

* [PATCH 5/24][New] ACPI / hotplug / PCI: Fix bridge removal race vs dock events
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (3 preceding siblings ...)
  2014-02-03 23:18       ` [PATCH 4/24][New] ACPI / hotplug / PCI: Fix bridge removal race in handle_hotplug_event() Rafael J. Wysocki
@ 2014-02-03 23:18       ` Rafael J. Wysocki
  2014-02-03 23:20       ` [PATCH 6/24][Resend] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
                         ` (19 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:18 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

If a PCI bridge with an ACPIPHP context attached is removed via
sysfs, the code path executed as a result is the following:

pci_stop_and_remove_bus_device_locked
 pci_remove_bus
  pcibios_remove_bus
   acpi_pci_remove_bus
    acpiphp_remove_slots
     cleanup_bridge
      unregister_hotplug_dock_device (drops dock references to the bridge)
     put_bridge
      free_bridge
       acpiphp_put_context (for each child, under context lock)
        kfree (context)

Now, if a dock event affecting one of the bridge's child devices
occurs (roughly at the same time), it will lead to the following code
path:

acpi_dock_deferred_cb
 dock_notify
  handle_eject_request
   hot_remove_dock_devices
    dock_hotplug_event
     hotplug_event (dereferences context)

That may lead to a kernel crash in hotplug_event() if it is executed
after the last kfree() in the bridge removal code path.

To prevent that from happening, add a wrapper around hotplug_event()
called dock_event() and point the .handler pointer in acpiphp_dock_ops
to it.  Make that wrapper retrieve the device's ACPIPHP context using
acpiphp_get_context() (instead of taking it from the data argument)
under acpiphp_context_lock and check if the parent bridge's
is_going_away flag is set.  If that flag is set, it will return
immediately and if it is not set it will grab a reference to the
device's parent bridge before executing hotplug_event().

Then, in the above scenario, the reference to the parent bridge
held by dock_event() will prevent free_bridge() from being executed
for it until hotplug_event() returns.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -210,10 +210,29 @@ static void post_dock_fixups(acpi_handle
 	}
 }
 
+static void dock_event(acpi_handle handle, u32 type, void *data)
+{
+	struct acpiphp_context *context;
+
+	mutex_lock(&acpiphp_context_lock);
+	context = acpiphp_get_context(handle);
+	if (!context || WARN_ON(context->handle != handle)
+	    || context->func.parent->is_going_away) {
+		mutex_unlock(&acpiphp_context_lock);
+		return;
+	}
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
+	mutex_unlock(&acpiphp_context_lock);
+
+	hotplug_event(handle, type, data);
+
+	put_bridge(context->func.parent);
+}
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
 	.fixup = post_dock_fixups,
-	.handler = hotplug_event,
+	.handler = dock_event,
 };
 
 /* Check whether the PCI device is managed by native PCIe hotplug driver */


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

* [PATCH 6/24][Resend] ACPI / hotplug / PCI: Simplify disable_slot()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (4 preceding siblings ...)
  2014-02-03 23:18       ` [PATCH 5/24][New] ACPI / hotplug / PCI: Fix bridge removal race vs dock events Rafael J. Wysocki
@ 2014-02-03 23:20       ` Rafael J. Wysocki
  2014-02-03 23:21       ` [PATCH 7/24][Resend] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
                         ` (18 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:20 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

After recent PCI core changes related to the rescan/remove locking,
the ACPIPHP's disable_slot() function is only called under the
general PCI rescan/remove lock, so it doesn't have to use
dev_in_slot() any more to avoid race conditions.  Make it simply
walk the devices on the bus and drop the ones in the slot being
disabled and drop dev_in_slot() which has no more users.

Moreover, to avoid problems described in the changelog of commit
29ed1f29b68a (PCI: pciehp: Fix null pointer deref when hot-removing
SR-IOV device), make disable_slot() carry out the list walk in
reverse order.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   28 +++++-----------------------
 1 file changed, 5 insertions(+), 23 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -625,32 +625,15 @@ static void __ref enable_slot(struct acp
 	}
 }
 
-/* return first device in slot, acquiring a reference on it */
-static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
-{
-	struct pci_bus *bus = slot->bus;
-	struct pci_dev *dev;
-	struct pci_dev *ret = NULL;
-
-	down_read(&pci_bus_sem);
-	list_for_each_entry(dev, &bus->devices, bus_list)
-		if (PCI_SLOT(dev->devfn) == slot->device) {
-			ret = pci_dev_get(dev);
-			break;
-		}
-	up_read(&pci_bus_sem);
-
-	return ret;
-}
-
 /**
  * disable_slot - disable a slot
  * @slot: ACPI PHP slot
  */
 static void disable_slot(struct acpiphp_slot *slot)
 {
+	struct pci_bus *bus = slot->bus;
+	struct pci_dev *dev, *prev;
 	struct acpiphp_func *func;
-	struct pci_dev *pdev;
 
 	/*
 	 * enable_slot() enumerates all functions in this device via
@@ -658,10 +641,9 @@ static void disable_slot(struct acpiphp_
 	 * methods (_EJ0, etc.) or not.  Therefore, we remove all functions
 	 * here.
 	 */
-	while ((pdev = dev_in_slot(slot))) {
-		pci_stop_and_remove_bus_device(pdev);
-		pci_dev_put(pdev);
-	}
+	list_for_each_entry_safe_reverse(dev, prev, &bus->devices, bus_list)
+		if (PCI_SLOT(dev->devfn) == slot->device)
+			pci_stop_and_remove_bus_device(dev);
 
 	list_for_each_entry(func, &slot->funcs, sibling)
 		acpiphp_bus_trim(func_to_handle(func));


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

* [PATCH 7/24][Resend] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (5 preceding siblings ...)
  2014-02-03 23:20       ` [PATCH 6/24][Resend] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
@ 2014-02-03 23:21       ` Rafael J. Wysocki
  2014-02-03 23:22       ` [PATCH 8/24][Resend] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
                         ` (17 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:21 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Add proper kerneldoc comments describing acpiphp_enumerate_slots()
and acpiphp_remove_slots().

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -1001,9 +1001,12 @@ static void handle_hotplug_event(acpi_ha
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-/*
- * Create hotplug slots for the PCI bus.
- * It should always return 0 to avoid skipping following notifiers.
+/**
+ * acpiphp_enumerate_slots - Enumerate PCI slots for a given bus.
+ * @bus: PCI bus to enumerate the slots for.
+ *
+ * A "slot" is an object associated with a PCI device number.  All functions
+ * (PCI devices) with the same bus and device number belong to the same slot.
  */
 void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
@@ -1076,7 +1079,10 @@ void acpiphp_enumerate_slots(struct pci_
 	}
 }
 
-/* Destroy hotplug slots associated with the PCI bus */
+/**
+ * acpiphp_remove_slots - Remove slot objects associated with a given bus.
+ * @bus: PCI bus to remove the slot objects for.
+ */
 void acpiphp_remove_slots(struct pci_bus *bus)
 {
 	struct acpiphp_bridge *bridge;


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

* [PATCH 8/24][Resend] ACPI / hotplug / PCI: Simplify register_slot()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (6 preceding siblings ...)
  2014-02-03 23:21       ` [PATCH 7/24][Resend] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
@ 2014-02-03 23:22       ` Rafael J. Wysocki
  2014-02-03 23:23       ` [PATCH 9/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
                         ` (16 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:22 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

The err label in register_slot() is only jumped to from one place,
so move the code under the label to that place and drop the label.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -335,8 +335,10 @@ static acpi_status register_slot(acpi_ha
 
 	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 	if (!slot) {
-		status = AE_NO_MEMORY;
-		goto err;
+		mutex_lock(&acpiphp_context_lock);
+		acpiphp_put_context(context);
+		mutex_unlock(&acpiphp_context_lock);
+		return AE_NO_MEMORY;
 	}
 
 	slot->bus = bridge->pci_bus;
@@ -404,12 +406,6 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	return AE_OK;
-
- err:
-	mutex_lock(&acpiphp_context_lock);
-	acpiphp_put_context(context);
-	mutex_unlock(&acpiphp_context_lock);
-	return status;
 }
 
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)


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

* [PATCH 9/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_trim()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (7 preceding siblings ...)
  2014-02-03 23:22       ` [PATCH 8/24][Resend] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
@ 2014-02-03 23:23       ` Rafael J. Wysocki
  2014-02-03 23:24       ` [PATCH 10/24][Resend] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
                         ` (15 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:23 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

If trim_stale_devices() calls acpi_bus_trim() directly, we can
save a potentially costly acpi_bus_get_device() invocation.  After
making that change acpiphp_bus_trim() would only be called from one
place, so move the code from it to that place and drop it.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -489,19 +489,6 @@ static unsigned char acpiphp_max_busnr(s
 }
 
 /**
- * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree.
- * @handle: ACPI device object handle to start from.
- */
-static void acpiphp_bus_trim(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
-	if (adev)
-		acpi_bus_trim(adev);
-}
-
-/**
  * acpiphp_bus_add - Scan ACPI namespace subtree.
  * @handle: ACPI object handle to start the scan from.
  */
@@ -641,8 +628,12 @@ static void disable_slot(struct acpiphp_
 		if (PCI_SLOT(dev->devfn) == slot->device)
 			pci_stop_and_remove_bus_device(dev);
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_trim(func_to_handle(func));
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev;
+
+		if (!acpi_bus_get_device(func_to_handle(func), &adev))
+			acpi_bus_trim(adev);
+	}
 
 	slot->flags &= (~SLOT_ENABLED);
 }
@@ -714,11 +705,12 @@ static unsigned int get_slot_status(stru
  */
 static void trim_stale_devices(struct pci_dev *dev)
 {
-	acpi_handle handle = ACPI_HANDLE(&dev->dev);
+	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
 	struct pci_bus *bus = dev->subordinate;
 	bool alive = false;
 
-	if (handle) {
+	if (adev) {
+		acpi_handle handle = adev->handle;
 		acpi_status status;
 		unsigned long long sta;
 
@@ -734,8 +726,8 @@ static void trim_stale_devices(struct pc
 	}
 	if (!alive) {
 		pci_stop_and_remove_bus_device(dev);
-		if (handle)
-			acpiphp_bus_trim(handle);
+		if (adev)
+			acpi_bus_trim(adev);
 	} else if (bus) {
 		struct pci_dev *child, *tmp;
 


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

* [PATCH 10/24][Resend] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (8 preceding siblings ...)
  2014-02-03 23:23       ` [PATCH 9/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
@ 2014-02-03 23:24       ` Rafael J. Wysocki
  2014-02-03 23:25       ` [PATCH 11/24][Update] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
                         ` (14 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:24 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

If a struct acpi_device pointer is passed to acpiphp_no_hotplug()
instead of an ACPI handle, the function won't need to call
acpi_bus_get_device(), which may be costly, any more.  Then,
trim_stale_devices() can call acpiphp_no_hotplug() passing
the struct acpi_device object it already has directly to that
function.

Make those changes and update slot_no_hotplug() accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -638,11 +638,8 @@ static void disable_slot(struct acpiphp_
 	slot->flags &= (~SLOT_ENABLED);
 }
 
-static bool acpiphp_no_hotplug(acpi_handle handle)
+static bool acpiphp_no_hotplug(struct acpi_device *adev)
 {
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_get_device(handle, &adev);
 	return adev && adev->flags.no_hotplug;
 }
 
@@ -650,10 +647,13 @@ static bool slot_no_hotplug(struct acpip
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		if (acpiphp_no_hotplug(func_to_handle(func)))
-			return true;
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev = NULL;
 
+		acpi_bus_get_device(func_to_handle(func), &adev);
+		if (acpiphp_no_hotplug(adev))
+			return true;
+	}
 	return false;
 }
 
@@ -710,13 +710,12 @@ static void trim_stale_devices(struct pc
 	bool alive = false;
 
 	if (adev) {
-		acpi_handle handle = adev->handle;
 		acpi_status status;
 		unsigned long long sta;
 
-		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+		status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
 		alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL)
-			|| acpiphp_no_hotplug(handle);
+			|| acpiphp_no_hotplug(adev);
 	}
 	if (!alive) {
 		u32 v;


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

* [PATCH 11/24][Update] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (9 preceding siblings ...)
  2014-02-03 23:24       ` [PATCH 10/24][Resend] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
@ 2014-02-03 23:25       ` Rafael J. Wysocki
  2014-02-03 23:26       ` [PATCH 12/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
                         ` (13 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:25 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

After recent modifications of the ACPI core making it create a struct
acpi_device object for every namespace node representing a device
regardless of the current status of that device the ACPIPHP code
can store a struct acpi_device pointer instead of an ACPI handle
in struct acpiphp_context.  This immediately makes it possible to
avoid making potentially costly calls to acpi_bus_get_device() in
two places and allows some more simplifications to be made going
forward.

The reason why that is correct is because ACPIPHP only installs
hotify handlers for namespace nodes that exist when
acpiphp_enumerate_slots() is called for their parent bridge.
That only happens if the parent bridge has an ACPI companion
associated with it, which means that the ACPI namespace scope
in question has been scanned already at that point.  That, in
turn, means that struct acpi_device objects have been created
for all namespace nodes in that scope and pointers to those
objects can be stored directly instead of their ACPI handles.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp.h      |    9 +++++--
 drivers/pci/hotplug/acpiphp_glue.c |   46 +++++++++++++++++--------------------
 2 files changed, 29 insertions(+), 26 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -117,8 +117,8 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
-	acpi_handle handle;
 	struct acpiphp_func func;
+	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
@@ -128,9 +128,14 @@ static inline struct acpiphp_context *fu
 	return container_of(func, struct acpiphp_context, func);
 }
 
+static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
+{
+	return func_to_context(func)->adev;
+}
+
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
 {
-	return func_to_context(func)->handle;
+	return func_to_acpi_device(func)->handle;
 }
 
 /*
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -73,11 +73,11 @@ static void acpiphp_context_handler(acpi
 
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
- * @handle: ACPI object handle to create the context for.
+ * @adev: ACPI device object to create the context for.
  *
  * Call under acpiphp_context_lock.
  */
-static struct acpiphp_context *acpiphp_init_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
 	acpi_status status;
@@ -86,9 +86,9 @@ static struct acpiphp_context *acpiphp_i
 	if (!context)
 		return NULL;
 
-	context->handle = handle;
+	context->adev = adev;
 	context->refcount = 1;
-	status = acpi_attach_data(handle, acpiphp_context_handler, context);
+	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
 	if (ACPI_FAILURE(status)) {
 		kfree(context);
 		return NULL;
@@ -118,7 +118,7 @@ static struct acpiphp_context *acpiphp_g
 
 /**
  * acpiphp_put_context - Drop a reference to ACPI hotplug context.
- * @handle: ACPI object handle to put the context for.
+ * @context: ACPI hotplug context to drop a reference to.
  *
  * The context object is removed if there are no more references to it.
  *
@@ -130,7 +130,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->handle, acpiphp_context_handler);
+	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
 	kfree(context);
 }
 
@@ -216,7 +216,7 @@ static void dock_event(acpi_handle handl
 
 	mutex_lock(&acpiphp_context_lock);
 	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->handle != handle)
+	if (!context || WARN_ON(context->adev->handle != handle)
 	    || context->func.parent->is_going_away) {
 		mutex_unlock(&acpiphp_context_lock);
 		return;
@@ -284,6 +284,7 @@ static acpi_status register_slot(acpi_ha
 {
 	struct acpiphp_bridge *bridge = data;
 	struct acpiphp_context *context;
+	struct acpi_device *adev;
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *newfunc;
 	acpi_status status = AE_OK;
@@ -303,12 +304,14 @@ static acpi_status register_slot(acpi_ha
 				"can't evaluate _ADR (%#x)\n", status);
 		return AE_OK;
 	}
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
 
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 
 	mutex_lock(&acpiphp_context_lock);
-	context = acpiphp_init_context(handle);
+	context = acpiphp_init_context(adev);
 	if (!context) {
 		mutex_unlock(&acpiphp_context_lock);
 		acpi_handle_err(handle, "No hotplug context\n");
@@ -628,12 +631,8 @@ static void disable_slot(struct acpiphp_
 		if (PCI_SLOT(dev->devfn) == slot->device)
 			pci_stop_and_remove_bus_device(dev);
 
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		struct acpi_device *adev;
-
-		if (!acpi_bus_get_device(func_to_handle(func), &adev))
-			acpi_bus_trim(adev);
-	}
+	list_for_each_entry(func, &slot->funcs, sibling)
+		acpi_bus_trim(func_to_acpi_device(func));
 
 	slot->flags &= (~SLOT_ENABLED);
 }
@@ -647,13 +646,10 @@ static bool slot_no_hotplug(struct acpip
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		struct acpi_device *adev = NULL;
-
-		acpi_bus_get_device(func_to_handle(func), &adev);
-		if (acpiphp_no_hotplug(adev))
+	list_for_each_entry(func, &slot->funcs, sibling)
+		if (acpiphp_no_hotplug(func_to_acpi_device(func)))
 			return true;
-	}
+
 	return false;
 }
 
@@ -908,7 +904,7 @@ static void hotplug_event(acpi_handle ha
 static void hotplug_event_work(void *data, u32 type)
 {
 	struct acpiphp_context *context = data;
-	acpi_handle handle = context->handle;
+	acpi_handle handle = context->adev->handle;
 
 	acpi_scan_lock_acquire();
 
@@ -967,7 +963,7 @@ static void handle_hotplug_event(acpi_ha
 
 	mutex_lock(&acpiphp_context_lock);
 	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->handle != handle)
+	if (!context || WARN_ON(context->adev->handle != handle)
 	    || context->func.parent->is_going_away)
 		goto err_out;
 
@@ -998,16 +994,18 @@ static void handle_hotplug_event(acpi_ha
 void acpiphp_enumerate_slots(struct pci_bus *bus)
 {
 	struct acpiphp_bridge *bridge;
+	struct acpi_device *adev;
 	acpi_handle handle;
 	acpi_status status;
 
 	if (acpiphp_disabled)
 		return;
 
-	handle = ACPI_HANDLE(bus->bridge);
-	if (!handle)
+	adev = ACPI_COMPANION(bus->bridge);
+	if (!adev)
 		return;
 
+	handle = adev->handle;
 	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
 	if (!bridge) {
 		acpi_handle_err(handle, "No memory for bridge object\n");


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

* [PATCH 12/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_add()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (10 preceding siblings ...)
  2014-02-03 23:25       ` [PATCH 11/24][Update] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
@ 2014-02-03 23:26       ` Rafael J. Wysocki
  2014-02-03 23:27       ` [PATCH 13/24][Resend] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
                         ` (12 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:26 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

acpiphp_bus_add() is only called from one place, so move the code out
of it into that place and drop it.  Also make that code use
func_to_acpi_device() to get the struct acpi_device pointer it needs
instead of calling acpi_bus_get_device() which may be costly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -491,20 +491,6 @@ static unsigned char acpiphp_max_busnr(s
 	return max;
 }
 
-/**
- * acpiphp_bus_add - Scan ACPI namespace subtree.
- * @handle: ACPI object handle to start the scan from.
- */
-static void acpiphp_bus_add(acpi_handle handle)
-{
-	struct acpi_device *adev = NULL;
-
-	acpi_bus_scan(handle);
-	acpi_bus_get_device(handle, &adev);
-	if (acpi_device_enumerated(adev))
-		acpi_device_set_power(adev, ACPI_STATE_D0);
-}
-
 static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
 {
 	struct acpiphp_func *func;
@@ -544,9 +530,13 @@ static int acpiphp_rescan_slot(struct ac
 {
 	struct acpiphp_func *func;
 
-	list_for_each_entry(func, &slot->funcs, sibling)
-		acpiphp_bus_add(func_to_handle(func));
+	list_for_each_entry(func, &slot->funcs, sibling) {
+		struct acpi_device *adev = func_to_acpi_device(func);
 
+		acpi_bus_scan(adev->handle);
+		if (acpi_device_enumerated(adev))
+			acpi_device_set_power(adev, ACPI_STATE_D0);
+	}
 	return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0));
 }
 


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

* [PATCH 13/24][Resend] ACPI / hotplug / PCI: Drop crit_sect locking
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (11 preceding siblings ...)
  2014-02-03 23:26       ` [PATCH 12/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
@ 2014-02-03 23:27       ` Rafael J. Wysocki
  2014-02-03 23:33       ` [PATCH 14/24][Update] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
                         ` (11 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:27 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

After recent PCI core changes related to the rescan/remove locking,
the code sections under crit_sect mutexes from ACPIPHP slot objects
are always executed under the general PCI rescan/remove lock.
For this reason, the crit_sect mutexes are simply redundant, so drop
them.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp.h      |    1 -
 drivers/pci/hotplug/acpiphp_glue.c |   23 +++--------------------
 2 files changed, 3 insertions(+), 21 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -347,7 +347,6 @@ static acpi_status register_slot(acpi_ha
 	slot->bus = bridge->pci_bus;
 	slot->device = device;
 	INIT_LIST_HEAD(&slot->funcs);
-	mutex_init(&slot->crit_sect);
 
 	list_add_tail(&slot->node, &bridge->slots);
 
@@ -744,7 +743,6 @@ static void acpiphp_check_bridge(struct
 		struct pci_bus *bus = slot->bus;
 		struct pci_dev *dev, *tmp;
 
-		mutex_lock(&slot->crit_sect);
 		if (slot_no_hotplug(slot)) {
 			; /* do nothing */
 		} else if (get_slot_status(slot) == ACPI_STA_ALL) {
@@ -759,7 +757,6 @@ static void acpiphp_check_bridge(struct
 		} else {
 			disable_slot(slot);
 		}
-		mutex_unlock(&slot->crit_sect);
 	}
 }
 
@@ -846,12 +843,8 @@ static void hotplug_event(acpi_handle ha
 		} else {
 			struct acpiphp_slot *slot = func->slot;
 
-			if (slot->flags & SLOT_IS_GOING_AWAY)
-				break;
-
-			mutex_lock(&slot->crit_sect);
-			enable_slot(slot);
-			mutex_unlock(&slot->crit_sect);
+			if (!(slot->flags & SLOT_IS_GOING_AWAY))
+				enable_slot(slot);
 		}
 		break;
 
@@ -862,7 +855,6 @@ static void hotplug_event(acpi_handle ha
 			acpiphp_check_bridge(bridge);
 		} else {
 			struct acpiphp_slot *slot = func->slot;
-			int ret;
 
 			if (slot->flags & SLOT_IS_GOING_AWAY)
 				break;
@@ -871,10 +863,7 @@ static void hotplug_event(acpi_handle ha
 			 * Check if anything has changed in the slot and rescan
 			 * from the parent if that's the case.
 			 */
-			mutex_lock(&slot->crit_sect);
-			ret = acpiphp_rescan_slot(slot);
-			mutex_unlock(&slot->crit_sect);
-			if (ret)
+			if (acpiphp_rescan_slot(slot))
 				acpiphp_check_bridge(func->parent);
 		}
 		break;
@@ -1088,13 +1077,10 @@ int acpiphp_enable_slot(struct acpiphp_s
 	if (slot->flags & SLOT_IS_GOING_AWAY)
 		return -ENODEV;
 
-	mutex_lock(&slot->crit_sect);
 	/* configure all functions */
 	if (!(slot->flags & SLOT_ENABLED))
 		enable_slot(slot);
 
-	mutex_unlock(&slot->crit_sect);
-
 	pci_unlock_rescan_remove();
 	return 0;
 }
@@ -1110,8 +1096,6 @@ static int acpiphp_disable_and_eject_slo
 	if (slot->flags & SLOT_IS_GOING_AWAY)
 		return -ENODEV;
 
-	mutex_lock(&slot->crit_sect);
-
 	/* unconfigure all functions */
 	disable_slot(slot);
 
@@ -1125,7 +1109,6 @@ static int acpiphp_disable_and_eject_slo
 			break;
 		}
 
-	mutex_unlock(&slot->crit_sect);
 	return 0;
 }
 
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -93,7 +93,6 @@ struct acpiphp_slot {
 	struct list_head funcs;		/* one slot may have different
 					   objects (i.e. for each function) */
 	struct slot *slot;
-	struct mutex crit_sect;
 
 	u8		device;		/* pci device# */
 	u32		flags;		/* see below */


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

* [PATCH 14/24][Update] ACPI / hotplug / PCI: Simplify hotplug_event()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (12 preceding siblings ...)
  2014-02-03 23:27       ` [PATCH 13/24][Resend] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
@ 2014-02-03 23:33       ` Rafael J. Wysocki
  2014-02-03 23:33       ` [PATCH 15/24][Resend] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
                         ` (10 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:33 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

A few lines of code can be cut from hotplug_event() by defining
and initializing the slot variable at the top of the function,
so do that.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -817,6 +817,7 @@ static void hotplug_event(acpi_handle ha
 {
 	struct acpiphp_context *context = data;
 	struct acpiphp_func *func = &context->func;
+	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
 	char objname[64];
 	struct acpi_buffer buffer = { .length = sizeof(objname),
@@ -838,14 +839,11 @@ static void hotplug_event(acpi_handle ha
 		pr_debug("%s: Bus check notify on %s\n", __func__, objname);
 		pr_debug("%s: re-enumerating slots under %s\n",
 			 __func__, objname);
-		if (bridge) {
+		if (bridge)
 			acpiphp_check_bridge(bridge);
-		} else {
-			struct acpiphp_slot *slot = func->slot;
+		else if (!(slot->flags & SLOT_IS_GOING_AWAY))
+			enable_slot(slot);
 
-			if (!(slot->flags & SLOT_IS_GOING_AWAY))
-				enable_slot(slot);
-		}
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
@@ -853,12 +851,7 @@ static void hotplug_event(acpi_handle ha
 		pr_debug("%s: Device check notify on %s\n", __func__, objname);
 		if (bridge) {
 			acpiphp_check_bridge(bridge);
-		} else {
-			struct acpiphp_slot *slot = func->slot;
-
-			if (slot->flags & SLOT_IS_GOING_AWAY)
-				break;
-
+		} else if (!(slot->flags & SLOT_IS_GOING_AWAY)) {
 			/*
 			 * Check if anything has changed in the slot and rescan
 			 * from the parent if that's the case.
@@ -871,7 +864,7 @@ static void hotplug_event(acpi_handle ha
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
 		pr_debug("%s: Device eject notify on %s\n", __func__, objname);
-		acpiphp_disable_and_eject_slot(func->slot);
+		acpiphp_disable_and_eject_slot(slot);
 		break;
 	}
 

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

* [PATCH 15/24][Resend] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (13 preceding siblings ...)
  2014-02-03 23:33       ` [PATCH 14/24][Update] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
@ 2014-02-03 23:33       ` Rafael J. Wysocki
  2014-02-03 23:34       ` [PATCH 16/24][New] ACPI / hotplug / PCI: Do not pass ACPI handle to hotplug_event() Rafael J. Wysocki
                         ` (9 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:33 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Make hotplug_event() use acpi_handle_debug() instead of an open-coded
debug message printing and clean up the messages printed by it.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -819,9 +819,6 @@ static void hotplug_event(acpi_handle ha
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
-	char objname[64];
-	struct acpi_buffer buffer = { .length = sizeof(objname),
-				      .pointer = objname };
 
 	mutex_lock(&acpiphp_context_lock);
 	bridge = context->bridge;
@@ -831,14 +828,11 @@ static void hotplug_event(acpi_handle ha
 	mutex_unlock(&acpiphp_context_lock);
 
 	pci_lock_rescan_remove();
-	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		/* bus re-enumerate */
-		pr_debug("%s: Bus check notify on %s\n", __func__, objname);
-		pr_debug("%s: re-enumerating slots under %s\n",
-			 __func__, objname);
+		acpi_handle_debug(handle, "Bus check in %s()\n", __func__);
 		if (bridge)
 			acpiphp_check_bridge(bridge);
 		else if (!(slot->flags & SLOT_IS_GOING_AWAY))
@@ -848,7 +842,7 @@ static void hotplug_event(acpi_handle ha
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		/* device check */
-		pr_debug("%s: Device check notify on %s\n", __func__, objname);
+		acpi_handle_debug(handle, "Device check in %s()\n", __func__);
 		if (bridge) {
 			acpiphp_check_bridge(bridge);
 		} else if (!(slot->flags & SLOT_IS_GOING_AWAY)) {
@@ -863,7 +857,7 @@ static void hotplug_event(acpi_handle ha
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
-		pr_debug("%s: Device eject notify on %s\n", __func__, objname);
+		acpi_handle_debug(handle, "Eject request in %s()\n", __func__);
 		acpiphp_disable_and_eject_slot(slot);
 		break;
 	}

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

* [PATCH 16/24][New] ACPI / hotplug / PCI: Do not pass ACPI handle to hotplug_event()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (14 preceding siblings ...)
  2014-02-03 23:33       ` [PATCH 15/24][Resend] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
@ 2014-02-03 23:34       ` Rafael J. Wysocki
  2014-02-03 23:34       ` [PATCH 17/24][Resend] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
                         ` (8 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:34 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Since hotplug_event() can get the ACPI handle needed for debug
printouts from its context argument, there's no need to pass the
handle to it.  Moreover, the second argument's type may be changed
to (struct acpiphp_context *), because that's what is always passed
to hotplug_event() as the second argument anyway.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/pci/hotplug/acpiphp_glue.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -63,7 +63,7 @@ static DEFINE_MUTEX(acpiphp_context_lock
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
-static void hotplug_event(acpi_handle handle, u32 type, void *data);
+static void hotplug_event(u32 type, struct acpiphp_context *context);
 static void free_bridge(struct kref *kref);
 
 static void acpiphp_context_handler(acpi_handle handle, void *context)
@@ -225,7 +225,7 @@ static void dock_event(acpi_handle handl
 	acpiphp_put_context(context);
 	mutex_unlock(&acpiphp_context_lock);
 
-	hotplug_event(handle, type, data);
+	hotplug_event(type, context);
 
 	put_bridge(context->func.parent);
 }
@@ -813,9 +813,9 @@ void acpiphp_check_host_bridge(acpi_hand
 
 static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot);
 
-static void hotplug_event(acpi_handle handle, u32 type, void *data)
+static void hotplug_event(u32 type, struct acpiphp_context *context)
 {
-	struct acpiphp_context *context = data;
+	acpi_handle handle = context->adev->handle;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
@@ -870,14 +870,14 @@ static void hotplug_event(acpi_handle ha
 static void hotplug_event_work(void *data, u32 type)
 {
 	struct acpiphp_context *context = data;
-	acpi_handle handle = context->adev->handle;
 
 	acpi_scan_lock_acquire();
 
-	hotplug_event(handle, type, context);
+	hotplug_event(type, context);
 
 	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
+	acpi_evaluate_hotplug_ost(context->adev->handle, type,
+				  ACPI_OST_SC_SUCCESS, NULL);
 	put_bridge(context->func.parent);
 }
 

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

* [PATCH 17/24][Resend] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (15 preceding siblings ...)
  2014-02-03 23:34       ` [PATCH 16/24][New] ACPI / hotplug / PCI: Do not pass ACPI handle to hotplug_event() Rafael J. Wysocki
@ 2014-02-03 23:34       ` Rafael J. Wysocki
  2014-02-03 23:36       ` [PATCH 18/24][Update] ACPI / hotplug: Fix potential race in acpi_bus_notify() Rafael J. Wysocki
                         ` (7 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:34 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Introduce a new function, acpi_get_data_full(), working in analogy
with acpi_get_data() except that it can execute a callback provided
as its 4th argument right after acpi_ns_get_attached_data() has
returned a success.

That will allow Linux to reference count the object pointed to by
*data before the namespace mutex is released so as to ensure that it
will not be freed going forward until the reference to it acquired
by acpi_get_data_full() is dropped.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/acpi/acpica/nsxfeval.c |   33 ++++++++++++++++++++++++++++++---
 include/acpi/acpixf.h          |    4 ++++
 2 files changed, 34 insertions(+), 3 deletions(-)

Index: linux-pm/drivers/acpi/acpica/nsxfeval.c
===================================================================
--- linux-pm.orig/drivers/acpi/acpica/nsxfeval.c
+++ linux-pm/drivers/acpi/acpica/nsxfeval.c
@@ -923,19 +923,22 @@ ACPI_EXPORT_SYMBOL(acpi_detach_data)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_get_data
+ * FUNCTION:    acpi_get_data_full
  *
  * PARAMETERS:  obj_handle          - Namespace node
  *              handler             - Handler used in call to attach_data
  *              data                - Where the data is returned
+ *              callback            - function to execute before returning
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
+ * DESCRIPTION: Retrieve data that was previously attached to a namespace node
+ *              and execute a callback before returning.
  *
  ******************************************************************************/
 acpi_status
-acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
+acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler,
+		   void **data, void (*callback)(void *))
 {
 	struct acpi_namespace_node *node;
 	acpi_status status;
@@ -960,10 +963,34 @@ acpi_get_data(acpi_handle obj_handle, ac
 	}
 
 	status = acpi_ns_get_attached_data(node, handler, data);
+	if (ACPI_SUCCESS(status) && callback) {
+		callback(*data);
+	}
 
 unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return (status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_get_data_full)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_get_data
+ *
+ * PARAMETERS:  obj_handle          - Namespace node
+ *              handler             - Handler used in call to attach_data
+ *              data                - Where the data is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
+{
+	return acpi_get_data_full(obj_handle, handler, data, NULL);
+}
+
 ACPI_EXPORT_SYMBOL(acpi_get_data)
Index: linux-pm/include/acpi/acpixf.h
===================================================================
--- linux-pm.orig/include/acpi/acpixf.h
+++ linux-pm/include/acpi/acpixf.h
@@ -230,6 +230,10 @@ acpi_attach_data(acpi_handle object, acp
 acpi_status acpi_detach_data(acpi_handle object, acpi_object_handler handler);
 
 acpi_status
+acpi_get_data_full(acpi_handle object, acpi_object_handler handler, void **data,
+		   void (*callback)(void *));
+
+acpi_status
 acpi_get_data(acpi_handle object, acpi_object_handler handler, void **data);
 
 acpi_status

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

* [PATCH 18/24][Update] ACPI / hotplug: Fix potential race in acpi_bus_notify()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (16 preceding siblings ...)
  2014-02-03 23:34       ` [PATCH 17/24][Resend] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
@ 2014-02-03 23:36       ` Rafael J. Wysocki
  2014-02-03 23:36       ` [PATCH 19/24][Update] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
                         ` (6 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:36 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

There is a slight possibility for the ACPI device object pointed to
by adev in acpi_hotplug_notify_cb() to become invalid between the
acpi_bus_get_device() that it comes from and the subsequent dereference
of that pointer under get_device().  Namely, if acpi_scan_drop_device()
runs in parallel with acpi_hotplug_notify_cb(), acpi_device_del_work_fn()
queued up by it may delete the device object in question right after
a successful execution of acpi_bus_get_device() in acpi_bus_notify().

An analogous problem is present in acpi_bus_notify() where the device
pointer coming from acpi_bus_get_device() may become invalid before
it subsequent dereference in the "if" block.

To prevent that from happening, introduce a new function,
acpi_bus_get_acpi_device(), working analogously to acpi_bus_get_device()
except that it will grab a reference to the ACPI device object returned
by it and it will do that under the ACPICA's namespace mutex.  Then,
make both acpi_hotplug_notify_cb() and acpi_bus_notify() use
acpi_bus_get_acpi_device() instead of acpi_bus_get_device() so as to
ensure that the pointers used by them will not become stale at one
point.

In addition to that, introduce acpi_bus_put_acpi_device() as a wrapper
around put_device() to be used along with acpi_bus_get_acpi_device()
and make the (new) users of the latter use acpi_bus_put_acpi_device()
too.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/bus.c      |    6 ++++--
 drivers/acpi/scan.c     |   42 ++++++++++++++++++++++++++++++++++--------
 include/acpi/acpi_bus.h |    2 ++
 3 files changed, 40 insertions(+), 10 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -476,7 +476,7 @@ static void acpi_device_hotplug(void *da
 
  out:
 	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
-	put_device(&adev->dev);
+	acpi_bus_put_acpi_device(adev);
 	mutex_unlock(&acpi_scan_lock);
 	unlock_device_hotplug();
 }
@@ -488,9 +488,6 @@ static void acpi_hotplug_notify_cb(acpi_
 	struct acpi_device *adev;
 	acpi_status status;
 
-	if (acpi_bus_get_device(handle, &adev))
-		goto err_out;
-
 	switch (type) {
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
@@ -512,12 +509,15 @@ static void acpi_hotplug_notify_cb(acpi_
 		/* non-hotplug event; possibly handled by other handler */
 		return;
 	}
-	get_device(&adev->dev);
+	adev = acpi_bus_get_acpi_device(handle);
+	if (!adev)
+		goto err_out;
+
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
 		return;
 
-	put_device(&adev->dev);
+	acpi_bus_put_acpi_device(adev);
 
  err_out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
@@ -1112,14 +1112,16 @@ static void acpi_scan_drop_device(acpi_h
 	mutex_unlock(&acpi_device_del_lock);
 }
 
-int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device,
+				void (*callback)(void *))
 {
 	acpi_status status;
 
 	if (!device)
 		return -EINVAL;
 
-	status = acpi_get_data(handle, acpi_scan_drop_device, (void **)device);
+	status = acpi_get_data_full(handle, acpi_scan_drop_device,
+				    (void **)device, callback);
 	if (ACPI_FAILURE(status) || !*device) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
 				  handle));
@@ -1127,8 +1129,32 @@ int acpi_bus_get_device(acpi_handle hand
 	}
 	return 0;
 }
+
+int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+{
+	return acpi_get_device_data(handle, device, NULL);
+}
 EXPORT_SYMBOL(acpi_bus_get_device);
 
+static void get_acpi_device(void *dev)
+{
+	if (dev)
+		get_device(&((struct acpi_device *)dev)->dev);
+}
+
+struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle)
+{
+	struct acpi_device *adev = NULL;
+
+	acpi_get_device_data(handle, &adev, get_acpi_device);
+	return adev;
+}
+
+void acpi_bus_put_acpi_device(struct acpi_device *adev)
+{
+	put_device(&adev->dev);
+}
+
 int acpi_device_add(struct acpi_device *device,
 		    void (*release)(struct device *))
 {
Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -340,7 +340,7 @@ static void acpi_bus_osc_support(void)
  */
 static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_device *device = NULL;
+	struct acpi_device *device;
 	struct acpi_driver *driver;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
@@ -387,12 +387,14 @@ static void acpi_bus_notify(acpi_handle
 		break;
 	}
 
-	acpi_bus_get_device(handle, &device);
+	device = acpi_bus_get_acpi_device(handle);
 	if (device) {
 		driver = device->driver;
 		if (driver && driver->ops.notify &&
 		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
 			driver->ops.notify(device, type);
+
+		acpi_bus_put_acpi_device(device);
 	}
 }
 
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -381,6 +381,8 @@ extern int unregister_acpi_notifier(stru
  */
 
 int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device);
+struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle);
+void acpi_bus_put_acpi_device(struct acpi_device *adev);
 acpi_status acpi_bus_get_status_handle(acpi_handle handle,
 				       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);

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

* [PATCH 19/24][Update] ACPI / hotplug / PCI: Define hotplug context lock in the core
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (17 preceding siblings ...)
  2014-02-03 23:36       ` [PATCH 18/24][Update] ACPI / hotplug: Fix potential race in acpi_bus_notify() Rafael J. Wysocki
@ 2014-02-03 23:36       ` Rafael J. Wysocki
  2014-02-03 23:37       ` [PATCH 20/24][Update] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
                         ` (5 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:36 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Subsequent changes will require the ACPI core to acquire the lock
protecting the ACPIPHP hotplug contexts, so move the definition of
the lock to the core and change its name to be more generic.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |   11 +++++++
 drivers/pci/hotplug/acpiphp_glue.c |   51 ++++++++++++++++++-------------------
 include/acpi/acpi_bus.h            |    2 +
 3 files changed, 38 insertions(+), 26 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -41,6 +41,7 @@ static DEFINE_MUTEX(acpi_scan_lock);
 static LIST_HEAD(acpi_scan_handlers_list);
 DEFINE_MUTEX(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
+static DEFINE_MUTEX(acpi_hp_context_lock);
 
 struct acpi_device_bus_id{
 	char bus_id[15];
@@ -60,6 +61,16 @@ void acpi_scan_lock_release(void)
 }
 EXPORT_SYMBOL_GPL(acpi_scan_lock_release);
 
+void acpi_lock_hp_context(void)
+{
+	mutex_lock(&acpi_hp_context_lock);
+}
+
+void acpi_unlock_hp_context(void)
+{
+	mutex_unlock(&acpi_hp_context_lock);
+}
+
 int acpi_scan_add_handler(struct acpi_scan_handler *handler)
 {
 	if (!handler || !handler->attach)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -58,7 +58,6 @@
 
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
-static DEFINE_MUTEX(acpiphp_context_lock);
 
 static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
@@ -75,7 +74,7 @@ static void acpiphp_context_handler(acpi
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
  * @adev: ACPI device object to create the context for.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
@@ -100,7 +99,7 @@ static struct acpiphp_context *acpiphp_i
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
  * @handle: ACPI object handle to get the context for.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
 {
@@ -122,7 +121,7 @@ static struct acpiphp_context *acpiphp_g
  *
  * The context object is removed if there are no more references to it.
  *
- * Call under acpiphp_context_lock.
+ * Call under acpi_hp_context_lock.
  */
 static void acpiphp_put_context(struct acpiphp_context *context)
 {
@@ -151,7 +150,7 @@ static void free_bridge(struct kref *kre
 	struct acpiphp_slot *slot, *next;
 	struct acpiphp_func *func, *tmp;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 
 	bridge = container_of(kref, struct acpiphp_bridge, ref);
 
@@ -175,7 +174,7 @@ static void free_bridge(struct kref *kre
 	pci_dev_put(bridge->pci_dev);
 	kfree(bridge);
 
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 }
 
 /*
@@ -214,16 +213,16 @@ static void dock_event(acpi_handle handl
 {
 	struct acpiphp_context *context;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_get_context(handle);
 	if (!context || WARN_ON(context->adev->handle != handle)
 	    || context->func.parent->is_going_away) {
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		return;
 	}
 	get_bridge(context->func.parent);
 	acpiphp_put_context(context);
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
 	hotplug_event(type, context);
 
@@ -310,17 +309,17 @@ static acpi_status register_slot(acpi_ha
 	device = (adr >> 16) & 0xffff;
 	function = adr & 0xffff;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_init_context(adev);
 	if (!context) {
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		acpi_handle_err(handle, "No hotplug context\n");
 		return AE_NOT_EXIST;
 	}
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -338,9 +337,9 @@ static acpi_status register_slot(acpi_ha
 
 	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
 	if (!slot) {
-		mutex_lock(&acpiphp_context_lock);
+		acpi_lock_hp_context();
 		acpiphp_put_context(context);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		return AE_NO_MEMORY;
 	}
 
@@ -415,7 +414,7 @@ static struct acpiphp_bridge *acpiphp_ha
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_get_context(handle);
 	if (context) {
 		bridge = context->bridge;
@@ -424,7 +423,7 @@ static struct acpiphp_bridge *acpiphp_ha
 
 		acpiphp_put_context(context);
 	}
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 	return bridge;
 }
 
@@ -458,9 +457,9 @@ static void cleanup_bridge(struct acpiph
 	list_del(&bridge->list);
 	mutex_unlock(&bridge_mutex);
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	bridge->is_going_away = true;
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 }
 
 /**
@@ -820,12 +819,12 @@ static void hotplug_event(u32 type, stru
 	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	bridge = context->bridge;
 	if (bridge)
 		get_bridge(bridge);
 
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 
 	pci_lock_rescan_remove();
 
@@ -927,7 +926,7 @@ static void handle_hotplug_event(acpi_ha
 		goto out;
 	}
 
-	mutex_lock(&acpiphp_context_lock);
+	acpi_lock_hp_context();
 	context = acpiphp_get_context(handle);
 	if (!context || WARN_ON(context->adev->handle != handle)
 	    || context->func.parent->is_going_away)
@@ -937,13 +936,13 @@ static void handle_hotplug_event(acpi_ha
 	acpiphp_put_context(context);
 	status = acpi_hotplug_execute(hotplug_event_work, context, type);
 	if (ACPI_SUCCESS(status)) {
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 		return;
 	}
 	put_bridge(context->func.parent);
 
  err_out:
-	mutex_unlock(&acpiphp_context_lock);
+	acpi_unlock_hp_context();
 	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
  out:
@@ -999,10 +998,10 @@ void acpiphp_enumerate_slots(struct pci_
 		 * parent is going to be handled by pciehp, in which case this
 		 * bridge is not interesting to us either.
 		 */
-		mutex_lock(&acpiphp_context_lock);
+		acpi_lock_hp_context();
 		context = acpiphp_get_context(handle);
 		if (!context) {
-			mutex_unlock(&acpiphp_context_lock);
+			acpi_unlock_hp_context();
 			put_device(&bus->dev);
 			pci_dev_put(bridge->pci_dev);
 			kfree(bridge);
@@ -1012,7 +1011,7 @@ void acpiphp_enumerate_slots(struct pci_
 		context->bridge = bridge;
 		/* Get a reference to the parent bridge. */
 		get_bridge(context->func.parent);
-		mutex_unlock(&acpiphp_context_lock);
+		acpi_unlock_hp_context();
 	}
 
 	/* must be added to the list prior to calling register_slot */
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -404,6 +404,8 @@ static inline bool acpi_bus_can_wakeup(a
 
 void acpi_scan_lock_acquire(void);
 void acpi_scan_lock_release(void);
+void acpi_lock_hp_context(void);
+void acpi_unlock_hp_context(void);
 int acpi_scan_add_handler(struct acpi_scan_handler *handler);
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);

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

* [PATCH 20/24][Update] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (18 preceding siblings ...)
  2014-02-03 23:36       ` [PATCH 19/24][Update] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
@ 2014-02-03 23:37       ` Rafael J. Wysocki
  2014-02-06 13:07         ` [Update][PATCH 20/24] " Rafael J. Wysocki
  2014-02-03 23:38       ` [PATCH 21/24][Resend] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
                         ` (4 subsequent siblings)
  24 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:37 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its
hotplug context objects directly to ACPI namespace nodes representing
hotplug devices.  However, after recent changes causing struct
acpi_device to be created for every namespace node representing a
device (regardless of its status), that is not necessary any more.
Moreover, it's vulnerable to a theoretical issue that the ACPI
handle passed in the context between handle_hotplug_event() and
hotplug_event_work() may become invalid in the meantime (as a
result of a concurrent table unload).

In principle, this issue might be addressed by adding a non-empty
release handler for ACPIPHP hotplug context objects analogous to
acpi_scan_drop_device(), but that would duplicate the code in that
function and in acpi_device_del_work_fn().  For this reason, it's
better to modify ACPIPHP to attach its device hotplug contexts to
struct device objects representing hotplug devices and make it
use acpi_hotplug_notify_cb() as its notify handler.  At the same
time, acpi_device_hotplug() can be modified to dispatch the new
.hp.event() callback pointing to acpiphp_hotplug_event() from ACPI
device objects associated with PCI devices and use the generic
ACPI device hotplug code for device objects with scan handlers
attached to them.

This allows the existing code duplication between ACPIPHP and the
ACPI core to be reduced too and makes further ACPI-based device
hotplug consolidation possible.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c                |  106 +++++++++++++++++------
 drivers/pci/hotplug/acpiphp.h      |    9 +-
 drivers/pci/hotplug/acpiphp_glue.c |  164 +++++++------------------------------
 include/acpi/acpi_bus.h            |   22 ++++
 4 files changed, 142 insertions(+), 159 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -450,43 +450,61 @@ static int acpi_scan_bus_check(struct ac
 	return 0;
 }
 
+static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
+{
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		return acpi_scan_bus_check(adev);
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		return acpi_scan_device_check(adev);
+	case ACPI_NOTIFY_EJECT_REQUEST:
+	case ACPI_OST_EC_OSPM_EJECT:
+		return acpi_scan_hot_remove(adev);
+	}
+	return -EINVAL;
+}
+
 static void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
-	int error;
+	int error = -ENODEV;
 
 	lock_device_hotplug();
 	mutex_lock(&acpi_scan_lock);
 
 	/*
 	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it may have become invalid before
+	 * are holding acpi_scan_lock, but it might have become invalid before
 	 * that lock was acquired.
 	 */
 	if (adev->handle == INVALID_ACPI_HANDLE)
-		goto out;
+		goto err_out;
 
-	switch (src) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		error = acpi_scan_bus_check(adev);
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		error = acpi_scan_device_check(adev);
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-	case ACPI_OST_EC_OSPM_EJECT:
-		error = acpi_scan_hot_remove(adev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
+	if (adev->handler) {
+		error = acpi_generic_hotplug_event(adev, src);
+	} else {
+		int (*event)(struct acpi_device *, u32);
+
+		acpi_lock_hp_context();
+		event = adev->hp ? adev->hp->event : NULL;
+		acpi_unlock_hp_context();
+		/*
+		 * There may be additional notify handlers for device objects
+		 * without the .event() callback, so ignore them here.
+		 */
+		if (event)
+			error = event(adev, src);
+		else
+			goto out;
 	}
 	if (!error)
 		ost_code = ACPI_OST_SC_SUCCESS;
 
- out:
+ err_out:
 	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
+
+ out:
 	acpi_bus_put_acpi_device(adev);
 	mutex_unlock(&acpi_scan_lock);
 	unlock_device_hotplug();
@@ -494,8 +512,8 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_scan_handler *handler = data;
+	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
 
@@ -503,26 +521,49 @@ static void acpi_hotplug_notify_cb(acpi_
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (!handler->hotplug.enabled) {
+		if (handler && !handler->hotplug.enabled) {
 			acpi_handle_err(handle, "Eject disabled\n");
 			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto err_out;
+			goto out;
 		}
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
-	default:
-		/* non-hotplug event; possibly handled by other handler */
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
 		return;
+
+	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_POWER_FAULT:
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
+		goto out;
+
+	default:
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto out;
 	}
+
+	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	adev = acpi_bus_get_acpi_device(handle);
 	if (!adev)
-		goto err_out;
+		goto out;
 
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
@@ -530,10 +571,22 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	acpi_bus_put_acpi_device(adev);
 
- err_out:
+ out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+{
+	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				    acpi_hotplug_notify_cb, data);
+}
+
+void acpi_remove_hotplug_notify_handler(acpi_handle handle)
+{
+	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				   acpi_hotplug_notify_cb);
+}
+
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1995,8 +2048,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					acpi_hotplug_notify_cb, handler);
+			acpi_install_hotplug_notify_handler(handle, handler);
 			break;
 		}
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -116,12 +116,17 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
+	struct acpi_hotplug_context hp;
 	struct acpiphp_func func;
-	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
 
+static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
+{
+	return container_of(hp, struct acpiphp_context, hp);
+}
+
 static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
 {
 	return container_of(func, struct acpiphp_context, func);
@@ -129,7 +134,7 @@ static inline struct acpiphp_context *fu
 
 static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
 {
-	return func_to_context(func)->adev;
+	return func_to_context(func)->hp.self;
 }
 
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -59,17 +59,12 @@
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
 static void hotplug_event(u32 type, struct acpiphp_context *context);
 static void free_bridge(struct kref *kref);
 
-static void acpiphp_context_handler(acpi_handle handle, void *context)
-{
-	/* Intentionally empty. */
-}
-
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
  * @adev: ACPI device object to create the context for.
@@ -79,39 +74,27 @@ static void acpiphp_context_handler(acpi
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
-	acpi_status status;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return NULL;
 
-	context->adev = adev;
 	context->refcount = 1;
-	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
-	if (ACPI_FAILURE(status)) {
-		kfree(context);
-		return NULL;
-	}
+	acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_event);
 	return context;
 }
 
 /**
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
- * @handle: ACPI object handle to get the context for.
+ * @adev: ACPI device object to get the context for.
  *
  * Call under acpi_hp_context_lock.
  */
-static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = NULL;
-	acpi_status status;
-	void *data;
+	struct acpiphp_context *context = to_acpiphp_context(adev->hp);
 
-	status = acpi_get_data(handle, acpiphp_context_handler, &data);
-	if (ACPI_SUCCESS(status)) {
-		context = data;
-		context->refcount++;
-	}
+	context->refcount++;
 	return context;
 }
 
@@ -129,7 +112,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
+	context->hp.self->hp = NULL;
 	kfree(context);
 }
 
@@ -211,22 +194,13 @@ static void post_dock_fixups(acpi_handle
 
 static void dock_event(acpi_handle handle, u32 type, void *data)
 {
-	struct acpiphp_context *context;
+	struct acpi_device *adev;
 
-	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->adev->handle != handle)
-	    || context->func.parent->is_going_away) {
-		acpi_unlock_hp_context();
-		return;
+	adev = acpi_bus_get_acpi_device(handle);
+	if (adev) {
+		acpiphp_hotplug_event(adev, type);
+		acpi_bus_put_acpi_device(adev);
 	}
-	get_bridge(context->func.parent);
-	acpiphp_put_context(context);
-	acpi_unlock_hp_context();
-
-	hotplug_event(type, context);
-
-	put_bridge(context->func.parent);
 }
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
@@ -397,25 +371,23 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-						     handle_hotplug_event,
-						     context);
-		if (ACPI_FAILURE(status))
-			acpi_handle_err(handle,
-					"failed to install notify handler\n");
-	}
+	if (!(newfunc->flags & FUNC_HAS_DCK))
+		acpi_install_hotplug_notify_handler(handle, NULL);
 
 	return AE_OK;
 }
 
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
 {
+	struct acpi_device *adev = acpi_bus_get_acpi_device(handle);
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
 
+	if (!adev)
+		return NULL;
+
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
+	context = acpiphp_get_context(adev);
 	if (context) {
 		bridge = context->bridge;
 		if (bridge)
@@ -424,6 +396,7 @@ static struct acpiphp_bridge *acpiphp_ha
 		acpiphp_put_context(context);
 	}
 	acpi_unlock_hp_context();
+	acpi_bus_put_acpi_device(adev);
 	return bridge;
 }
 
@@ -431,7 +404,6 @@ static void cleanup_bridge(struct acpiph
 {
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
-	acpi_status status;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
@@ -440,13 +412,8 @@ static void cleanup_bridge(struct acpiph
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
 
-			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(handle,
-							ACPI_SYSTEM_NOTIFY,
-							handle_hotplug_event);
-				if (ACPI_FAILURE(status))
-					pr_err("failed to remove notify handler\n");
-			}
+			if (!(func->flags & FUNC_HAS_DCK))
+				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
@@ -814,7 +781,7 @@ static int acpiphp_disable_and_eject_slo
 
 static void hotplug_event(u32 type, struct acpiphp_context *context)
 {
-	acpi_handle handle = context->adev->handle;
+	acpi_handle handle = context->hp.self->handle;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
@@ -866,87 +833,24 @@ static void hotplug_event(u32 type, stru
 		put_bridge(bridge);
 }
 
-static void hotplug_event_work(void *data, u32 type)
-{
-	struct acpiphp_context *context = data;
-
-	acpi_scan_lock_acquire();
-
-	hotplug_event(type, context);
-
-	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(context->adev->handle, type,
-				  ACPI_OST_SC_SUCCESS, NULL);
-	put_bridge(context->func.parent);
-}
-
-/**
- * handle_hotplug_event - handle ACPI hotplug event
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @data: pointer to acpiphp_context structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type)
 {
 	struct acpiphp_context *context;
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-	acpi_status status;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
-		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
 
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->adev->handle != handle)
-	    || context->func.parent->is_going_away)
-		goto err_out;
-
-	get_bridge(context->func.parent);
-	acpiphp_put_context(context);
-	status = acpi_hotplug_execute(hotplug_event_work, context, type);
-	if (ACPI_SUCCESS(status)) {
+	context = acpiphp_get_context(adev);
+	if (!context || context->func.parent->is_going_away) {
 		acpi_unlock_hp_context();
-		return;
+		return -ENODATA;
 	}
-	put_bridge(context->func.parent);
-
- err_out:
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
 	acpi_unlock_hp_context();
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
+	hotplug_event(type, context);
+
+	put_bridge(context->func.parent);
+	return 0;
 }
 
 /**
@@ -999,7 +903,7 @@ void acpiphp_enumerate_slots(struct pci_
 		 * bridge is not interesting to us either.
 		 */
 		acpi_lock_hp_context();
-		context = acpiphp_get_context(handle);
+		context = acpiphp_get_context(adev);
 		if (!context) {
 			acpi_unlock_hp_context();
 			put_device(&bus->dev);
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -137,6 +137,16 @@ struct acpi_scan_handler {
 };
 
 /*
+ * ACPI Hotplug Context
+ * --------------------
+ */
+
+struct acpi_hotplug_context {
+	struct acpi_device *self;
+	int (*event)(struct acpi_device *, u32);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -329,6 +339,7 @@ struct acpi_device {
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
 	struct acpi_scan_handler *handler;
+	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
@@ -351,6 +362,15 @@ static inline void acpi_set_device_statu
 	*((u32 *)&adev->status) = sta;
 }
 
+static inline void acpi_set_hp_context(struct acpi_device *adev,
+				       struct acpi_hotplug_context *hp,
+				       int (*event)(struct acpi_device *, u32))
+{
+	hp->self = adev;
+	hp->event = event;
+	adev->hp = hp;
+}
+
 /* acpi_device.dev.bus == &acpi_bus_type */
 extern struct bus_type acpi_bus_type;
 
@@ -425,6 +445,8 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver


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

* [PATCH 21/24][Resend] ACPI / hotplug / PCI: Rework the handling of eject requests
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (19 preceding siblings ...)
  2014-02-03 23:37       ` [PATCH 20/24][Update] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
@ 2014-02-03 23:38       ` Rafael J. Wysocki
  2014-02-03 23:39       ` [PATCH 22/24][Resend] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
                         ` (3 subsequent siblings)
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:38 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

To avoid the need to install a hotplug notify handler for each ACPI
namespace node representing a device and having a matching scan
handler, move the check whether or not the ejection of the given
device is enabled through its scan handler from acpi_hotplug_notify_cb()
to acpi_generic_hotplug_event().  Also, move the execution of
ACPI_OST_SC_EJECT_IN_PROGRESS _OST to acpi_generic_hotplug_event(),
because in acpi_hotplug_notify_cb() or in acpi_eject_store() we really
don't know whether or not the eject is going to be in progress (for
example, acpi_hotplug_execute() may still fail without queuing up the
work item).

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/acpi/scan.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -459,6 +459,12 @@ static int acpi_generic_hotplug_event(st
 		return acpi_scan_device_check(adev);
 	case ACPI_NOTIFY_EJECT_REQUEST:
 	case ACPI_OST_EC_OSPM_EJECT:
+		if (adev->handler && !adev->handler->hotplug.enabled) {
+			dev_info(&adev->dev, "Eject disabled\n");
+			return -EPERM;
+		}
+		acpi_evaluate_hotplug_ost(adev->handle, ACPI_NOTIFY_EJECT_REQUEST,
+					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		return acpi_scan_hot_remove(adev);
 	}
 	return -EINVAL;
@@ -483,6 +489,10 @@ static void acpi_device_hotplug(void *da
 
 	if (adev->handler) {
 		error = acpi_generic_hotplug_event(adev, src);
+		if (error == -EPERM) {
+			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
+			goto err_out;
+		}
 	} else {
 		int (*event)(struct acpi_device *, u32);
 
@@ -512,7 +522,6 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_scan_handler *handler = data;
 	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
@@ -528,13 +537,6 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (handler && !handler->hotplug.enabled) {
-			acpi_handle_err(handle, "Eject disabled\n");
-			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto out;
-		}
-		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
-					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
@@ -632,8 +634,6 @@ acpi_eject_store(struct device *d, struc
 	if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
 		return -ENODEV;
 
-	acpi_evaluate_hotplug_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
-				  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 	get_device(&acpi_device->dev);
 	status = acpi_hotplug_execute(acpi_device_hotplug, acpi_device,
 				      ACPI_OST_EC_OSPM_EJECT);


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

* [PATCH 22/24][Resend] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (20 preceding siblings ...)
  2014-02-03 23:38       ` [PATCH 21/24][Resend] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
@ 2014-02-03 23:39       ` Rafael J. Wysocki
  2014-02-06 13:09         ` [Update][PATCH 22/24] " Rafael J. Wysocki
  2014-02-03 23:40       ` [PATCH 23/24][Update] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
                         ` (2 subsequent siblings)
  24 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:39 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Since acpi_hotplug_notify_cb() does not use its data argument any
more, the second argument of acpi_install_hotplug_notify_handler()
can be dropped, so do that and update its callers accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/acpi/scan.c                |    6 +++---
 drivers/pci/hotplug/acpiphp_glue.c |    2 +-
 include/acpi/acpi_bus.h            |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -577,10 +577,10 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+void acpi_install_hotplug_notify_handler(acpi_handle handle)
 {
 	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, data);
+				    acpi_hotplug_notify_cb, NULL);
 }
 
 void acpi_remove_hotplug_notify_handler(acpi_handle handle)
@@ -2048,7 +2048,7 @@ static void acpi_scan_init_hotplug(acpi_
 	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
 		if (handler) {
-			acpi_install_hotplug_notify_handler(handle, handler);
+			acpi_install_hotplug_notify_handler(handle);
 			break;
 		}
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -372,7 +372,7 @@ static acpi_status register_slot(acpi_ha
 
 	/* install notify handler */
 	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle, NULL);
+		acpi_install_hotplug_notify_handler(handle);
 
 	return AE_OK;
 }
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -445,7 +445,7 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_install_hotplug_notify_handler(acpi_handle handle);
 void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**


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

* [PATCH 23/24][Update] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (21 preceding siblings ...)
  2014-02-03 23:39       ` [PATCH 22/24][Resend] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-02-03 23:40       ` Rafael J. Wysocki
  2014-02-06 13:10         ` [Update][PATCH 23/24] " Rafael J. Wysocki
  2014-02-03 23:41       ` [PATCH 24/24][New] ACPI / hotplug / PCI: Rework acpiphp_check_host_bridge() Rafael J. Wysocki
  2014-02-05 10:14       ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Mika Westerberg
  24 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:40 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Since acpi_bus_notify() is executed on all notifications for all
devices anyway, make it execute acpi_device_hotplug() for all
hotplug events instead of installing notify handlers pointing to
the same function for all hotplug devices.

This change reduces both the size and complexity of ACPI-based device
hotplug code.  Moreover, since acpi_device_hotplug() only does
significant things for devices that have either an ACPI scan handler,
or a hotplug context with .eject() defined, and those devices
had notify handlers pointing to acpi_hotplug_notify_cb() installed
before anyway, this modification shouldn't change functionality.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/bus.c                 |   61 +++++++++++++---------
 drivers/acpi/internal.h            |    1 
 drivers/acpi/scan.c                |  101 -------------------------------------
 drivers/pci/hotplug/acpiphp.h      |    1 
 drivers/pci/hotplug/acpiphp_glue.c |   24 ++++----
 include/acpi/acpi_bus.h            |    2 
 6 files changed, 53 insertions(+), 137 deletions(-)

Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -340,62 +340,77 @@ static void acpi_bus_osc_support(void)
  */
 static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_device *device;
+	struct acpi_device *adev;
 	struct acpi_driver *driver;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
-			  type, handle));
+	acpi_status status;
+	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
 	switch (type) {
-
 	case ACPI_NOTIFY_BUS_CHECK:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n");
 		break;
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
 		/* TBD: Exactly what does 'light' mean? */
 		break;
 
 	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		/* TBD */
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
 		break;
 
 	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		/* TBD */
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
 		break;
 
 	case ACPI_NOTIFY_POWER_FAULT:
-		/* TBD */
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received unknown/unsupported notification [%08x]\n",
-				  type));
-		break;
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto err;
 	}
 
-	device = acpi_bus_get_acpi_device(handle);
-	if (device) {
-		driver = device->driver;
-		if (driver && driver->ops.notify &&
-		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
-			driver->ops.notify(device, type);
+	adev = acpi_bus_get_acpi_device(handle);
+	if (!adev)
+		goto err;
+
+	driver = adev->driver;
+	if (driver && driver->ops.notify &&
+	    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
+		driver->ops.notify(adev, type);
 
-		acpi_bus_put_acpi_device(device);
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+	case ACPI_NOTIFY_DEVICE_CHECK:
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
+		if (ACPI_SUCCESS(status))
+			return;
+	default:
+		break;
 	}
+	acpi_bus_put_acpi_device(adev);
+	return;
+
+ err:
+	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
 /* --------------------------------------------------------------------------
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -73,6 +73,7 @@ static inline void acpi_lpss_init(void)
 #endif
 
 bool acpi_queue_hotplug_work(struct work_struct *work);
+void acpi_device_hotplug(void *data, u32 src);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
 
 /* --------------------------------------------------------------------------
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -470,7 +470,7 @@ static int acpi_generic_hotplug_event(st
 	return -EINVAL;
 }
 
-static void acpi_device_hotplug(void *data, u32 src)
+void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
@@ -520,75 +520,6 @@ static void acpi_device_hotplug(void *da
 	unlock_device_hotplug();
 }
 
-static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
-{
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-	struct acpi_device *adev;
-	acpi_status status;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
-
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-	adev = acpi_bus_get_acpi_device(handle);
-	if (!adev)
-		goto out;
-
-	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
-	if (ACPI_SUCCESS(status))
-		return;
-
-	acpi_bus_put_acpi_device(adev);
-
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-}
-
-void acpi_install_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, NULL);
-}
-
-void acpi_remove_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				   acpi_hotplug_notify_cb);
-}
-
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -2029,34 +1960,6 @@ void acpi_scan_hotplug_enabled(struct ac
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
-{
-	struct acpi_device_pnp pnp = {};
-	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
-
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
-
-	if (!pnp.type.hardware_id)
-		goto out;
-
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
-		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (handler) {
-			acpi_install_hotplug_notify_handler(handle);
-			break;
-		}
-	}
-
-out:
-	acpi_free_pnp_ids(&pnp);
-}
-
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 				      void *not_used, void **return_value)
 {
@@ -2078,8 +1981,6 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -293,7 +293,6 @@ static acpi_status register_slot(acpi_ha
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	acpi_unlock_hp_context();
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -301,8 +300,14 @@ static acpi_status register_slot(acpi_ha
 	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
+	/*
+	 * Dock stations' notify handler should be used for dock devices instead
+	 * of the common one, so clear hp.event in their contexts.
+	 */
 	if (acpi_has_method(handle, "_DCK"))
-		newfunc->flags |= FUNC_HAS_DCK;
+		context->hp.event = NULL;
+
+	acpi_unlock_hp_context();
 
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
@@ -370,10 +375,6 @@ static acpi_status register_slot(acpi_ha
 			pr_debug("failed to register dock device\n");
 	}
 
-	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle);
-
 	return AE_OK;
 }
 
@@ -407,13 +408,14 @@ static void cleanup_bridge(struct acpiph
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
-			acpi_handle handle = func_to_handle(func);
+			struct acpi_device *adev = func_to_acpi_device(func);
 
-			if (is_dock_device(handle))
-				unregister_hotplug_dock_device(handle);
+			if (is_dock_device(adev->handle))
+				unregister_hotplug_dock_device(adev->handle);
 
-			if (!(func->flags & FUNC_HAS_DCK))
-				acpi_remove_hotplug_notify_handler(handle);
+			acpi_lock_hp_context();
+			adev->hp->event = NULL;
+			acpi_unlock_hp_context();
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -445,8 +445,6 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle);
-void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -167,7 +167,6 @@ struct acpiphp_attention_info
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 


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

* [PATCH 24/24][New] ACPI / hotplug / PCI: Rework acpiphp_check_host_bridge()
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (22 preceding siblings ...)
  2014-02-03 23:40       ` [PATCH 23/24][Update] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
@ 2014-02-03 23:41       ` Rafael J. Wysocki
  2014-02-05 10:14       ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Mika Westerberg
  24 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-03 23:41 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

Since the only existing caller of acpiphp_check_host_bridge(),
which is acpi_pci_root_scan_dependent(), already has a struct
acpi_device pointer needed to obtain the ACPIPHP context, it
doesn't make sense to execute acpi_bus_get_device() on its
handle in acpiphp_handle_to_bridge() just in order to get that
pointer back.

For this reason, modify acpiphp_check_host_bridge() to take
a struct acpi_device pointer as its argument and rearrange the
code accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/pci_root.c            |    2 +-
 drivers/pci/hotplug/acpiphp_glue.c |   11 +++--------
 include/linux/pci-acpi.h           |    4 ++--
 3 files changed, 6 insertions(+), 11 deletions(-)

Index: linux-pm/include/linux/pci-acpi.h
===================================================================
--- linux-pm.orig/include/linux/pci-acpi.h
+++ linux-pm/include/linux/pci-acpi.h
@@ -59,12 +59,12 @@ static inline void acpi_pci_slot_remove(
 void acpiphp_init(void);
 void acpiphp_enumerate_slots(struct pci_bus *bus);
 void acpiphp_remove_slots(struct pci_bus *bus);
-void acpiphp_check_host_bridge(acpi_handle handle);
+void acpiphp_check_host_bridge(struct acpi_device *adev);
 #else
 static inline void acpiphp_init(void) { }
 static inline void acpiphp_enumerate_slots(struct pci_bus *bus) { }
 static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
-static inline void acpiphp_check_host_bridge(acpi_handle handle) { }
+static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { }
 #endif
 
 #else	/* CONFIG_ACPI */
Index: linux-pm/drivers/acpi/pci_root.c
===================================================================
--- linux-pm.orig/drivers/acpi/pci_root.c
+++ linux-pm/drivers/acpi/pci_root.c
@@ -51,7 +51,7 @@ static void acpi_pci_root_remove(struct
 
 static int acpi_pci_root_scan_dependent(struct acpi_device *adev)
 {
-	acpiphp_check_host_bridge(adev->handle);
+	acpiphp_check_host_bridge(adev);
 	return 0;
 }
 
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -378,15 +378,11 @@ static acpi_status register_slot(acpi_ha
 	return AE_OK;
 }
 
-static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
+static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev)
 {
-	struct acpi_device *adev = acpi_bus_get_acpi_device(handle);
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
 
-	if (!adev)
-		return NULL;
-
 	acpi_lock_hp_context();
 	context = acpiphp_get_context(adev);
 	if (context) {
@@ -397,7 +393,6 @@ static struct acpiphp_bridge *acpiphp_ha
 		acpiphp_put_context(context);
 	}
 	acpi_unlock_hp_context();
-	acpi_bus_put_acpi_device(adev);
 	return bridge;
 }
 
@@ -764,11 +759,11 @@ static void acpiphp_sanitize_bus(struct
  * ACPI event handlers
  */
 
-void acpiphp_check_host_bridge(acpi_handle handle)
+void acpiphp_check_host_bridge(struct acpi_device *adev)
 {
 	struct acpiphp_bridge *bridge;
 
-	bridge = acpiphp_handle_to_bridge(handle);
+	bridge = acpiphp_dev_to_bridge(adev);
 	if (bridge) {
 		pci_lock_rescan_remove();
 


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

* Re: [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core
  2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
                         ` (23 preceding siblings ...)
  2014-02-03 23:41       ` [PATCH 24/24][New] ACPI / hotplug / PCI: Rework acpiphp_check_host_bridge() Rafael J. Wysocki
@ 2014-02-05 10:14       ` Mika Westerberg
  2014-02-05 10:59         ` Rafael J. Wysocki
  24 siblings, 1 reply; 100+ messages in thread
From: Mika Westerberg @ 2014-02-05 10:14 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Tue, Feb 04, 2014 at 12:12:26AM +0100, Rafael J. Wysocki wrote:
> As I said previously, I have found two concurrency-related bugs more in ACPIPHP
> and I needed to put fixes for those bugs at the top of the series (after previous
> [1-2/13] and the patch at https://patchwork.kernel.org/patch/3567701/).  For this
> reason, I also had to rebase the ACPI/PCI hotplug consolidation patchset
> (https://lkml.org/lkml/2014/2/2/87) which got a few additional cosmetic changes too.
> 
> The following is a combination of the two series with one patch dropped (it would
> conflict with [4-5/24]) and a few patches added.  It is on top of 3.14-rc1.
> 
> Patches [1-5/24], that are regarded as 3.14-rc2 material, are on the bleeding-edge
> branch of linux-pm.git.  The remaining patches will show up in bleeding-edge
> shortly.
> 
> [1/24] Remove entries from bus->devices in reverse order (in ACPIPHP).
> [2/24] Move PCI rescan-remove locking to hotplug_event().
> [3/24] Scan root bus under the PCI rescan-remove lock
> [4/24] Fix race in handle_hotplug_event() related to concurrent bridge removal.
> [5/24] Fix race in hotplug_event() related to dock events and concurrent bridge removal.
> [6/24] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
> [7/24] Fix up two kerneldoc comments in acpiphp_glue.c.
> [8/24] Get rid of an unnecessary label in register_slot().
> [9/24] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
> [10/24] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
> [11/24] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
> [12/24] Drop acpiphp_bus_add() (which has only one user).
> [13/24] Drop crit_sect mutexes (that are redundant).
> [14/24] Clean up the usage of the slot variable in hotplug_event().
> [15/24] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
> [16/24] Do not pass ACPI handle to hotplug_event().
> [17/24] Add a new function to ACPICA allowing a callback to be executed under the
>         namespace mutex after calling acpi_ns_get_attached_data().
> [18/24] Use the new ACPICA's function to fix a couple of potential races related
>         to ACPI notifies.
> [19/24] Move the hotplug context lock definition to the ACPI core (from ACPIPHP).
> [20/24] Consolidate ACPI hotplug signaling for PCI and ACPI core.
> [21/24] Rework the handling of eject requests in the ACPI core.
> [22/24] Simplify a routine for installing hotplug notify handlers.
> [23/24] Dispatch ACPI hotplug notifications for "core" devices and PCI from
>         acpi_bus_notify().
> [24/24] Pass struct acpi_device pointer to acpiphp_check_host_bridge().

Tried your latest bleeding-edge branch (it seemed to have all the above
patches) on my TBT test machines (Acer Aspire S5, Intel NUC and Intel
DZ77RE-75K). TBT hotplug works nicely, no deadlocks or anything like that.

Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

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

* Re: [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core
  2014-02-05 10:14       ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Mika Westerberg
@ 2014-02-05 10:59         ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-05 10:59 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: ACPI Devel Maling List, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

On Wednesday, February 05, 2014 12:14:05 PM Mika Westerberg wrote:
> On Tue, Feb 04, 2014 at 12:12:26AM +0100, Rafael J. Wysocki wrote:
> > As I said previously, I have found two concurrency-related bugs more in ACPIPHP
> > and I needed to put fixes for those bugs at the top of the series (after previous
> > [1-2/13] and the patch at https://patchwork.kernel.org/patch/3567701/).  For this
> > reason, I also had to rebase the ACPI/PCI hotplug consolidation patchset
> > (https://lkml.org/lkml/2014/2/2/87) which got a few additional cosmetic changes too.
> > 
> > The following is a combination of the two series with one patch dropped (it would
> > conflict with [4-5/24]) and a few patches added.  It is on top of 3.14-rc1.
> > 
> > Patches [1-5/24], that are regarded as 3.14-rc2 material, are on the bleeding-edge
> > branch of linux-pm.git.  The remaining patches will show up in bleeding-edge
> > shortly.
> > 
> > [1/24] Remove entries from bus->devices in reverse order (in ACPIPHP).
> > [2/24] Move PCI rescan-remove locking to hotplug_event().
> > [3/24] Scan root bus under the PCI rescan-remove lock
> > [4/24] Fix race in handle_hotplug_event() related to concurrent bridge removal.
> > [5/24] Fix race in hotplug_event() related to dock events and concurrent bridge removal.
> > [6/24] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
> > [7/24] Fix up two kerneldoc comments in acpiphp_glue.c.
> > [8/24] Get rid of an unnecessary label in register_slot().
> > [9/24] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
> > [10/24] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
> > [11/24] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
> > [12/24] Drop acpiphp_bus_add() (which has only one user).
> > [13/24] Drop crit_sect mutexes (that are redundant).
> > [14/24] Clean up the usage of the slot variable in hotplug_event().
> > [15/24] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
> > [16/24] Do not pass ACPI handle to hotplug_event().
> > [17/24] Add a new function to ACPICA allowing a callback to be executed under the
> >         namespace mutex after calling acpi_ns_get_attached_data().
> > [18/24] Use the new ACPICA's function to fix a couple of potential races related
> >         to ACPI notifies.
> > [19/24] Move the hotplug context lock definition to the ACPI core (from ACPIPHP).
> > [20/24] Consolidate ACPI hotplug signaling for PCI and ACPI core.
> > [21/24] Rework the handling of eject requests in the ACPI core.
> > [22/24] Simplify a routine for installing hotplug notify handlers.
> > [23/24] Dispatch ACPI hotplug notifications for "core" devices and PCI from
> >         acpi_bus_notify().
> > [24/24] Pass struct acpi_device pointer to acpiphp_check_host_bridge().
> 
> Tried your latest bleeding-edge branch (it seemed to have all the above
> patches) on my TBT test machines (Acer Aspire S5, Intel NUC and Intel
> DZ77RE-75K).

Yes, bleeding-edge already has the patches (linux-next has them too now for
that matter).

> TBT hotplug works nicely, no deadlocks or anything like that.
> 
> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Thanks!

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

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

* [Update][PATCH 20/24] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
  2014-02-03 23:37       ` [PATCH 20/24][Update] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
@ 2014-02-06 13:07         ` Rafael J. Wysocki
  2014-02-06 23:35           ` [Update 2x][PATCH " Rafael J. Wysocki
  0 siblings, 1 reply; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-06 13:07 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its
hotplug context objects directly to ACPI namespace nodes representing
hotplug devices.  However, after recent changes causing struct
acpi_device to be created for every namespace node representing a
device (regardless of its status), that is not necessary any more.
Moreover, it's vulnerable to the theoretical issue that the ACPI
handle passed in the context between handle_hotplug_event() and
hotplug_event_work() may become invalid in the meantime (as a
result of a concurrent table unload).

In principle, this issue might be addressed by adding a non-empty
release handler for ACPIPHP hotplug context objects analogous to
acpi_scan_drop_device(), but that would duplicate the code in that
function and in acpi_device_del_work_fn().  For this reason, it's
better to modify ACPIPHP to attach its device hotplug contexts to
struct device objects representing hotplug devices and make it
use acpi_hotplug_notify_cb() as its notify handler.  At the same
time, acpi_device_hotplug() can be modified to dispatch the new
.hp.event() callback pointing to acpiphp_hotplug_event() from ACPI
device objects associated with PCI devices or use the generic
ACPI device hotplug code for device objects with matching scan
handlers.

This allows the existing code duplication between ACPIPHP and the
ACPI core to be reduced too and makes further ACPI-based device
hotplug consolidation possible.

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

The previous version would cause hotplug notifications to be ignored for
devices with matching scan handlers, but without any scan handlers attached
to them, so the would not get any hotplug notifications after acpi_bus_trim().

The fix is to introduce a flag meaning "this device should get hotplug
notifications" and set it when we know there's a matching scan handler
for a device.

Thanks,
Rafael

---
 drivers/acpi/scan.c                |  137 ++++++++++++++++++++----------
 drivers/pci/hotplug/acpiphp.h      |    9 +-
 drivers/pci/hotplug/acpiphp_glue.c |  164 +++++++------------------------------
 include/acpi/acpi_bus.h            |   25 +++++
 4 files changed, 154 insertions(+), 181 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -450,43 +450,61 @@ static int acpi_scan_bus_check(struct ac
 	return 0;
 }
 
+static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
+{
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		return acpi_scan_bus_check(adev);
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		return acpi_scan_device_check(adev);
+	case ACPI_NOTIFY_EJECT_REQUEST:
+	case ACPI_OST_EC_OSPM_EJECT:
+		return acpi_scan_hot_remove(adev);
+	}
+	return -EINVAL;
+}
+
 static void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
-	int error;
+	int error = -ENODEV;
 
 	lock_device_hotplug();
 	mutex_lock(&acpi_scan_lock);
 
 	/*
 	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it may have become invalid before
+	 * are holding acpi_scan_lock, but it might have become invalid before
 	 * that lock was acquired.
 	 */
 	if (adev->handle == INVALID_ACPI_HANDLE)
-		goto out;
+		goto err_out;
 
-	switch (src) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		error = acpi_scan_bus_check(adev);
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		error = acpi_scan_device_check(adev);
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-	case ACPI_OST_EC_OSPM_EJECT:
-		error = acpi_scan_hot_remove(adev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
+	if (adev->flags.hotplug_notify) {
+		error = acpi_generic_hotplug_event(adev, src);
+	} else {
+		int (*event)(struct acpi_device *, u32);
+
+		acpi_lock_hp_context();
+		event = adev->hp ? adev->hp->event : NULL;
+		acpi_unlock_hp_context();
+		/*
+		 * There may be additional notify handlers for device objects
+		 * without the .event() callback, so ignore them here.
+		 */
+		if (event)
+			error = event(adev, src);
+		else
+			goto out;
 	}
 	if (!error)
 		ost_code = ACPI_OST_SC_SUCCESS;
 
- out:
+ err_out:
 	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
+
+ out:
 	acpi_bus_put_acpi_device(adev);
 	mutex_unlock(&acpi_scan_lock);
 	unlock_device_hotplug();
@@ -494,8 +512,8 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_scan_handler *handler = data;
+	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
 
@@ -503,26 +521,49 @@ static void acpi_hotplug_notify_cb(acpi_
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (!handler->hotplug.enabled) {
+		if (handler && !handler->hotplug.enabled) {
 			acpi_handle_err(handle, "Eject disabled\n");
 			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto err_out;
+			goto out;
 		}
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
-	default:
-		/* non-hotplug event; possibly handled by other handler */
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
 		return;
+
+	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_POWER_FAULT:
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
+		goto out;
+
+	default:
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto out;
 	}
+
+	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	adev = acpi_bus_get_acpi_device(handle);
 	if (!adev)
-		goto err_out;
+		goto out;
 
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
@@ -530,10 +571,22 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	acpi_bus_put_acpi_device(adev);
 
- err_out:
+ out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+{
+	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				    acpi_hotplug_notify_cb, data);
+}
+
+void acpi_remove_hotplug_notify_handler(acpi_handle handle)
+{
+	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				   acpi_hotplug_notify_cb);
+}
+
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1976,33 +2029,21 @@ void acpi_scan_hotplug_enabled(struct ac
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
+static void acpi_scan_init_hotplug(struct acpi_device *adev)
 {
-	struct acpi_device_pnp pnp = {};
 	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
-
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
 
-	if (!pnp.type.hardware_id)
-		goto out;
+	list_for_each_entry(hwid, &adev->pnp.ids, list) {
+		struct acpi_scan_handler *handler;
 
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (handler) {
-			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					acpi_hotplug_notify_cb, handler);
-			break;
-		}
-	}
+		if (!handler)
+			continue;
 
-out:
-	acpi_free_pnp_ids(&pnp);
+		acpi_install_hotplug_notify_handler(adev->handle, handler);
+		adev->flags.hotplug_notify = true;
+		break;
+	}
 }
 
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
@@ -2026,12 +2067,12 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
 
+	acpi_scan_init_hotplug(device);
+
  out:
 	if (!*return_value)
 		*return_value = device;
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -116,12 +116,17 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
+	struct acpi_hotplug_context hp;
 	struct acpiphp_func func;
-	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
 
+static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
+{
+	return container_of(hp, struct acpiphp_context, hp);
+}
+
 static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
 {
 	return container_of(func, struct acpiphp_context, func);
@@ -129,7 +134,7 @@ static inline struct acpiphp_context *fu
 
 static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
 {
-	return func_to_context(func)->adev;
+	return func_to_context(func)->hp.self;
 }
 
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -59,17 +59,12 @@
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
 static void hotplug_event(u32 type, struct acpiphp_context *context);
 static void free_bridge(struct kref *kref);
 
-static void acpiphp_context_handler(acpi_handle handle, void *context)
-{
-	/* Intentionally empty. */
-}
-
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
  * @adev: ACPI device object to create the context for.
@@ -79,39 +74,27 @@ static void acpiphp_context_handler(acpi
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
-	acpi_status status;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return NULL;
 
-	context->adev = adev;
 	context->refcount = 1;
-	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
-	if (ACPI_FAILURE(status)) {
-		kfree(context);
-		return NULL;
-	}
+	acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_event);
 	return context;
 }
 
 /**
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
- * @handle: ACPI object handle to get the context for.
+ * @adev: ACPI device object to get the context for.
  *
  * Call under acpi_hp_context_lock.
  */
-static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = NULL;
-	acpi_status status;
-	void *data;
+	struct acpiphp_context *context = to_acpiphp_context(adev->hp);
 
-	status = acpi_get_data(handle, acpiphp_context_handler, &data);
-	if (ACPI_SUCCESS(status)) {
-		context = data;
-		context->refcount++;
-	}
+	context->refcount++;
 	return context;
 }
 
@@ -129,7 +112,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
+	context->hp.self->hp = NULL;
 	kfree(context);
 }
 
@@ -211,22 +194,13 @@ static void post_dock_fixups(acpi_handle
 
 static void dock_event(acpi_handle handle, u32 type, void *data)
 {
-	struct acpiphp_context *context;
+	struct acpi_device *adev;
 
-	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->adev->handle != handle)
-	    || context->func.parent->is_going_away) {
-		acpi_unlock_hp_context();
-		return;
+	adev = acpi_bus_get_acpi_device(handle);
+	if (adev) {
+		acpiphp_hotplug_event(adev, type);
+		acpi_bus_put_acpi_device(adev);
 	}
-	get_bridge(context->func.parent);
-	acpiphp_put_context(context);
-	acpi_unlock_hp_context();
-
-	hotplug_event(type, context);
-
-	put_bridge(context->func.parent);
 }
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
@@ -397,25 +371,23 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-						     handle_hotplug_event,
-						     context);
-		if (ACPI_FAILURE(status))
-			acpi_handle_err(handle,
-					"failed to install notify handler\n");
-	}
+	if (!(newfunc->flags & FUNC_HAS_DCK))
+		acpi_install_hotplug_notify_handler(handle, NULL);
 
 	return AE_OK;
 }
 
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
 {
+	struct acpi_device *adev = acpi_bus_get_acpi_device(handle);
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
 
+	if (!adev)
+		return NULL;
+
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
+	context = acpiphp_get_context(adev);
 	if (context) {
 		bridge = context->bridge;
 		if (bridge)
@@ -424,6 +396,7 @@ static struct acpiphp_bridge *acpiphp_ha
 		acpiphp_put_context(context);
 	}
 	acpi_unlock_hp_context();
+	acpi_bus_put_acpi_device(adev);
 	return bridge;
 }
 
@@ -431,7 +404,6 @@ static void cleanup_bridge(struct acpiph
 {
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
-	acpi_status status;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
@@ -440,13 +412,8 @@ static void cleanup_bridge(struct acpiph
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
 
-			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(handle,
-							ACPI_SYSTEM_NOTIFY,
-							handle_hotplug_event);
-				if (ACPI_FAILURE(status))
-					pr_err("failed to remove notify handler\n");
-			}
+			if (!(func->flags & FUNC_HAS_DCK))
+				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
@@ -814,7 +781,7 @@ static int acpiphp_disable_and_eject_slo
 
 static void hotplug_event(u32 type, struct acpiphp_context *context)
 {
-	acpi_handle handle = context->adev->handle;
+	acpi_handle handle = context->hp.self->handle;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
@@ -866,87 +833,24 @@ static void hotplug_event(u32 type, stru
 		put_bridge(bridge);
 }
 
-static void hotplug_event_work(void *data, u32 type)
-{
-	struct acpiphp_context *context = data;
-
-	acpi_scan_lock_acquire();
-
-	hotplug_event(type, context);
-
-	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(context->adev->handle, type,
-				  ACPI_OST_SC_SUCCESS, NULL);
-	put_bridge(context->func.parent);
-}
-
-/**
- * handle_hotplug_event - handle ACPI hotplug event
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @data: pointer to acpiphp_context structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type)
 {
 	struct acpiphp_context *context;
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-	acpi_status status;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
-		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
 
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->adev->handle != handle)
-	    || context->func.parent->is_going_away)
-		goto err_out;
-
-	get_bridge(context->func.parent);
-	acpiphp_put_context(context);
-	status = acpi_hotplug_execute(hotplug_event_work, context, type);
-	if (ACPI_SUCCESS(status)) {
+	context = acpiphp_get_context(adev);
+	if (!context || context->func.parent->is_going_away) {
 		acpi_unlock_hp_context();
-		return;
+		return -ENODATA;
 	}
-	put_bridge(context->func.parent);
-
- err_out:
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
 	acpi_unlock_hp_context();
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
+	hotplug_event(type, context);
+
+	put_bridge(context->func.parent);
+	return 0;
 }
 
 /**
@@ -999,7 +903,7 @@ void acpiphp_enumerate_slots(struct pci_
 		 * bridge is not interesting to us either.
 		 */
 		acpi_lock_hp_context();
-		context = acpiphp_get_context(handle);
+		context = acpiphp_get_context(adev);
 		if (!context) {
 			acpi_unlock_hp_context();
 			put_device(&bus->dev);
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -137,6 +137,16 @@ struct acpi_scan_handler {
 };
 
 /*
+ * ACPI Hotplug Context
+ * --------------------
+ */
+
+struct acpi_hotplug_context {
+	struct acpi_device *self;
+	int (*event)(struct acpi_device *, u32);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -190,7 +200,8 @@ struct acpi_device_flags {
 	u32 initialized:1;
 	u32 visited:1;
 	u32 no_hotplug:1;
-	u32 reserved:24;
+	u32 hotplug_notify:1;
+	u32 reserved:23;
 };
 
 /* File System */
@@ -329,6 +340,7 @@ struct acpi_device {
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
 	struct acpi_scan_handler *handler;
+	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
@@ -351,6 +363,15 @@ static inline void acpi_set_device_statu
 	*((u32 *)&adev->status) = sta;
 }
 
+static inline void acpi_set_hp_context(struct acpi_device *adev,
+				       struct acpi_hotplug_context *hp,
+				       int (*event)(struct acpi_device *, u32))
+{
+	hp->self = adev;
+	hp->event = event;
+	adev->hp = hp;
+}
+
 /* acpi_device.dev.bus == &acpi_bus_type */
 extern struct bus_type acpi_bus_type;
 
@@ -425,6 +446,8 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver


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

* [Update][PATCH 22/24] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()
  2014-02-03 23:39       ` [PATCH 22/24][Resend] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
@ 2014-02-06 13:09         ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-06 13:09 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Subject: ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler()

Since acpi_hotplug_notify_cb() does not use its data argument any
more, the second argument of acpi_install_hotplug_notify_handler()
can be dropped, so do that and update its callers accordingly.

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

This one had to be updated after patch [20/24] had been updated.

Thanks,
Rafael

---
 drivers/acpi/scan.c                |    6 +++---
 drivers/pci/hotplug/acpiphp_glue.c |    2 +-
 include/acpi/acpi_bus.h            |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -577,10 +577,10 @@ static void acpi_hotplug_notify_cb(acpi_
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+void acpi_install_hotplug_notify_handler(acpi_handle handle)
 {
 	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, data);
+				    acpi_hotplug_notify_cb, NULL);
 }
 
 void acpi_remove_hotplug_notify_handler(acpi_handle handle)
@@ -2040,7 +2040,7 @@ static void acpi_scan_init_hotplug(struc
 		if (!handler)
 			continue;
 
-		acpi_install_hotplug_notify_handler(adev->handle, handler);
+		acpi_install_hotplug_notify_handler(adev->handle);
 		adev->flags.hotplug_notify = true;
 		break;
 	}
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -372,7 +372,7 @@ static acpi_status register_slot(acpi_ha
 
 	/* install notify handler */
 	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle, NULL);
+		acpi_install_hotplug_notify_handler(handle);
 
 	return AE_OK;
 }
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -446,7 +446,7 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_install_hotplug_notify_handler(acpi_handle handle);
 void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**


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

* [Update][PATCH 23/24] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify()
  2014-02-03 23:40       ` [PATCH 23/24][Update] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
@ 2014-02-06 13:10         ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-06 13:10 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Subject: ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify()

Since acpi_bus_notify() is executed on all notifications for all
devices anyway, make it execute acpi_device_hotplug() for all
hotplug events instead of installing notify handlers pointing to
the same function for all hotplug devices.

This change reduces both the size and complexity of ACPI-based device
hotplug code.  Moreover, since acpi_device_hotplug() only does
significant things for devices that have either an ACPI scan handler,
or a hotplug context with .eject() defined, and those devices
had notify handlers pointing to acpi_hotplug_notify_cb() installed
before anyway, this modification shouldn't change functionality.

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

This one had to be updated after patch [20/24] had been updated.

Thanks,
Rafael

---
 drivers/acpi/bus.c                 |   61 +++++++++++++++++----------
 drivers/acpi/internal.h            |    1 
 drivers/acpi/scan.c                |   81 ++-----------------------------------
 drivers/pci/hotplug/acpiphp.h      |    1 
 drivers/pci/hotplug/acpiphp_glue.c |   24 +++++-----
 include/acpi/acpi_bus.h            |    2 
 6 files changed, 57 insertions(+), 113 deletions(-)

Index: linux-pm/drivers/acpi/bus.c
===================================================================
--- linux-pm.orig/drivers/acpi/bus.c
+++ linux-pm/drivers/acpi/bus.c
@@ -340,62 +340,77 @@ static void acpi_bus_osc_support(void)
  */
 static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 {
-	struct acpi_device *device;
+	struct acpi_device *adev;
 	struct acpi_driver *driver;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
-			  type, handle));
+	acpi_status status;
+	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
 	switch (type) {
-
 	case ACPI_NOTIFY_BUS_CHECK:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_WAKE:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n");
 		break;
 
 	case ACPI_NOTIFY_EJECT_REQUEST:
-		/* TBD */
+		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
 		break;
 
 	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
+		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
 		/* TBD: Exactly what does 'light' mean? */
 		break;
 
 	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		/* TBD */
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
 		break;
 
 	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		/* TBD */
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
 		break;
 
 	case ACPI_NOTIFY_POWER_FAULT:
-		/* TBD */
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
 		break;
 
 	default:
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "Received unknown/unsupported notification [%08x]\n",
-				  type));
-		break;
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto err;
 	}
 
-	device = acpi_bus_get_acpi_device(handle);
-	if (device) {
-		driver = device->driver;
-		if (driver && driver->ops.notify &&
-		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
-			driver->ops.notify(device, type);
+	adev = acpi_bus_get_acpi_device(handle);
+	if (!adev)
+		goto err;
+
+	driver = adev->driver;
+	if (driver && driver->ops.notify &&
+	    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
+		driver->ops.notify(adev, type);
 
-		acpi_bus_put_acpi_device(device);
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+	case ACPI_NOTIFY_DEVICE_CHECK:
+	case ACPI_NOTIFY_EJECT_REQUEST:
+		status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
+		if (ACPI_SUCCESS(status))
+			return;
+	default:
+		break;
 	}
+	acpi_bus_put_acpi_device(adev);
+	return;
+
+ err:
+	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
 /* --------------------------------------------------------------------------
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -73,6 +73,7 @@ static inline void acpi_lpss_init(void)
 #endif
 
 bool acpi_queue_hotplug_work(struct work_struct *work);
+void acpi_device_hotplug(void *data, u32 src);
 bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent);
 
 /* --------------------------------------------------------------------------
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -470,7 +470,7 @@ static int acpi_generic_hotplug_event(st
 	return -EINVAL;
 }
 
-static void acpi_device_hotplug(void *data, u32 src)
+void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
@@ -520,75 +520,6 @@ static void acpi_device_hotplug(void *da
 	unlock_device_hotplug();
 }
 
-static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
-{
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-	struct acpi_device *adev;
-	acpi_status status;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
-		break;
-
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
-		break;
-
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
-
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-	adev = acpi_bus_get_acpi_device(handle);
-	if (!adev)
-		goto out;
-
-	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
-	if (ACPI_SUCCESS(status))
-		return;
-
-	acpi_bus_put_acpi_device(adev);
-
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-}
-
-void acpi_install_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				    acpi_hotplug_notify_cb, NULL);
-}
-
-void acpi_remove_hotplug_notify_handler(acpi_handle handle)
-{
-	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-				   acpi_hotplug_notify_cb);
-}
-
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -2037,12 +1968,10 @@ static void acpi_scan_init_hotplug(struc
 		struct acpi_scan_handler *handler;
 
 		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (!handler)
-			continue;
-
-		acpi_install_hotplug_notify_handler(adev->handle);
-		adev->flags.hotplug_notify = true;
-		break;
+		if (handler) {
+			adev->flags.hotplug_notify = true;
+			break;
+		}
 	}
 }
 
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -293,7 +293,6 @@ static acpi_status register_slot(acpi_ha
 	newfunc = &context->func;
 	newfunc->function = function;
 	newfunc->parent = bridge;
-	acpi_unlock_hp_context();
 
 	if (acpi_has_method(handle, "_EJ0"))
 		newfunc->flags = FUNC_HAS_EJ0;
@@ -301,8 +300,14 @@ static acpi_status register_slot(acpi_ha
 	if (acpi_has_method(handle, "_STA"))
 		newfunc->flags |= FUNC_HAS_STA;
 
+	/*
+	 * Dock stations' notify handler should be used for dock devices instead
+	 * of the common one, so clear hp.event in their contexts.
+	 */
 	if (acpi_has_method(handle, "_DCK"))
-		newfunc->flags |= FUNC_HAS_DCK;
+		context->hp.event = NULL;
+
+	acpi_unlock_hp_context();
 
 	/* search for objects that share the same slot */
 	list_for_each_entry(slot, &bridge->slots, node)
@@ -370,10 +375,6 @@ static acpi_status register_slot(acpi_ha
 			pr_debug("failed to register dock device\n");
 	}
 
-	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK))
-		acpi_install_hotplug_notify_handler(handle);
-
 	return AE_OK;
 }
 
@@ -407,13 +408,14 @@ static void cleanup_bridge(struct acpiph
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
-			acpi_handle handle = func_to_handle(func);
+			struct acpi_device *adev = func_to_acpi_device(func);
 
-			if (is_dock_device(handle))
-				unregister_hotplug_dock_device(handle);
+			if (is_dock_device(adev->handle))
+				unregister_hotplug_dock_device(adev->handle);
 
-			if (!(func->flags & FUNC_HAS_DCK))
-				acpi_remove_hotplug_notify_handler(handle);
+			acpi_lock_hp_context();
+			adev->hp->event = NULL;
+			acpi_unlock_hp_context();
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -446,8 +446,6 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
-void acpi_install_hotplug_notify_handler(acpi_handle handle);
-void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -167,7 +167,6 @@ struct acpiphp_attention_info
 
 #define FUNC_HAS_STA		(0x00000001)
 #define FUNC_HAS_EJ0		(0x00000002)
-#define FUNC_HAS_DCK            (0x00000004)
 
 /* function prototypes */
 


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

* [Update 2x][PATCH 20/24] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug
  2014-02-06 13:07         ` [Update][PATCH 20/24] " Rafael J. Wysocki
@ 2014-02-06 23:35           ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-06 23:35 UTC (permalink / raw)
  To: ACPI Devel Maling List
  Cc: Mika Westerberg, Bjorn Helgaas, Aaron Lu,
	Linux Kernel Mailing List, Linux PCI

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

The ACPI-based PCI hotplug (ACPIPHP) code currently attaches its
hotplug context objects directly to ACPI namespace nodes representing
hotplug devices.  However, after recent changes causing struct
acpi_device to be created for every namespace node representing a
device (regardless of its status), that is not necessary any more.
Moreover, it's vulnerable to the theoretical issue that the ACPI
handle passed in the context between handle_hotplug_event() and
hotplug_event_work() may become invalid in the meantime (as a
result of a concurrent table unload).

In principle, this issue might be addressed by adding a non-empty
release handler for ACPIPHP hotplug context objects analogous to
acpi_scan_drop_device(), but that would duplicate the code in that
function and in acpi_device_del_work_fn().  For this reason, it's
better to modify ACPIPHP to attach its device hotplug contexts to
struct device objects representing hotplug devices and make it
use acpi_hotplug_notify_cb() as its notify handler.  At the same
time, acpi_device_hotplug() can be modified to dispatch the new
.hp.event() callback pointing to acpiphp_hotplug_event() from ACPI
device objects associated with PCI devices or use the generic
ACPI device hotplug code for device objects with matching scan
handlers.

This allows the existing code duplication between ACPIPHP and the
ACPI core to be reduced too and makes further ACPI-based device
hotplug consolidation possible.

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

This update fixes the bug reported here: https://lkml.org/lkml/2014/2/6/212

None of the other patches in the series need to be updated because of that.

Thanks!

---
 drivers/acpi/scan.c                |  137 +++++++++++++++++++-----------
 drivers/pci/hotplug/acpiphp.h      |    9 +
 drivers/pci/hotplug/acpiphp_glue.c |  168 ++++++++-----------------------------
 include/acpi/acpi_bus.h            |   25 +++++
 4 files changed, 158 insertions(+), 181 deletions(-)

Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -450,43 +450,61 @@ static int acpi_scan_bus_check(struct ac
 	return 0;
 }
 
+static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
+{
+	switch (type) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		return acpi_scan_bus_check(adev);
+	case ACPI_NOTIFY_DEVICE_CHECK:
+		return acpi_scan_device_check(adev);
+	case ACPI_NOTIFY_EJECT_REQUEST:
+	case ACPI_OST_EC_OSPM_EJECT:
+		return acpi_scan_hot_remove(adev);
+	}
+	return -EINVAL;
+}
+
 static void acpi_device_hotplug(void *data, u32 src)
 {
 	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_device *adev = data;
-	int error;
+	int error = -ENODEV;
 
 	lock_device_hotplug();
 	mutex_lock(&acpi_scan_lock);
 
 	/*
 	 * The device object's ACPI handle cannot become invalid as long as we
-	 * are holding acpi_scan_lock, but it may have become invalid before
+	 * are holding acpi_scan_lock, but it might have become invalid before
 	 * that lock was acquired.
 	 */
 	if (adev->handle == INVALID_ACPI_HANDLE)
-		goto out;
+		goto err_out;
 
-	switch (src) {
-	case ACPI_NOTIFY_BUS_CHECK:
-		error = acpi_scan_bus_check(adev);
-		break;
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		error = acpi_scan_device_check(adev);
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-	case ACPI_OST_EC_OSPM_EJECT:
-		error = acpi_scan_hot_remove(adev);
-		break;
-	default:
-		error = -EINVAL;
-		break;
+	if (adev->flags.hotplug_notify) {
+		error = acpi_generic_hotplug_event(adev, src);
+	} else {
+		int (*event)(struct acpi_device *, u32);
+
+		acpi_lock_hp_context();
+		event = adev->hp ? adev->hp->event : NULL;
+		acpi_unlock_hp_context();
+		/*
+		 * There may be additional notify handlers for device objects
+		 * without the .event() callback, so ignore them here.
+		 */
+		if (event)
+			error = event(adev, src);
+		else
+			goto out;
 	}
 	if (!error)
 		ost_code = ACPI_OST_SC_SUCCESS;
 
- out:
+ err_out:
 	acpi_evaluate_hotplug_ost(adev->handle, src, ost_code, NULL);
+
+ out:
 	acpi_bus_put_acpi_device(adev);
 	mutex_unlock(&acpi_scan_lock);
 	unlock_device_hotplug();
@@ -494,8 +512,8 @@ static void acpi_device_hotplug(void *da
 
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
-	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	struct acpi_scan_handler *handler = data;
+	u32 ost_code = ACPI_OST_SC_SUCCESS;
 	struct acpi_device *adev;
 	acpi_status status;
 
@@ -503,26 +521,49 @@ static void acpi_hotplug_notify_cb(acpi_
 	case ACPI_NOTIFY_BUS_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_DEVICE_CHECK:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
 		break;
+
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-		if (!handler->hotplug.enabled) {
+		if (handler && !handler->hotplug.enabled) {
 			acpi_handle_err(handle, "Eject disabled\n");
 			ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-			goto err_out;
+			goto out;
 		}
 		acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
 					  ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
 		break;
-	default:
-		/* non-hotplug event; possibly handled by other handler */
+
+	case ACPI_NOTIFY_DEVICE_WAKE:
 		return;
+
+	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a frequency mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
+		acpi_handle_err(handle, "Device cannot be configured due "
+				"to a bus mode mismatch\n");
+		goto out;
+
+	case ACPI_NOTIFY_POWER_FAULT:
+		acpi_handle_err(handle, "Device has suffered a power fault\n");
+		goto out;
+
+	default:
+		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
+		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
+		goto out;
 	}
+
+	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 	adev = acpi_bus_get_acpi_device(handle);
 	if (!adev)
-		goto err_out;
+		goto out;
 
 	status = acpi_hotplug_execute(acpi_device_hotplug, adev, type);
 	if (ACPI_SUCCESS(status))
@@ -530,10 +571,22 @@ static void acpi_hotplug_notify_cb(acpi_
 
 	acpi_bus_put_acpi_device(adev);
 
- err_out:
+ out:
 	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
 }
 
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data)
+{
+	acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				    acpi_hotplug_notify_cb, data);
+}
+
+void acpi_remove_hotplug_notify_handler(acpi_handle handle)
+{
+	acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+				   acpi_hotplug_notify_cb);
+}
+
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -1976,33 +2029,21 @@ void acpi_scan_hotplug_enabled(struct ac
 	mutex_unlock(&acpi_scan_lock);
 }
 
-static void acpi_scan_init_hotplug(acpi_handle handle, int type)
+static void acpi_scan_init_hotplug(struct acpi_device *adev)
 {
-	struct acpi_device_pnp pnp = {};
 	struct acpi_hardware_id *hwid;
-	struct acpi_scan_handler *handler;
-
-	INIT_LIST_HEAD(&pnp.ids);
-	acpi_set_pnp_ids(handle, &pnp, type);
 
-	if (!pnp.type.hardware_id)
-		goto out;
+	list_for_each_entry(hwid, &adev->pnp.ids, list) {
+		struct acpi_scan_handler *handler;
 
-	/*
-	 * This relies on the fact that acpi_install_notify_handler() will not
-	 * install the same notify handler routine twice for the same handle.
-	 */
-	list_for_each_entry(hwid, &pnp.ids, list) {
 		handler = acpi_scan_match_handler(hwid->id, NULL);
-		if (handler) {
-			acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-					acpi_hotplug_notify_cb, handler);
-			break;
-		}
-	}
+		if (!handler)
+			continue;
 
-out:
-	acpi_free_pnp_ids(&pnp);
+		acpi_install_hotplug_notify_handler(adev->handle, handler);
+		adev->flags.hotplug_notify = true;
+		break;
+	}
 }
 
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
@@ -2026,12 +2067,12 @@ static acpi_status acpi_bus_check_add(ac
 		return AE_OK;
 	}
 
-	acpi_scan_init_hotplug(handle, type);
-
 	acpi_add_single_object(&device, handle, type, sta);
 	if (!device)
 		return AE_CTRL_DEPTH;
 
+	acpi_scan_init_hotplug(device);
+
  out:
 	if (!*return_value)
 		*return_value = device;
Index: linux-pm/drivers/pci/hotplug/acpiphp.h
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp.h
+++ linux-pm/drivers/pci/hotplug/acpiphp.h
@@ -116,12 +116,17 @@ struct acpiphp_func {
 };
 
 struct acpiphp_context {
+	struct acpi_hotplug_context hp;
 	struct acpiphp_func func;
-	struct acpi_device *adev;
 	struct acpiphp_bridge *bridge;
 	unsigned int refcount;
 };
 
+static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp)
+{
+	return container_of(hp, struct acpiphp_context, hp);
+}
+
 static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)
 {
 	return container_of(func, struct acpiphp_context, func);
@@ -129,7 +134,7 @@ static inline struct acpiphp_context *fu
 
 static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func)
 {
-	return func_to_context(func)->adev;
+	return func_to_context(func)->hp.self;
 }
 
 static inline acpi_handle func_to_handle(struct acpiphp_func *func)
Index: linux-pm/drivers/pci/hotplug/acpiphp_glue.c
===================================================================
--- linux-pm.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-pm/drivers/pci/hotplug/acpiphp_glue.c
@@ -59,17 +59,12 @@
 static LIST_HEAD(bridge_list);
 static DEFINE_MUTEX(bridge_mutex);
 
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type);
 static void acpiphp_sanitize_bus(struct pci_bus *bus);
 static void acpiphp_set_hpp_values(struct pci_bus *bus);
 static void hotplug_event(u32 type, struct acpiphp_context *context);
 static void free_bridge(struct kref *kref);
 
-static void acpiphp_context_handler(acpi_handle handle, void *context)
-{
-	/* Intentionally empty. */
-}
-
 /**
  * acpiphp_init_context - Create hotplug context and grab a reference to it.
  * @adev: ACPI device object to create the context for.
@@ -79,39 +74,31 @@ static void acpiphp_context_handler(acpi
 static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)
 {
 	struct acpiphp_context *context;
-	acpi_status status;
 
 	context = kzalloc(sizeof(*context), GFP_KERNEL);
 	if (!context)
 		return NULL;
 
-	context->adev = adev;
 	context->refcount = 1;
-	status = acpi_attach_data(adev->handle, acpiphp_context_handler, context);
-	if (ACPI_FAILURE(status)) {
-		kfree(context);
-		return NULL;
-	}
+	acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_event);
 	return context;
 }
 
 /**
  * acpiphp_get_context - Get hotplug context and grab a reference to it.
- * @handle: ACPI object handle to get the context for.
+ * @adev: ACPI device object to get the context for.
  *
  * Call under acpi_hp_context_lock.
  */
-static struct acpiphp_context *acpiphp_get_context(acpi_handle handle)
+static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)
 {
-	struct acpiphp_context *context = NULL;
-	acpi_status status;
-	void *data;
+	struct acpiphp_context *context;
 
-	status = acpi_get_data(handle, acpiphp_context_handler, &data);
-	if (ACPI_SUCCESS(status)) {
-		context = data;
-		context->refcount++;
-	}
+	if (!adev->hp)
+		return NULL;
+
+	context = to_acpiphp_context(adev->hp);
+	context->refcount++;
 	return context;
 }
 
@@ -129,7 +116,7 @@ static void acpiphp_put_context(struct a
 		return;
 
 	WARN_ON(context->bridge);
-	acpi_detach_data(context->adev->handle, acpiphp_context_handler);
+	context->hp.self->hp = NULL;
 	kfree(context);
 }
 
@@ -211,22 +198,13 @@ static void post_dock_fixups(acpi_handle
 
 static void dock_event(acpi_handle handle, u32 type, void *data)
 {
-	struct acpiphp_context *context;
+	struct acpi_device *adev;
 
-	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->adev->handle != handle)
-	    || context->func.parent->is_going_away) {
-		acpi_unlock_hp_context();
-		return;
+	adev = acpi_bus_get_acpi_device(handle);
+	if (adev) {
+		acpiphp_hotplug_event(adev, type);
+		acpi_bus_put_acpi_device(adev);
 	}
-	get_bridge(context->func.parent);
-	acpiphp_put_context(context);
-	acpi_unlock_hp_context();
-
-	hotplug_event(type, context);
-
-	put_bridge(context->func.parent);
 }
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
@@ -397,25 +375,23 @@ static acpi_status register_slot(acpi_ha
 	}
 
 	/* install notify handler */
-	if (!(newfunc->flags & FUNC_HAS_DCK)) {
-		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-						     handle_hotplug_event,
-						     context);
-		if (ACPI_FAILURE(status))
-			acpi_handle_err(handle,
-					"failed to install notify handler\n");
-	}
+	if (!(newfunc->flags & FUNC_HAS_DCK))
+		acpi_install_hotplug_notify_handler(handle, NULL);
 
 	return AE_OK;
 }
 
 static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
 {
+	struct acpi_device *adev = acpi_bus_get_acpi_device(handle);
 	struct acpiphp_context *context;
 	struct acpiphp_bridge *bridge = NULL;
 
+	if (!adev)
+		return NULL;
+
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
+	context = acpiphp_get_context(adev);
 	if (context) {
 		bridge = context->bridge;
 		if (bridge)
@@ -424,6 +400,7 @@ static struct acpiphp_bridge *acpiphp_ha
 		acpiphp_put_context(context);
 	}
 	acpi_unlock_hp_context();
+	acpi_bus_put_acpi_device(adev);
 	return bridge;
 }
 
@@ -431,7 +408,6 @@ static void cleanup_bridge(struct acpiph
 {
 	struct acpiphp_slot *slot;
 	struct acpiphp_func *func;
-	acpi_status status;
 
 	list_for_each_entry(slot, &bridge->slots, node) {
 		list_for_each_entry(func, &slot->funcs, sibling) {
@@ -440,13 +416,8 @@ static void cleanup_bridge(struct acpiph
 			if (is_dock_device(handle))
 				unregister_hotplug_dock_device(handle);
 
-			if (!(func->flags & FUNC_HAS_DCK)) {
-				status = acpi_remove_notify_handler(handle,
-							ACPI_SYSTEM_NOTIFY,
-							handle_hotplug_event);
-				if (ACPI_FAILURE(status))
-					pr_err("failed to remove notify handler\n");
-			}
+			if (!(func->flags & FUNC_HAS_DCK))
+				acpi_remove_hotplug_notify_handler(handle);
 		}
 		slot->flags |= SLOT_IS_GOING_AWAY;
 		if (slot->slot)
@@ -814,7 +785,7 @@ static int acpiphp_disable_and_eject_slo
 
 static void hotplug_event(u32 type, struct acpiphp_context *context)
 {
-	acpi_handle handle = context->adev->handle;
+	acpi_handle handle = context->hp.self->handle;
 	struct acpiphp_func *func = &context->func;
 	struct acpiphp_slot *slot = func->slot;
 	struct acpiphp_bridge *bridge;
@@ -866,87 +837,24 @@ static void hotplug_event(u32 type, stru
 		put_bridge(bridge);
 }
 
-static void hotplug_event_work(void *data, u32 type)
-{
-	struct acpiphp_context *context = data;
-
-	acpi_scan_lock_acquire();
-
-	hotplug_event(type, context);
-
-	acpi_scan_lock_release();
-	acpi_evaluate_hotplug_ost(context->adev->handle, type,
-				  ACPI_OST_SC_SUCCESS, NULL);
-	put_bridge(context->func.parent);
-}
-
-/**
- * handle_hotplug_event - handle ACPI hotplug event
- * @handle: Notify()'ed acpi_handle
- * @type: Notify code
- * @data: pointer to acpiphp_context structure
- *
- * Handles ACPI event notification on slots.
- */
-static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
+static int acpiphp_hotplug_event(struct acpi_device *adev, u32 type)
 {
 	struct acpiphp_context *context;
-	u32 ost_code = ACPI_OST_SC_SUCCESS;
-	acpi_status status;
-
-	switch (type) {
-	case ACPI_NOTIFY_BUS_CHECK:
-	case ACPI_NOTIFY_DEVICE_CHECK:
-		break;
-	case ACPI_NOTIFY_EJECT_REQUEST:
-		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS;
-		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-		break;
-
-	case ACPI_NOTIFY_DEVICE_WAKE:
-		return;
-
-	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a frequency mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
-		acpi_handle_err(handle, "Device cannot be configured due "
-				"to a bus mode mismatch\n");
-		goto out;
-
-	case ACPI_NOTIFY_POWER_FAULT:
-		acpi_handle_err(handle, "Device has suffered a power fault\n");
-		goto out;
-
-	default:
-		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type);
-		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY;
-		goto out;
-	}
 
 	acpi_lock_hp_context();
-	context = acpiphp_get_context(handle);
-	if (!context || WARN_ON(context->adev->handle != handle)
-	    || context->func.parent->is_going_away)
-		goto err_out;
-
-	get_bridge(context->func.parent);
-	acpiphp_put_context(context);
-	status = acpi_hotplug_execute(hotplug_event_work, context, type);
-	if (ACPI_SUCCESS(status)) {
+	context = acpiphp_get_context(adev);
+	if (!context || context->func.parent->is_going_away) {
 		acpi_unlock_hp_context();
-		return;
+		return -ENODATA;
 	}
-	put_bridge(context->func.parent);
-
- err_out:
+	get_bridge(context->func.parent);
+	acpiphp_put_context(context);
 	acpi_unlock_hp_context();
-	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
 
- out:
-	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
+	hotplug_event(type, context);
+
+	put_bridge(context->func.parent);
+	return 0;
 }
 
 /**
@@ -999,7 +907,7 @@ void acpiphp_enumerate_slots(struct pci_
 		 * bridge is not interesting to us either.
 		 */
 		acpi_lock_hp_context();
-		context = acpiphp_get_context(handle);
+		context = acpiphp_get_context(adev);
 		if (!context) {
 			acpi_unlock_hp_context();
 			put_device(&bus->dev);
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -137,6 +137,16 @@ struct acpi_scan_handler {
 };
 
 /*
+ * ACPI Hotplug Context
+ * --------------------
+ */
+
+struct acpi_hotplug_context {
+	struct acpi_device *self;
+	int (*event)(struct acpi_device *, u32);
+};
+
+/*
  * ACPI Driver
  * -----------
  */
@@ -190,7 +200,8 @@ struct acpi_device_flags {
 	u32 initialized:1;
 	u32 visited:1;
 	u32 no_hotplug:1;
-	u32 reserved:24;
+	u32 hotplug_notify:1;
+	u32 reserved:23;
 };
 
 /* File System */
@@ -329,6 +340,7 @@ struct acpi_device {
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
 	struct acpi_scan_handler *handler;
+	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct device dev;
@@ -351,6 +363,15 @@ static inline void acpi_set_device_statu
 	*((u32 *)&adev->status) = sta;
 }
 
+static inline void acpi_set_hp_context(struct acpi_device *adev,
+				       struct acpi_hotplug_context *hp,
+				       int (*event)(struct acpi_device *, u32))
+{
+	hp->self = adev;
+	hp->event = event;
+	adev->hp = hp;
+}
+
 /* acpi_device.dev.bus == &acpi_bus_type */
 extern struct bus_type acpi_bus_type;
 
@@ -425,6 +446,8 @@ static inline bool acpi_device_enumerate
 typedef void (*acpi_hp_callback)(void *data, u32 src);
 
 acpi_status acpi_hotplug_execute(acpi_hp_callback func, void *data, u32 src);
+void acpi_install_hotplug_notify_handler(acpi_handle handle, void *data);
+void acpi_remove_hotplug_notify_handler(acpi_handle handle);
 
 /**
  * module_acpi_driver(acpi_driver) - Helper macro for registering an ACPI driver


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

* Re: [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently
  2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
                   ` (12 preceding siblings ...)
  2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
@ 2014-02-11  0:19 ` Bjorn Helgaas
  2014-02-11 12:53   ` Rafael J. Wysocki
  13 siblings, 1 reply; 100+ messages in thread
From: Bjorn Helgaas @ 2014-02-11  0:19 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: ACPI Devel Maling List, Aaron Lu, Linux Kernel Mailing List,
	Linux PCI, Mika Westerberg

On Mon, Jan 27, 2014 at 01:37:17AM +0100, Rafael J. Wysocki wrote:
> Hi All,
> 
> ACPIPHP can be simplified a bit on top of some PCI and ACPI changes merged
> recently and the following series of patches implements those simplifications:
> 
> [1/11] Fix up two kerneldoc comments in acpiphp_glue.c.
> [2/11] Get rid of an unnecessary label in register_slot().
> [3/11] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
> [4/11] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
> [5/11] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
> [6/11] Drop acpiphp_bus_add() (which has only one user).
> [7/11] Drop crit_sect mutexes (that are redundant).
> [8/11] Clean up the usage of the slot variable in hotplug_event().
> [9/11] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
> [10/11] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
> [11/11] Drop handle argument from the member functions of struct acpi_dock_ops.

I assume you'll handle all these through your tree, Rafael.  Let me know if
you need me to do anything.

Bjorn

> All of that is relateively straightforward, but I have some more intrusive changes
> on top of it in the works.  They will be posted separately later this week.
> 
> Thanks!
> 
> -- 
> I speak only for myself.
> Rafael J. Wysocki, Intel Open Source Technology Center.

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

* Re: [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently
  2014-02-11  0:19 ` [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Bjorn Helgaas
@ 2014-02-11 12:53   ` Rafael J. Wysocki
  0 siblings, 0 replies; 100+ messages in thread
From: Rafael J. Wysocki @ 2014-02-11 12:53 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: ACPI Devel Maling List, Aaron Lu, Linux Kernel Mailing List,
	Linux PCI, Mika Westerberg

On Monday, February 10, 2014 05:19:58 PM Bjorn Helgaas wrote:
> On Mon, Jan 27, 2014 at 01:37:17AM +0100, Rafael J. Wysocki wrote:
> > Hi All,
> > 
> > ACPIPHP can be simplified a bit on top of some PCI and ACPI changes merged
> > recently and the following series of patches implements those simplifications:
> > 
> > [1/11] Fix up two kerneldoc comments in acpiphp_glue.c.
> > [2/11] Get rid of an unnecessary label in register_slot().
> > [3/11] Drop acpiphp_bus_trim() and use acpi_bus_trim() instead of it directly.
> > [4/11] Move the acpi_bus_get_device() call out of acpiphp_no_hotplug().
> > [5/11] Store struct acpi_device pointers instead of ACPI handles in struct acpiphp_context.
> > [6/11] Drop acpiphp_bus_add() (which has only one user).
> > [7/11] Drop crit_sect mutexes (that are redundant).
> > [8/11] Clean up the usage of the slot variable in hotplug_event().
> > [9/11] Drop dev_in_slot() and rework disable_slot() to walk bus->devices directly.
> > [10/11] Use acpi_handle_debug() in hotplug_event() instead of open-coded stuff.
> > [11/11] Drop handle argument from the member functions of struct acpi_dock_ops.
> 
> I assume you'll handle all these through your tree, Rafael.  Let me know if
> you need me to do anything.

Yes, I'll handle these, thanks!

Rafael


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

end of thread, other threads:[~2014-02-11 12:39 UTC | newest]

Thread overview: 100+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-27  0:37 [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
2014-01-27  0:38 ` [PATCH 1/11] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
2014-01-27  0:38 ` [PATCH 2/11] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
2014-01-27  0:39 ` [PATCH 3/11] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
2014-01-27  0:40 ` [PATCH 4/11] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
2014-01-27  0:41 ` [PATCH 5/11] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
2014-01-27  0:41 ` [PATCH 6/11] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
2014-01-27  0:42 ` [PATCH 7/11] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
2014-01-27  0:43 ` [PATCH 8/11] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
2014-01-27  0:44 ` [PATCH 9/11] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
2014-01-27  0:45 ` [PATCH 10/11] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
2014-01-27  0:46 ` [PATCH 11/11] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations Rafael J. Wysocki
2014-01-28 22:10 ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
2014-01-28 22:12   ` [PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
2014-01-28 22:13   ` [PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-01-28 22:14   ` [PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-01-28 22:14   ` [PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-01-28 22:16   ` [PATCH 5/5][RFT] ACPI / hotplug: Dispach hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-01-28 23:57   ` [PATCH 0/5][RFT] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
2014-01-28 23:58     ` [Resend][PATCH 1/5][RFT] ACPI / hotplug / PCI: Attach hotplug contexts to struct acpi_device Rafael J. Wysocki
2014-01-28 23:59     ` [Resend][PATCH 2/5][RFT] ACPI / hotplug: Introduce acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-01-28 23:59     ` [Update][PATCH 3/5][RFT] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-01-29  0:00     ` [Update][PATCH 4/5][RFT] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-01-31 15:28       ` Mika Westerberg
2014-01-31 15:42         ` Rafael J. Wysocki
2014-01-31 15:40           ` Mika Westerberg
2014-01-31 16:01             ` Mika Westerberg
2014-01-31 16:16               ` Rafael J. Wysocki
2014-01-31 17:09                 ` Mika Westerberg
2014-01-31 17:34                   ` Rafael J. Wysocki
2014-02-02  0:12                     ` Rafael J. Wysocki
2014-01-29  0:02     ` [Update][PATCH 5/5][RFT] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-01-30 15:28       ` [Update 2x][PATCH " Rafael J. Wysocki
2014-02-02  0:52     ` [PATCH v2 0/6] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
2014-02-02  0:54       ` [PATCH v2 1/6] ACPI / hotplug: Fix theoretical race in acpi_hotplug_notify_cb() Rafael J. Wysocki
2014-02-02 17:01         ` Rafael J. Wysocki
2014-02-02  0:55       ` [PATCH v2 2/6] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
2014-02-02  0:56       ` [PATCH v2 3/6] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-02-02  0:57       ` [PATCH v2 4/6] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
2014-02-02  0:58       ` [PATCH v2 5/6] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-02-02  0:58       ` [PATCH v2 6/6] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-02-02 17:11       ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Rafael J. Wysocki
2014-02-02 17:12         ` [PATCH v3 1/7] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
2014-02-02 17:15         ` [PATCH v3 2/7] ACPI / hotplug: Fix potential races in notify handlers Rafael J. Wysocki
2014-02-02 17:16         ` [PATCH v3 3/7] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
2014-02-02 17:17         ` [PATCH v3 4/7] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-02-02 17:18         ` [PATCH v3 5/7] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
2014-02-02 17:19         ` [PATCH v3 6/7] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-02-02 17:20         ` [PATCH v3 7/7] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-02-03 10:45         ` [PATCH v3 0/7] ACPI / hotplug / PCI: Consolidation of ACPIPHP with ACPI core device hotplug Mika Westerberg
2014-02-03 21:51           ` Rafael J. Wysocki
2014-02-02  0:19 ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Rafael J. Wysocki
2014-02-02  0:21   ` [PATCH v2 1/13] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
2014-02-02  0:22   ` [PATCH v2 2/13] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() Rafael J. Wysocki
2014-02-02  0:23   ` [PATCH v2 3/13] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
2014-02-02  0:24   ` [PATCH v2 4/13] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
2014-02-02  0:25   ` [PATCH v2 5/13] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
2014-02-02  0:26   ` [PATCH v2 6/13] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
2014-02-02  0:27   ` [PATCH v2 7/13] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
2014-02-02  0:27   ` [PATCH v2 8/13] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
2014-02-02  0:28   ` [PATCH v2 9/13] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
2014-02-02  0:29   ` [PATCH v2 10/13] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
2014-02-02  0:30   ` [PATCH v2 11/13] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
2014-02-02  0:31   ` [PATCH v2 12/13] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
2014-02-02  0:31   ` [PATCH v2 13/13] ACPI / hotplug: Do not pass ACPI handles to ACPI dock operations Rafael J. Wysocki
2014-02-03  1:47   ` [PATCH] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock Rafael J. Wysocki
2014-02-03 10:44   ` [PATCH v2 0/13] ACPI / hotplug / PCI: Updates on top of changes merged recently Mika Westerberg
2014-02-03 23:12     ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Rafael J. Wysocki
2014-02-03 23:14       ` [PATCH 1/24][Resend] ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order Rafael J. Wysocki
2014-02-03 23:15       ` [PATCH 2/24][Resend] ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event() Rafael J. Wysocki
2014-02-03 23:16       ` [PATCH 3/24][Resend] ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock Rafael J. Wysocki
2014-02-03 23:18       ` [PATCH 4/24][New] ACPI / hotplug / PCI: Fix bridge removal race in handle_hotplug_event() Rafael J. Wysocki
2014-02-03 23:18       ` [PATCH 5/24][New] ACPI / hotplug / PCI: Fix bridge removal race vs dock events Rafael J. Wysocki
2014-02-03 23:20       ` [PATCH 6/24][Resend] ACPI / hotplug / PCI: Simplify disable_slot() Rafael J. Wysocki
2014-02-03 23:21       ` [PATCH 7/24][Resend] ACPI / hotplug / PCI: Proper kerneldoc comments for enumeration/removal Rafael J. Wysocki
2014-02-03 23:22       ` [PATCH 8/24][Resend] ACPI / hotplug / PCI: Simplify register_slot() Rafael J. Wysocki
2014-02-03 23:23       ` [PATCH 9/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_trim() Rafael J. Wysocki
2014-02-03 23:24       ` [PATCH 10/24][Resend] ACPI / hotplug / PCI: Rework acpiphp_no_hotplug() Rafael J. Wysocki
2014-02-03 23:25       ` [PATCH 11/24][Update] ACPI / hotplug / PCI: Store acpi_device pointer in acpiphp_context Rafael J. Wysocki
2014-02-03 23:26       ` [PATCH 12/24][Resend] ACPI / hotplug / PCI: Drop acpiphp_bus_add() Rafael J. Wysocki
2014-02-03 23:27       ` [PATCH 13/24][Resend] ACPI / hotplug / PCI: Drop crit_sect locking Rafael J. Wysocki
2014-02-03 23:33       ` [PATCH 14/24][Update] ACPI / hotplug / PCI: Simplify hotplug_event() Rafael J. Wysocki
2014-02-03 23:33       ` [PATCH 15/24][Resend] ACPI / hotplug / PCI: Use acpi_handle_debug() in hotplug_event() Rafael J. Wysocki
2014-02-03 23:34       ` [PATCH 16/24][New] ACPI / hotplug / PCI: Do not pass ACPI handle to hotplug_event() Rafael J. Wysocki
2014-02-03 23:34       ` [PATCH 17/24][Resend] ACPICA: Introduce acpi_get_data_full() and rework acpi_get_data() Rafael J. Wysocki
2014-02-03 23:36       ` [PATCH 18/24][Update] ACPI / hotplug: Fix potential race in acpi_bus_notify() Rafael J. Wysocki
2014-02-03 23:36       ` [PATCH 19/24][Update] ACPI / hotplug / PCI: Define hotplug context lock in the core Rafael J. Wysocki
2014-02-03 23:37       ` [PATCH 20/24][Update] ACPI / hotplug / PCI: Consolidate ACPIPHP with ACPI core hotplug Rafael J. Wysocki
2014-02-06 13:07         ` [Update][PATCH 20/24] " Rafael J. Wysocki
2014-02-06 23:35           ` [Update 2x][PATCH " Rafael J. Wysocki
2014-02-03 23:38       ` [PATCH 21/24][Resend] ACPI / hotplug / PCI: Rework the handling of eject requests Rafael J. Wysocki
2014-02-03 23:39       ` [PATCH 22/24][Resend] ACPI / hotplug / PCI: Simplify acpi_install_hotplug_notify_handler() Rafael J. Wysocki
2014-02-06 13:09         ` [Update][PATCH 22/24] " Rafael J. Wysocki
2014-02-03 23:40       ` [PATCH 23/24][Update] ACPI / hotplug / PCI: Hotplug notifications from acpi_bus_notify() Rafael J. Wysocki
2014-02-06 13:10         ` [Update][PATCH 23/24] " Rafael J. Wysocki
2014-02-03 23:41       ` [PATCH 24/24][New] ACPI / hotplug / PCI: Rework acpiphp_check_host_bridge() Rafael J. Wysocki
2014-02-05 10:14       ` [PATCH v2 0/24] ACPI / hotplug / PCI: ACPIPHP updates and consolidation with ACPI core Mika Westerberg
2014-02-05 10:59         ` Rafael J. Wysocki
2014-02-11  0:19 ` [PATCH 0/11] ACPI / hotplug / PCI: Updates on top of changes merged recently Bjorn Helgaas
2014-02-11 12:53   ` 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).