Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=56b8756b3bc8812837a21f3e066dba1b489e071e
Commit:     56b8756b3bc8812837a21f3e066dba1b489e071e
Parent:     59b19106f3f20487093ea06c8220426147cf7835
Author:     [EMAIL PROTECTED] <[EMAIL PROTECTED]>
AuthorDate: Mon Apr 9 10:19:05 2007 +0200
Committer:  Len Brown <[EMAIL PROTECTED]>
CommitDate: Tue Apr 10 16:01:18 2007 -0400

    sony-laptop: Prepare the platform driver for multiple users.
    
    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 <[EMAIL PROTECTED]>
    Signed-off-by: Len Brown <[EMAIL PROTECTED]>
---
 drivers/misc/sony-laptop.c |  212 +++++++++++++++++++++++---------------------
 1 files changed, 112 insertions(+), 100 deletions(-)

diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index e67189a..2d05d5b 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -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(struct device *dev,
        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_device *device)
        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_device *device)
 
        }
 
-       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_device *device)
 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_device *device, int 
type)
        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");
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to