public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
From: malattia@linux.it
To: lenb@kernel.org
Cc: linux-acpi@vger.kernel.org, akpm@linux-foundation.org,
	stelian@popies.net
Subject: [patch 2/9] Prepare the platform driver for multiple users.
Date: Mon, 9 Apr 2007 19:20:19 +0200	[thread overview]
Message-ID: <20070409172019.GC10646@inferi.kami.home> (raw)
In-Reply-To: 20070409081903.057292676@linux.it

[-- Attachment #1: 0002-prepare-pfdriver-for-multiple-users.patch --]
[-- Type: text/plain, Size: 7255 bytes --]

Both the SNC and SPIC device drivers will create attributes and thus
there's the need to have an internal usage count to avoid
re-registering or de-registering at the wrong time.

Signed-off-by: Mattia Dongili <malattia@linux.it>
---
 drivers/misc/sony-laptop.c |  212 ++++++++++++++++++++++++++++++----------------------------
 1 file changed, 112 insertions(+), 100 deletions(-)

Index: linux-2.6/drivers/misc/sony-laptop.c
===================================================================
--- linux-2.6.orig/drivers/misc/sony-laptop.c	2007-03-16 16:08:17.490191147 +0100
+++ linux-2.6/drivers/misc/sony-laptop.c	2007-03-18 18:50:17.769519953 +0100
@@ -54,6 +54,64 @@ module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "set this to 1 (and RTFM) if you want to help "
 		 "the development of this driver");
 
+/*********** Platform Device ***********/
+
+static atomic_t sony_pf_users = ATOMIC_INIT(0);
+static struct platform_driver sony_pf_driver = {
+	.driver = {
+		   .name = "sony-laptop",
+		   .owner = THIS_MODULE,
+		   }
+};
+static struct platform_device *sony_pf_device;
+
+static int sony_pf_add(void)
+{
+	int ret = 0;
+
+	/* don't run again if already initialized */
+	if (atomic_add_return(1, &sony_pf_users) > 1)
+		return 0;
+
+	ret = platform_driver_register(&sony_pf_driver);
+	if (ret)
+		goto out;
+
+	sony_pf_device = platform_device_alloc("sony-laptop", -1);
+	if (!sony_pf_device) {
+		ret = -ENOMEM;
+		goto out_platform_registered;
+	}
+
+	ret = platform_device_add(sony_pf_device);
+	if (ret)
+		goto out_platform_alloced;
+
+	return 0;
+
+      out_platform_alloced:
+	platform_device_put(sony_pf_device);
+	sony_pf_device = NULL;
+      out_platform_registered:
+	platform_driver_unregister(&sony_pf_driver);
+      out:
+	atomic_dec(&sony_pf_users);
+	return ret;
+}
+
+static void sony_pf_remove(void)
+{
+	/* deregister only after the last user has gone */
+	if (!atomic_dec_and_test(&sony_pf_users))
+		return;
+
+	platform_device_del(sony_pf_device);
+	platform_device_put(sony_pf_device);
+	platform_driver_unregister(&sony_pf_driver);
+}
+
+/*********** SNC (SNY5001) Device ***********/
+
 static ssize_t sony_nc_sysfs_show(struct device *, struct device_attribute *,
 			      char *);
 static ssize_t sony_nc_sysfs_store(struct device *, struct device_attribute *,
@@ -279,104 +337,6 @@ static ssize_t sony_nc_sysfs_store(struc
 	return count;
 }
 
-/*
- * Platform device
- */
-static struct platform_driver sncpf_driver = {
-	.driver = {
-		   .name = "sony-laptop",
-		   .owner = THIS_MODULE,
-		   }
-};
-static struct platform_device *sncpf_device;
-
-static int sony_nc_pf_add(void)
-{
-	acpi_handle handle;
-	struct sony_nc_value *item;
-	int ret = 0;
-
-	ret = platform_driver_register(&sncpf_driver);
-	if (ret)
-		goto out;
-
-	sncpf_device = platform_device_alloc("sony-laptop", -1);
-	if (!sncpf_device) {
-		ret = -ENOMEM;
-		goto out_platform_registered;
-	}
-
-	ret = platform_device_add(sncpf_device);
-	if (ret)
-		goto out_platform_alloced;
-
-	for (item = sony_nc_values; item->name; ++item) {
-
-		if (!debug && item->debug)
-			continue;
-
-		/* find the available acpiget as described in the DSDT */
-		for (; item->acpiget && *item->acpiget; ++item->acpiget) {
-			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
-							 *item->acpiget,
-							 &handle))) {
-				if (debug)
-					printk(LOG_PFX "Found %s getter: %s\n",
-					       item->name, *item->acpiget);
-				item->devattr.attr.mode |= S_IRUGO;
-				break;
-			}
-		}
-
-		/* find the available acpiset as described in the DSDT */
-		for (; item->acpiset && *item->acpiset; ++item->acpiset) {
-			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
-							 *item->acpiset,
-							 &handle))) {
-				if (debug)
-					printk(LOG_PFX "Found %s setter: %s\n",
-					       item->name, *item->acpiset);
-				item->devattr.attr.mode |= S_IWUSR;
-				break;
-			}
-		}
-
-		if (item->devattr.attr.mode != 0) {
-			ret =
-			    device_create_file(&sncpf_device->dev,
-					       &item->devattr);
-			if (ret)
-				goto out_sysfs;
-		}
-	}
-
-	return 0;
-
-      out_sysfs:
-	for (item = sony_nc_values; item->name; ++item) {
-		device_remove_file(&sncpf_device->dev, &item->devattr);
-	}
-	platform_device_del(sncpf_device);
-      out_platform_alloced:
-	platform_device_put(sncpf_device);
-      out_platform_registered:
-	platform_driver_unregister(&sncpf_driver);
-      out:
-	return ret;
-}
-
-static void sony_nc_pf_remove(void)
-{
-	struct sony_nc_value *item;
-
-	for (item = sony_nc_values; item->name; ++item) {
-		device_remove_file(&sncpf_device->dev, &item->devattr);
-	}
-
-	platform_device_del(sncpf_device);
-	platform_device_put(sncpf_device);
-	platform_driver_unregister(&sncpf_driver);
-}
 
 /*
  * Backlight device
@@ -455,6 +415,7 @@ static int sony_nc_add(struct acpi_devic
 	acpi_status status;
 	int result = 0;
 	acpi_handle handle;
+	struct sony_nc_value *item;
 
 	sony_nc_acpi_device = device;
 
@@ -497,13 +458,59 @@ static int sony_nc_add(struct acpi_devic
 
 	}
 
-	if (sony_nc_pf_add())
+	if (sony_pf_add())
 		goto outbacklight;
 
+	/* create sony_pf sysfs attributes related to the SNC device */
+	for (item = sony_nc_values; item->name; ++item) {
+
+		if (!debug && item->debug)
+			continue;
+
+		/* find the available acpiget as described in the DSDT */
+		for (; item->acpiget && *item->acpiget; ++item->acpiget) {
+			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
+							 *item->acpiget,
+							 &handle))) {
+				if (debug)
+					printk(LOG_PFX "Found %s getter: %s\n",
+					       item->name, *item->acpiget);
+				item->devattr.attr.mode |= S_IRUGO;
+				break;
+			}
+		}
+
+		/* find the available acpiset as described in the DSDT */
+		for (; item->acpiset && *item->acpiset; ++item->acpiset) {
+			if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
+							 *item->acpiset,
+							 &handle))) {
+				if (debug)
+					printk(LOG_PFX "Found %s setter: %s\n",
+					       item->name, *item->acpiset);
+				item->devattr.attr.mode |= S_IWUSR;
+				break;
+			}
+		}
+
+		if (item->devattr.attr.mode != 0) {
+			result =
+			    device_create_file(&sony_pf_device->dev,
+					       &item->devattr);
+			if (result)
+				goto out_sysfs;
+		}
+	}
+
 	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully installed\n");
 
 	return 0;
 
+      out_sysfs:
+	for (item = sony_nc_values; item->name; ++item) {
+		device_remove_file(&sony_pf_device->dev, &item->devattr);
+	}
+	sony_pf_remove();
       outbacklight:
 	if (sony_backlight_device)
 		backlight_device_unregister(sony_backlight_device);
@@ -520,6 +527,7 @@ static int sony_nc_add(struct acpi_devic
 static int sony_nc_remove(struct acpi_device *device, int type)
 {
 	acpi_status status;
+	struct sony_nc_value *item;
 
 	if (sony_backlight_device)
 		backlight_device_unregister(sony_backlight_device);
@@ -532,7 +540,11 @@ static int sony_nc_remove(struct acpi_de
 	if (ACPI_FAILURE(status))
 		printk(LOG_PFX "unable to remove notify handler\n");
 
-	sony_nc_pf_remove();
+	for (item = sony_nc_values; item->name; ++item) {
+		device_remove_file(&sony_pf_device->dev, &item->devattr);
+	}
+
+	sony_pf_remove();
 
 	printk(KERN_INFO SONY_NC_DRIVER_NAME " successfully removed\n");
 

--
-- 
mattia
:wq!

  parent reply	other threads:[~2007-04-09 17:22 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20070409081903.057292676@linux.it>
2007-04-09 17:18 ` [patch 1/9] Remove ACPI references from variable and function names malattia
2007-04-09 17:20 ` malattia [this message]
2007-04-09 17:22 ` [patch 3/9] Add debug macros also used by the sonypi reimplementation malattia
2007-04-09 17:26 ` [patch 4/9] Add SNY6001 device handling (sonypi reimplementation) malattia
2007-04-09 17:28 ` [patch 5/9] Unify the input subsystem event forwarding malattia
2007-04-09 17:28 ` [patch 6/9] additional platform attributes coming from SNY6001 malattia
2007-04-09 17:31 ` [patch 7/9] sanitize printks malattia
2007-04-09 17:31 ` [patch 8/9] update documentation and Kconfig help malattia
2007-04-09 17:31 ` [patch 9/9] sonypi backward compatibility code malattia
2007-04-10 20:13 ` [patch 0/9] [RFC] sonypi ACPI reimplementation (resend 3) Len Brown
2007-04-10 22:04   ` Mattia Dongili
2007-04-12  9:20     ` Stelian Pop

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=20070409172019.GC10646@inferi.kami.home \
    --to=malattia@linux.it \
    --cc=akpm@linux-foundation.org \
    --cc=lenb@kernel.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=stelian@popies.net \
    /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