public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH -v3 02/47] PNPACPI: Fix device ref leaking in acpi_pnp_match
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
@ 2012-03-19  5:45 ` Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 26/47] PCI, ACPI: Make acpi_pci_root_remove remove pci root bus too Yinghai Lu
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:45 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Yinghai Lu, stable, Len Brown,
	Adam Belay, linux-acpi

During testing pci root bus removal, found some root bus bridge is not freed.

If booting with pnpacpi=off, those hostbridge could be freed without problem.

It turns out that some devices reference are not released during acpi_pnp_match.

That match should not hold one device ref during every calling.

Add put_device calling before returning.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: stable@kernel.org
Cc: Len Brown <lenb@kernel.org>
Cc: Adam Belay <abelay@mit.edu>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-acpi@vger.kernel.org
---
 drivers/pnp/pnpacpi/core.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index b00c176..d21e8f5 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -321,9 +321,14 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp)
 {
 	struct acpi_device *acpi = to_acpi_device(dev);
 	struct pnp_dev *pnp = _pnp;
+	struct device *physical_device;
+
+	physical_device = acpi_get_physical_device(acpi->handle);
+	if (physical_device)
+		put_device(physical_device);
 
 	/* true means it matched */
-	return !acpi_get_physical_device(acpi->handle)
+	return !physical_device
 	    && compare_pnp_id(pnp->id, acpi_device_hid(acpi));
 }
 
-- 
1.7.7


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

* [PATCH -v3 26/47] PCI, ACPI: Make acpi_pci_root_remove remove pci root bus too
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
  2012-03-19  5:45 ` [PATCH -v3 02/47] PNPACPI: Fix device ref leaking in acpi_pnp_match Yinghai Lu
@ 2012-03-19  5:46 ` Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 28/47] PCI, ACPI: Add pci_root_hp hot removal notification support Yinghai Lu
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:46 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Yinghai Lu, Len Brown, linux-acpi

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

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

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

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

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

* [PATCH -v3 28/47] PCI, ACPI: Add pci_root_hp hot removal notification support.
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
  2012-03-19  5:45 ` [PATCH -v3 02/47] PNPACPI: Fix device ref leaking in acpi_pnp_match Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 26/47] PCI, ACPI: Make acpi_pci_root_remove remove pci root bus too Yinghai Lu
@ 2012-03-19  5:46 ` Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 29/47] PCI, ACPI: Add alloc_acpi_hp_work() Yinghai Lu
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:46 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Yinghai Lu, Len Brown, linux-acpi

Add missing hot_remove support for root device.

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

  echo "\_SB.PCIB 3" > /proc/acpi/sci/notify
to remove root bus

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

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

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

* [PATCH -v3 29/47] PCI, ACPI: Add alloc_acpi_hp_work()
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
                   ` (2 preceding siblings ...)
  2012-03-19  5:46 ` [PATCH -v3 28/47] PCI, ACPI: Add pci_root_hp hot removal notification support Yinghai Lu
@ 2012-03-19  5:46 ` Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 30/47] PCI, acpiphp: Use acpi_hp_work Yinghai Lu
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:46 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Yinghai Lu, Len Brown, linux-acpi

Will use it with acpiphp and pci_root_hp events handling

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

diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 412a1e0..fdcf4a5 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1641,3 +1641,24 @@ acpi_status acpi_os_terminate(void)
 
 	return AE_OK;
 }
+
+void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
+			void (*func)(struct work_struct *work))
+{
+	struct acpi_hp_work *hp_work;
+	int ret;
+
+	hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
+	if (!hp_work)
+		return;
+
+	hp_work->handle = handle;
+	hp_work->type = type;
+	hp_work->context = context;
+
+	INIT_WORK(&hp_work->work, func);
+	ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
+	if (!ret)
+		kfree(hp_work);
+}
+EXPORT_SYMBOL(alloc_acpi_hp_work);
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 7c9aebe..62326ae 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -191,6 +191,15 @@ void acpi_os_fixed_event_count(u32 fixed_event_number);
  */
 extern struct workqueue_struct *kacpi_hotplug_wq;
 
+struct acpi_hp_work {
+	struct work_struct work;
+	acpi_handle handle;
+	u32 type;
+	void *context;
+};
+void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context,
+			void (*func)(struct work_struct *work));
+
 acpi_thread_id acpi_os_get_thread_id(void);
 
 acpi_status
-- 
1.7.7


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

* [PATCH -v3 30/47] PCI, acpiphp: Use acpi_hp_work
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
                   ` (3 preceding siblings ...)
  2012-03-19  5:46 ` [PATCH -v3 29/47] PCI, ACPI: Add alloc_acpi_hp_work() Yinghai Lu
@ 2012-03-19  5:46 ` Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 31/47] PCI, pci_root_hp: " Yinghai Lu
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:46 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Yinghai Lu, Len Brown, linux-acpi

Remove local defined acpiphp_hp_work.

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

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


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

* [PATCH -v3 31/47] PCI, pci_root_hp: Use acpi_hp_work
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
                   ` (4 preceding siblings ...)
  2012-03-19  5:46 ` [PATCH -v3 30/47] PCI, acpiphp: Use acpi_hp_work Yinghai Lu
@ 2012-03-19  5:46 ` Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 32/47] PCI, ACPI: Make kacpi_hotplug_wq static Yinghai Lu
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:46 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Yinghai Lu, Len Brown, linux-acpi

Remove local copy: acpi_root_hp_work

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

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

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

* [PATCH -v3 32/47] PCI, ACPI: Make kacpi_hotplug_wq static
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
                   ` (5 preceding siblings ...)
  2012-03-19  5:46 ` [PATCH -v3 31/47] PCI, pci_root_hp: " Yinghai Lu
@ 2012-03-19  5:46 ` Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 39/47] ACPI: Enable SCI_EMULATE to manually simulate physical hotplug testing Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 41/47] PCI, ACPI: Add acpi_pci_root_rescan() Yinghai Lu
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:46 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Yinghai Lu, Len Brown, linux-acpi

No external user anymore.

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

diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index fdcf4a5..09be602 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -81,8 +81,7 @@ static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
 static struct workqueue_struct *kacpi_notify_wq;
-struct workqueue_struct *kacpi_hotplug_wq;
-EXPORT_SYMBOL(kacpi_hotplug_wq);
+static struct workqueue_struct *kacpi_hotplug_wq;
 
 /*
  * This list of permanent mappings is for memory that may be accessed from
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 62326ae..2326622 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -189,8 +189,6 @@ void acpi_os_fixed_event_count(u32 fixed_event_number);
 /*
  * Threads and Scheduling
  */
-extern struct workqueue_struct *kacpi_hotplug_wq;
-
 struct acpi_hp_work {
 	struct work_struct work;
 	acpi_handle handle;
-- 
1.7.7

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

* [PATCH -v3 39/47] ACPI: Enable SCI_EMULATE to manually simulate physical hotplug testing.
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
                   ` (6 preceding siblings ...)
  2012-03-19  5:46 ` [PATCH -v3 32/47] PCI, ACPI: Make kacpi_hotplug_wq static Yinghai Lu
@ 2012-03-19  5:46 ` Yinghai Lu
  2012-03-19  5:46 ` [PATCH -v3 41/47] PCI, ACPI: Add acpi_pci_root_rescan() Yinghai Lu
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:46 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Ashok Raj, Yinghai Lu, Len Brown,
	linux-acpi

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

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

Enable CONFIG_ACPI_SCI_EMULATE on kernel compile.

Now you will notice /proc/acpi/sci/notify when new kernel is booted.

echo "\_SB.CPU4 1" > /proc/acpi/sci/notify to trigger a hot-add of CPU4.
You will now notice an entry /sys/firmware/acpi/namespace/ACPI/_SB/CPU4
if the namespace had an entry CPU4 under _SB scope. If the entry had a
_EJ0 method, you will also notice a file "eject" under the CPU4 directory.

-v2: Update to current upstream, and remove not related stuff.

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

===================================================================
---
 drivers/acpi/Kconfig    |   10 +++
 drivers/acpi/Makefile   |    1 +
 drivers/acpi/bus.c      |    2 +
 drivers/acpi/internal.h |    6 ++
 drivers/acpi/sci_emu.c  |  141 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 160 insertions(+), 0 deletions(-)
 create mode 100644 drivers/acpi/sci_emu.c

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 7556913..b7b8541 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -272,6 +272,16 @@ config ACPI_BLACKLIST_YEAR
 	  Enter 0 to disable this mechanism and allow ACPI to
 	  run by default no matter what the year.  (default)
 
+config ACPI_SCI_EMULATE
+	bool "ACPI SCI Event Emulation Support"
+	depends on ACPI
+	default n
+	help
+	  This will enable your system to emulate sci hotplug event
+	  notification through proc file system. For example user needs to
+	  echo "XXX 0" > /proc/acpi/sci/notify (where, XXX is a target ACPI
+	  device object name present under \_SB scope).
+
 config ACPI_DEBUG
 	bool "Debug Statements"
 	default n
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index bc6e53f..3580f04 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -31,6 +31,7 @@ acpi-$(CONFIG_ACPI_SLEEP)	+= proc.o
 # ACPI Bus and Device Drivers
 #
 acpi-y				+= bus.o glue.o
+acpi-$(CONFIG_ACPI_SCI_EMULATE)	+= sci_emu.o
 acpi-y				+= scan.o
 acpi-y				+= processor_core.o
 acpi-y				+= ec.o
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 9ecec98..512235e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1001,6 +1001,8 @@ static int __init acpi_bus_init(void)
 	 */
 	acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);
 
+	acpi_init_sci_emulate();
+
 	return 0;
 
 	/* Mimic structured exception handling */
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index ca75b9c..5b22cd2 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -34,6 +34,12 @@ int acpi_debugfs_init(void);
 static inline void acpi_debugfs_init(void) { return; }
 #endif
 
+#ifdef CONFIG_ACPI_SCI_EMULATE
+int acpi_init_sci_emulate(void);
+#else
+static inline int acpi_init_sci_emulate(void) { return 0; }
+#endif
+
 /* --------------------------------------------------------------------------
                                   Power Resource
    -------------------------------------------------------------------------- */
diff --git a/drivers/acpi/sci_emu.c b/drivers/acpi/sci_emu.c
new file mode 100644
index 0000000..d972436
--- /dev/null
+++ b/drivers/acpi/sci_emu.c
@@ -0,0 +1,141 @@
+/*
+ *  Code to emulate SCI interrupt for Hotplug node insertion/removal
+ */
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/acpi.h>
+
+#include "internal.h"
+
+#include "acpica/accommon.h"
+#include "acpica/acnamesp.h"
+#include "acpica/acevents.h"
+
+#define _COMPONENT		ACPI_SYSTEM_COMPONENT
+ACPI_MODULE_NAME("sci_emu");
+
+static void acpi_sci_notify_client(char *acpi_name, u32 event);
+static int acpi_sci_notify_write_proc(struct file *file, const char *buffer, \
+	unsigned long count, void *data);
+struct proc_dir_entry *acpi_sci_dir;
+
+static int acpi_sci_notify_write_proc(struct file *file, const char *buffer,
+				      unsigned long count, void *data)
+{
+	u32 event;
+	char *name1 = NULL;
+	char *name2 = NULL;
+	char *end_name = NULL;
+	const char *delim = " ";
+	char *temp_buf = NULL;
+	char *temp_buf_addr = NULL;
+
+	temp_buf = kmalloc(count+1, GFP_ATOMIC);
+	if (!temp_buf) {
+		printk(KERN_WARNING PREFIX
+		 "acpi_sci_notify_wire_proc: Memory allocation failed\n");
+		return count;
+	}
+	temp_buf[count] = '\0';
+	temp_buf_addr = temp_buf;
+	memcpy(temp_buf, buffer, count);
+	name1 = strsep(&temp_buf, delim);
+	name2 = strsep(&temp_buf, delim);
+
+	if (name1 && name2)
+		event = simple_strtoul(name2, &end_name, 10);
+	else {
+		printk(KERN_WARNING PREFIX "unknown device\n");
+		kfree(temp_buf_addr);
+		return count;
+	}
+
+	printk(KERN_INFO PREFIX
+		"ACPI device name is <%s>, event code is <%d>\n",
+		name1, event);
+
+	acpi_sci_notify_client(name1, event);
+
+	kfree(temp_buf_addr);
+
+	return count;
+}
+
+static void acpi_sci_notify_client(char *acpi_name, u32 event)
+{
+	struct acpi_namespace_node *node;
+	acpi_status status, status1;
+	acpi_handle hlsb, hsb;
+	union acpi_operand_object *obj_desc;
+
+	status = acpi_get_handle(NULL, "\\_SB", &hsb);
+	status1 = acpi_get_handle(hsb, acpi_name, &hlsb);
+	if (ACPI_FAILURE(status) || ACPI_FAILURE(status1)) {
+		printk(KERN_ERR PREFIX
+	"acpi getting handle to <\\_SB.%s> failed inside notify_client\n",
+			acpi_name);
+		return;
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR PREFIX "Acquiring acpi namespace mutext failed\n");
+		return;
+	}
+
+	node = acpi_ns_validate_handle(hlsb);
+	if (!node) {
+		acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+		printk(KERN_ERR PREFIX "Mapping handle to node failed\n");
+		return;
+	}
+
+	/*
+	 * Check for internal object and make sure there is a handler
+	 * registered for this object
+	 */
+	obj_desc = acpi_ns_get_attached_object(node);
+	if (obj_desc) {
+		if (obj_desc->common_notify.system_notify) {
+			/*
+			 * Release the lock and queue the item for later
+			 * exectuion
+			 */
+			acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+			status = acpi_ev_queue_notify_request(node, event);
+			if (ACPI_FAILURE(status))
+				printk(KERN_ERR PREFIX "acpi_ev_queue_notify_request failed\n");
+			else
+				printk(KERN_INFO PREFIX "Notify event is queued\n");
+			return;
+		}
+	} else {
+		printk(KERN_INFO PREFIX "Notify handler not registered for this device\n");
+	}
+
+	acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+	return;
+}
+
+int __init acpi_init_sci_emulate(void)
+{
+	struct proc_dir_entry   *notify_entry = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_init_sci_emulate");
+
+	acpi_sci_dir = proc_mkdir("sci", acpi_root_dir);
+	if (!acpi_sci_dir)
+		return_VALUE(-ENODEV);
+
+	notify_entry = create_proc_entry("notify", \
+		S_IWUGO|S_IRUGO, acpi_sci_dir);
+	if (!notify_entry) {
+		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
+			"Unable to create '%s' fs entry\n", "notify"));
+	} else {
+		notify_entry->write_proc = acpi_sci_notify_write_proc;
+		notify_entry->data = NULL;
+	}
+
+	return_VALUE(0);
+}
-- 
1.7.7

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

* [PATCH -v3 41/47] PCI, ACPI: Add acpi_pci_root_rescan()
       [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
                   ` (7 preceding siblings ...)
  2012-03-19  5:46 ` [PATCH -v3 39/47] ACPI: Enable SCI_EMULATE to manually simulate physical hotplug testing Yinghai Lu
@ 2012-03-19  5:46 ` Yinghai Lu
  8 siblings, 0 replies; 9+ messages in thread
From: Yinghai Lu @ 2012-03-19  5:46 UTC (permalink / raw)
  To: Jesse Barnes, x86
  Cc: Bjorn Helgaas, Andrew Morton, Linus Torvalds, Greg Kroah-Hartman,
	linux-pci, linux-kernel, Yinghai Lu, Len Brown, linux-acpi

It will rescan all acpi pci root if related pci root bus get removed before.

Signed-off-by: Yinghai <yinghai@kernel.org>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-acpi@vger.kernel.org
---
 drivers/acpi/pci_root_hp.c |   17 +++++++++++++++++
 include/linux/pci-acpi.h   |    7 +++++++
 2 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/pci_root_hp.c b/drivers/acpi/pci_root_hp.c
index d2ace81..e16b53d 100644
--- a/drivers/acpi/pci_root_hp.c
+++ b/drivers/acpi/pci_root_hp.c
@@ -269,3 +269,20 @@ static int __init acpi_pci_root_hp_init(void)
 }
 
 subsys_initcall(acpi_pci_root_hp_init);
+
+static acpi_status
+rescan_root_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	if (!acpi_is_root_bridge(handle))
+		return AE_OK;
+
+	handle_root_bridge_insertion(handle);
+
+	return AE_OK;
+}
+
+void acpi_pci_root_rescan(void)
+{
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+		ACPI_UINT32_MAX, rescan_root_bridge, NULL, NULL, NULL);
+}
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 4462350..ac93634 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -35,6 +35,13 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
 	return acpi_get_pci_rootbridge_handle(pci_domain_nr(pbus),
 					      pbus->number);
 }
+
+void acpi_pci_root_rescan(void);
+
+#else
+
+static inline void acpi_pci_root_rescan(void) { }
+
 #endif
 
 #ifdef CONFIG_ACPI_APEI
-- 
1.7.7


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

end of thread, other threads:[~2012-03-19  5:48 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1332135996-13860-1-git-send-email-yinghai@kernel.org>
2012-03-19  5:45 ` [PATCH -v3 02/47] PNPACPI: Fix device ref leaking in acpi_pnp_match Yinghai Lu
2012-03-19  5:46 ` [PATCH -v3 26/47] PCI, ACPI: Make acpi_pci_root_remove remove pci root bus too Yinghai Lu
2012-03-19  5:46 ` [PATCH -v3 28/47] PCI, ACPI: Add pci_root_hp hot removal notification support Yinghai Lu
2012-03-19  5:46 ` [PATCH -v3 29/47] PCI, ACPI: Add alloc_acpi_hp_work() Yinghai Lu
2012-03-19  5:46 ` [PATCH -v3 30/47] PCI, acpiphp: Use acpi_hp_work Yinghai Lu
2012-03-19  5:46 ` [PATCH -v3 31/47] PCI, pci_root_hp: " Yinghai Lu
2012-03-19  5:46 ` [PATCH -v3 32/47] PCI, ACPI: Make kacpi_hotplug_wq static Yinghai Lu
2012-03-19  5:46 ` [PATCH -v3 39/47] ACPI: Enable SCI_EMULATE to manually simulate physical hotplug testing Yinghai Lu
2012-03-19  5:46 ` [PATCH -v3 41/47] PCI, ACPI: Add acpi_pci_root_rescan() Yinghai Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox