public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
From: Shaohua Li <shaohua.li-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
To: acpi-dev <acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: Len <len.brown-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	Dominik Brodowski <linux-JhLEnvuH02M@public.gmane.org>,
	Adam Belay <ambx1-IBH0VoN/3vPQT0dZR+AlfA@public.gmane.org>
Subject: [RFC]convert ACPI driver model to Linux driver model - takes 2
Date: Thu, 13 Oct 2005 14:37:34 +0800	[thread overview]
Message-ID: <1129185454.9074.15.camel@linux-hp.sh.intel.com> (raw)

Hi,
This is the updated patch for the topic. In this version, I completely
convert devices in ACPI bus into Linux driver model. Now the device
driver for ACPI bus device should be a 'struct acpi_phys_driver'. Old
style driver (struct acpi_driver) now can't work for ACPI bus devices.
Here I still regard devices listed in DSDT but not belonging to any
physical bus as ACPI bus devices.
For back compatibility, old style driver model still applies to non-ACPI
bus devices. In the implementation, we register an old style driver
(acpi_dummy) for each acpi bus device, whose goal is to enumerate acpi
bus devices and prevent new old style driver binding with the devices. 
I tried to convert one ACPI driver (link device driver) to the new
model. It's quite easy.
I'm looking forward to your comments/suggestions.

Thanks,
Shaohua
---

 linux-2.6.14-rc3-root/drivers/acpi/scan.c     |  231 +++++++++++++++++++++++++-
 linux-2.6.14-rc3-root/include/acpi/acpi_bus.h |   34 +++
 2 files changed, 263 insertions(+), 2 deletions(-)

diff -puN drivers/acpi/scan.c~acpi_bus drivers/acpi/scan.c
--- linux-2.6.14-rc3/drivers/acpi/scan.c~acpi_bus	2005-10-11 14:13:26.000000000 +0800
+++ linux-2.6.14-rc3-root/drivers/acpi/scan.c	2005-10-13 13:59:08.000000000 +0800
@@ -112,6 +112,234 @@ static struct kset acpi_namespace_kset =
 	.hotplug_ops = &namespace_hotplug_ops,
 };
 
+/* ACPI phys bus */
+static int acpi_phys_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct acpi_phys_device *phys_dev = to_acpi_phys_dev(dev);
+	struct acpi_phys_driver *phys_drv = to_acpi_phys_drv(drv);
+	return !acpi_match_ids(phys_dev->acpi_dev, phys_drv->ids);
+}
+
+static int acpi_phys_bus_hotplug(struct device *dev, char **envp,
+	int num_envp, char *buffer, int buffer_size)
+{
+	int i = 0;
+	struct acpi_device *acpi_dev = to_acpi_phys_dev(dev)->acpi_dev;
+	char *scratch;
+	int length = 0;
+	struct acpi_compatible_id_list *cid_list;
+
+	scratch = buffer;
+	if (acpi_dev->flags.hardware_id) {
+		envp[i++] = scratch;
+		length += scnprintf(scratch, buffer_size - length, "HWID=%s",
+			acpi_dev->pnp.hardware_id);
+		if ((buffer_size - length <=0) || (i > num_envp))
+			return -ENOMEM;
+		++length;
+		scratch += length;
+	}
+	if (acpi_dev->flags.compatible_ids) {
+		int j;
+		cid_list = acpi_dev->pnp.cid_list;
+
+		/* multiple _CID entries */
+		for (j = 0; j < cid_list->count; j++)
+		{
+			envp[i++] = scratch;
+			length += scnprintf(scratch, buffer_size - length,
+				"COMPTID=%s", cid_list->id[j].value);
+			if ((buffer_size - length <=0) || (i > num_envp))
+				return -ENOMEM;
+			++length;
+			scratch += length;
+		}
+	}
+	envp[i] = NULL;
+
+	return 0;
+}
+
+static int acpi_phys_bus_suspend(struct device * dev, pm_message_t state)
+{
+	struct acpi_phys_device *phys_dev = to_acpi_phys_dev(dev);
+
+	if (!phys_dev->driver || !phys_dev->driver->suspend)
+		return 0;
+	return phys_dev->driver->suspend(phys_dev, state);
+}
+
+static int acpi_phys_bus_resume(struct device * dev)
+{
+	struct acpi_phys_device *phys_dev = to_acpi_phys_dev(dev);
+
+	if (!phys_dev->driver || !phys_dev->driver->resume)
+		return 0;
+	return phys_dev->driver->resume(phys_dev);
+}
+
+static struct bus_type acpi_phys_bus_type = {
+	.name = "acpi",
+	.match = acpi_phys_bus_match,
+	.hotplug = acpi_phys_bus_hotplug,
+	.suspend = acpi_phys_bus_suspend,
+	.resume = acpi_phys_bus_resume,
+};
+
+static LIST_HEAD(acpi_phys_devices);
+static DEFINE_SPINLOCK(acpi_phys_bus_lock);
+static struct acpi_phys_device *phys_root;
+
+static void acpi_phys_device_release(struct device *dev)
+{
+	struct acpi_phys_device *phys_dev = to_acpi_phys_dev(dev);
+	kfree(phys_dev);
+}
+
+static int acpi_phys_bus_add(struct acpi_device *acpi_dev)
+{
+	struct acpi_phys_device *phys_dev;
+
+	phys_dev = kzalloc(sizeof(struct acpi_phys_device), GFP_KERNEL);
+	if (!phys_dev)
+		return -ENOMEM;
+
+	spin_lock(&acpi_phys_bus_lock);
+	list_add_tail(&phys_dev->node, &acpi_phys_devices);
+	spin_unlock(&acpi_phys_bus_lock);
+
+	phys_dev->acpi_dev = acpi_dev;
+	phys_dev->phys_dev.parent = &phys_root->phys_dev;
+	phys_dev->phys_dev.bus = &acpi_phys_bus_type;
+	device_initialize(&phys_dev->phys_dev);
+	sprintf(phys_dev->phys_dev.bus_id, "%s", acpi_dev->pnp.bus_id);
+	phys_dev->phys_dev.release = acpi_phys_device_release;
+	device_add(&phys_dev->phys_dev);
+	return 0;
+}
+
+static int acpi_phys_bus_remove(struct acpi_device *acpi_dev, int type)
+{
+	struct acpi_phys_device *phys_dev, *tmp, *find = NULL;
+
+	spin_lock(&acpi_phys_bus_lock);
+	list_for_each_entry_safe(phys_dev, tmp, &acpi_phys_devices, node) {
+		if (phys_dev->acpi_dev == acpi_dev) {
+			find = phys_dev;
+			list_del(&find->node);
+			break;
+		}
+	}
+	spin_unlock(&acpi_phys_bus_lock);
+	if (find)
+		device_unregister(&find->phys_dev);
+	return 0;
+}
+
+/* this driver is linking acpi device with acpi phys device */
+static struct acpi_driver dummy_driver = {
+	.name = "acpi_dummy",
+	/* List all ids of ACPI phys devices */
+	.ids =
+//		"PNP0C09," /* EC */
+//		"ACPI0003," /* AC */
+//		"PNP0C0F," /* Link */
+//		"PNP0C0A," /* battery */
+//		"PNP0C0C,PNP0C0E,PNP0C0D,ACPI_FPB,ACPI_FSB," /* button */
+//		"PNP0C0B," /* fan */
+//		"PNP0A03," /* PCI root */
+//		ACPI_POWER_HID"," /* power */
+//		ACPI_PROCESSOR_HID"," /* CPU */
+//		ACPI_THERMAL_HID"," /* thermal */
+		"",
+	.ops = {
+		.add = acpi_phys_bus_add,
+		.remove = acpi_phys_bus_remove,
+	},
+};
+
+static int __init acpi_phys_bus_init(void)
+{
+	bus_register(&acpi_phys_bus_type);
+
+	phys_root = kzalloc(sizeof(struct acpi_phys_device), GFP_KERNEL);
+	if (!phys_root)
+		return -ENOMEM;
+
+	phys_root->acpi_dev = acpi_root;
+	phys_root->phys_dev.release = acpi_phys_device_release;
+	sprintf(phys_root->phys_dev.bus_id, "%s", acpi_root->pnp.bus_id);
+	device_register(&phys_root->phys_dev);
+
+	/* enumerate devices */
+	acpi_bus_register_driver(&dummy_driver);
+	return 0;
+}
+
+
+static int acpi_phys_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct acpi_phys_device *phys_dev = to_acpi_phys_dev(dev);
+	struct acpi_phys_driver *phys_drv = to_acpi_phys_drv(dev->driver);
+
+	get_device(dev);
+	if (!phys_dev->driver && phys_drv->probe) {
+		error = phys_drv->probe(phys_dev);
+		if (error >= 0)
+			phys_dev->driver = phys_drv;
+	}
+	if (error < 0)
+		put_device(dev);
+	return error;
+}
+
+static int acpi_phys_device_remove(struct device * dev)
+{
+	struct acpi_phys_device *phys_dev = to_acpi_phys_dev(dev);
+	struct acpi_phys_driver *phys_drv = phys_dev->driver;
+
+	if (phys_drv) {
+		if (phys_drv->remove)
+			phys_drv->remove(phys_dev);
+		phys_dev->driver = NULL;
+	}
+	put_device(dev);
+	return 0;
+}
+
+static void acpi_phys_device_shutdown(struct device *dev)
+{
+	struct acpi_phys_device *phys_dev = to_acpi_phys_dev(dev);
+
+	if (!phys_dev->driver || !phys_dev->driver->shutdown)
+		return;
+
+	phys_dev->driver->shutdown(phys_dev);
+}
+
+int acpi_phys_driver_register(struct acpi_phys_driver *drv)
+{
+	int error;
+	/*FIXME: add to a list */
+	drv->phys_drv.name = drv->name;
+	drv->phys_drv.bus = &acpi_phys_bus_type;
+	drv->phys_drv.probe = acpi_phys_device_probe;
+	drv->phys_drv.remove = acpi_phys_device_remove;
+	drv->phys_drv.shutdown = acpi_phys_device_shutdown;
+	drv->phys_drv.owner = drv->owner;
+	error = driver_register(&drv->phys_drv);
+	return error;
+}
+EXPORT_SYMBOL(acpi_phys_driver_register);
+
+void acpi_phys_driver_unregister(struct acpi_phys_driver *drv)
+{
+	driver_unregister(&drv->phys_drv);
+}
+EXPORT_SYMBOL(acpi_phys_driver_unregister);
+/*-----------------------------------*/
+
 static void acpi_device_register(struct acpi_device *device,
 				 struct acpi_device *parent)
 {
@@ -1400,8 +1628,9 @@ static int __init acpi_scan_init(void)
 
 	if (result)
 		acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+	acpi_phys_bus_init();
 
-      Done:
+Done:
 	return_VALUE(result);
 }
 
diff -puN include/acpi/acpi_bus.h~acpi_bus include/acpi/acpi_bus.h
--- linux-2.6.14-rc3/include/acpi/acpi_bus.h~acpi_bus	2005-10-11 14:13:26.000000000 +0800
+++ linux-2.6.14-rc3-root/include/acpi/acpi_bus.h	2005-10-13 10:43:21.000000000 +0800
@@ -28,6 +28,7 @@
 
 #include <linux/kobject.h>
 
+#include <linux/device.h>
 #include <acpi/acpi.h>
 
 #define PREFIX			"ACPI: "
@@ -300,6 +301,38 @@ struct acpi_device {
 
 #define acpi_driver_data(d)	((d)->driver_data)
 
+/* acpi bus type for real ACPI device */
+struct acpi_phys_device {
+	struct list_head node;
+	struct acpi_device *acpi_dev;
+	struct device phys_dev;
+	struct acpi_phys_driver *driver;
+	void *driver_data;
+};
+
+#define acpi_phys_driver_data(d) ((d)->driver_data)
+
+struct acpi_phys_driver {
+//	struct list_head node;
+	char name[80];
+	char class[80];
+	struct module *owner;
+	char *ids;
+	int (*probe)(struct acpi_phys_device *dev);
+	void (*remove) (struct acpi_phys_device *dev);
+	int  (*suspend) (struct acpi_phys_device *dev, pm_message_t state);
+	int  (*resume) (struct acpi_phys_device *dev);
+	void (*shutdown) (struct acpi_phys_device *dev);
+
+	struct device_driver    phys_drv;
+};
+
+#define to_acpi_phys_dev(n) container_of(n, struct acpi_phys_device, phys_dev)
+#define to_acpi_phys_drv(n) container_of(n, struct acpi_phys_driver, phys_drv)
+int acpi_phys_driver_register(struct acpi_phys_driver *drv);
+void acpi_phys_driver_unregister(struct acpi_phys_driver *drv);
+
+
 /*
  * Events
  * ------
@@ -339,7 +372,6 @@ void acpi_remove_dir(struct acpi_device 
 /*
  * Bind physical devices with ACPI devices
  */
-#include <linux/device.h>
 struct acpi_bus_type {
 	struct list_head list;
 	struct bus_type *bus;
_




-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl

             reply	other threads:[~2005-10-13  6:37 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-10-13  6:37 Shaohua Li [this message]
     [not found] ` <1129185454.9074.15.camel-ECwVeV2eNyQD0+JXs3kMbRL4W9x8LtSr@public.gmane.org>
2005-10-13 20:43   ` [RFC]convert ACPI driver model to Linux driver model - takes 2 Bjorn Helgaas
     [not found]     ` <200510131443.47844.bjorn.helgaas-VXdhtT5mjnY@public.gmane.org>
2005-10-14  1:13       ` Shaohua Li
     [not found]         ` <1129252436.3948.12.camel-ECwVeV2eNyQD0+JXs3kMbRL4W9x8LtSr@public.gmane.org>
2005-10-14  3:21           ` Bjorn Helgaas
2005-10-20 17:04   ` Bjorn Helgaas
  -- strict thread matches above, loose matches on Subject: below --
2005-10-13  7:45 Yu, Luming
2005-10-13  8:20 ` Shaohua Li
2005-10-13  8:18 mika.penttila-9Aww8k/80nUxHbG02/KK1g
     [not found] ` <20051013081837.PTGN24578.fep01-app.kolumbus.fi-7B1qVitd7rZYRdgNIgFt/t8DI8KqlI9s@public.gmane.org>
2005-10-13  8:32   ` Shaohua Li
2005-10-14  9:35 Li, Shaohua
2005-10-14 12:47 ` Matthew Wilcox
     [not found]   ` <20051014124749.GD16113-6jwH94ZQLHl74goWV3ctuw@public.gmane.org>
2005-10-18  1:30     ` Shaohua Li
     [not found]       ` <1129599034.3965.6.camel-ECwVeV2eNyQD0+JXs3kMbRL4W9x8LtSr@public.gmane.org>
2005-10-18 17:32         ` Rajesh Shah
2005-10-14 15:54 ` Bjorn Helgaas
     [not found]   ` <200510140954.52206.bjorn.helgaas-VXdhtT5mjnY@public.gmane.org>
2005-10-18  3:06     ` Shaohua Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1129185454.9074.15.camel@linux-hp.sh.intel.com \
    --to=shaohua.li-ral2jqcrhueavxtiumwx3w@public.gmane.org \
    --cc=acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    --cc=ambx1-IBH0VoN/3vPQT0dZR+AlfA@public.gmane.org \
    --cc=len.brown-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=linux-JhLEnvuH02M@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox