linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / firmware / dcdbas.c
index 339f405..4652512 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/types.h>
-#include <linux/mutex.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
 
@@ -49,7 +48,7 @@ static u8 *smi_data_buf;
 static dma_addr_t smi_data_buf_handle;
 static unsigned long smi_data_buf_size;
 static u32 smi_data_buf_phys_addr;
-static DEFINE_MUTEX(smi_data_lock);
+static DECLARE_MUTEX(smi_data_lock);
 
 static unsigned int host_control_action;
 static unsigned int host_control_smi_type;
@@ -140,9 +139,9 @@ static ssize_t smi_data_buf_size_store(struct device *dev,
        buf_size = simple_strtoul(buf, NULL, 10);
 
        /* make sure SMI data buffer is at least buf_size */
-       mutex_lock(&smi_data_lock);
+       down(&smi_data_lock);
        ret = smi_data_buf_realloc(buf_size);
-       mutex_unlock(&smi_data_lock);
+       up(&smi_data_lock);
        if (ret)
                return ret;
 
@@ -155,7 +154,7 @@ static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
        size_t max_read;
        ssize_t ret;
 
-       mutex_lock(&smi_data_lock);
+       down(&smi_data_lock);
 
        if (pos >= smi_data_buf_size) {
                ret = 0;
@@ -166,7 +165,7 @@ static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
        ret = min(max_read, count);
        memcpy(buf, smi_data_buf + pos, ret);
 out:
-       mutex_unlock(&smi_data_lock);
+       up(&smi_data_lock);
        return ret;
 }
 
@@ -175,7 +174,7 @@ static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
 {
        ssize_t ret;
 
-       mutex_lock(&smi_data_lock);
+       down(&smi_data_lock);
 
        ret = smi_data_buf_realloc(pos + count);
        if (ret)
@@ -184,7 +183,7 @@ static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
        memcpy(smi_data_buf + pos, buf, count);
        ret = count;
 out:
-       mutex_unlock(&smi_data_lock);
+       up(&smi_data_lock);
        return ret;
 }
 
@@ -202,9 +201,9 @@ static ssize_t host_control_action_store(struct device *dev,
        ssize_t ret;
 
        /* make sure buffer is available for host control command */
-       mutex_lock(&smi_data_lock);
+       down(&smi_data_lock);
        ret = smi_data_buf_realloc(sizeof(struct apm_cmd));
-       mutex_unlock(&smi_data_lock);
+       up(&smi_data_lock);
        if (ret)
                return ret;
 
@@ -303,7 +302,7 @@ static ssize_t smi_request_store(struct device *dev,
        unsigned long val = simple_strtoul(buf, NULL, 10);
        ssize_t ret;
 
-       mutex_lock(&smi_data_lock);
+       down(&smi_data_lock);
 
        if (smi_data_buf_size < sizeof(struct smi_cmd)) {
                ret = -ENODEV;
@@ -335,7 +334,7 @@ static ssize_t smi_request_store(struct device *dev,
        }
 
 out:
-       mutex_unlock(&smi_data_lock);
+       up(&smi_data_lock);
        return ret;
 }
 
@@ -484,15 +483,26 @@ static void dcdbas_host_control(void)
 static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
                                void *unused)
 {
+       static unsigned int notify_cnt = 0;
+
        switch (code) {
        case SYS_DOWN:
        case SYS_HALT:
        case SYS_POWER_OFF:
                if (host_control_on_shutdown) {
                        /* firmware is going to perform host control action */
-                       printk(KERN_WARNING "Please wait for shutdown "
-                              "action to complete...\n");
-                       dcdbas_host_control();
+                       if (++notify_cnt == 2) {
+                               printk(KERN_WARNING
+                                      "Please wait for shutdown "
+                                      "action to complete...\n");
+                               dcdbas_host_control();
+                       }
+                       /*
+                        * register again and initiate the host control
+                        * action on the second notification to allow
+                        * everyone that registered to be notified
+                        */
+                       register_reboot_notifier(nb);
                }
                break;
        }
@@ -503,7 +513,7 @@ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code,
 static struct notifier_block dcdbas_reboot_nb = {
        .notifier_call = dcdbas_reboot_notify,
        .next = NULL,
-       .priority = INT_MIN
+       .priority = 0
 };
 
 static DCDBAS_BIN_ATTR_RW(smi_data);
@@ -520,27 +530,30 @@ static DCDBAS_DEV_ATTR_RW(host_control_action);
 static DCDBAS_DEV_ATTR_RW(host_control_smi_type);
 static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown);
 
-static struct attribute *dcdbas_dev_attrs[] = {
-       &dev_attr_smi_data_buf_size.attr,
-       &dev_attr_smi_data_buf_phys_addr.attr,
-       &dev_attr_smi_request.attr,
-       &dev_attr_host_control_action.attr,
-       &dev_attr_host_control_smi_type.attr,
-       &dev_attr_host_control_on_shutdown.attr,
+static struct device_attribute *dcdbas_dev_attrs[] = {
+       &dev_attr_smi_data_buf_size,
+       &dev_attr_smi_data_buf_phys_addr,
+       &dev_attr_smi_request,
+       &dev_attr_host_control_action,
+       &dev_attr_host_control_smi_type,
+       &dev_attr_host_control_on_shutdown,
        NULL
 };
 
-static struct attribute_group dcdbas_attr_group = {
-       .attrs = dcdbas_dev_attrs,
-};
-
-static int __devinit dcdbas_probe(struct platform_device *dev)
+/**
+ * dcdbas_init: initialize driver
+ */
+static int __init dcdbas_init(void)
 {
-       int i, error;
+       int i;
 
        host_control_action = HC_ACTION_NONE;
        host_control_smi_type = HC_SMITYPE_NONE;
 
+       dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+       if (IS_ERR(dcdbas_pdev))
+               return PTR_ERR(dcdbas_pdev);
+
        /*
         * BIOS SMI calls require buffer addresses be in 32-bit address space.
         * This is done by setting the DMA mask below.
@@ -548,79 +561,19 @@ static int __devinit dcdbas_probe(struct platform_device *dev)
        dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
        dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask;
 
-       error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
-       if (error)
-               return error;
-
-       for (i = 0; dcdbas_bin_attrs[i]; i++) {
-               error = sysfs_create_bin_file(&dev->dev.kobj,
-                                             dcdbas_bin_attrs[i]);
-               if (error) {
-                       while (--i >= 0)
-                               sysfs_remove_bin_file(&dev->dev.kobj,
-                                                     dcdbas_bin_attrs[i]);
-                       sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
-                       return error;
-               }
-       }
-
        register_reboot_notifier(&dcdbas_reboot_nb);
 
-       dev_info(&dev->dev, "%s (version %s)\n",
-                DRIVER_DESCRIPTION, DRIVER_VERSION);
-
-       return 0;
-}
-
-static int __devexit dcdbas_remove(struct platform_device *dev)
-{
-       int i;
-
-       unregister_reboot_notifier(&dcdbas_reboot_nb);
        for (i = 0; dcdbas_bin_attrs[i]; i++)
-               sysfs_remove_bin_file(&dev->dev.kobj, dcdbas_bin_attrs[i]);
-       sysfs_remove_group(&dev->dev.kobj, &dcdbas_attr_group);
-
-       return 0;
-}
-
-static struct platform_driver dcdbas_driver = {
-       .driver         = {
-               .name   = DRIVER_NAME,
-               .owner  = THIS_MODULE,
-       },
-       .probe          = dcdbas_probe,
-       .remove         = __devexit_p(dcdbas_remove),
-};
-
-/**
- * dcdbas_init: initialize driver
- */
-static int __init dcdbas_init(void)
-{
-       int error;
+               sysfs_create_bin_file(&dcdbas_pdev->dev.kobj,
+                                     dcdbas_bin_attrs[i]);
 
-       error = platform_driver_register(&dcdbas_driver);
-       if (error)
-               return error;
+       for (i = 0; dcdbas_dev_attrs[i]; i++)
+               device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]);
 
-       dcdbas_pdev = platform_device_alloc(DRIVER_NAME, -1);
-       if (!dcdbas_pdev) {
-               error = -ENOMEM;
-               goto err_unregister_driver;
-       }
-
-       error = platform_device_add(dcdbas_pdev);
-       if (error)
-               goto err_free_device;
+       dev_info(&dcdbas_pdev->dev, "%s (version %s)\n",
+                DRIVER_DESCRIPTION, DRIVER_VERSION);
 
        return 0;
-
- err_free_device:
-       platform_device_put(dcdbas_pdev);
- err_unregister_driver:
-       platform_driver_unregister(&dcdbas_driver);
-       return error;
 }
 
 /**
@@ -635,15 +588,6 @@ static void __exit dcdbas_exit(void)
        unregister_reboot_notifier(&dcdbas_reboot_nb);
        smi_data_buf_free();
        platform_device_unregister(dcdbas_pdev);
-       platform_driver_unregister(&dcdbas_driver);
-
-       /*
-        * We have to free the buffer here instead of dcdbas_remove
-        * because only in module exit function we can be sure that
-        * all sysfs attributes belonging to this module have been
-        * released.
-        */
-       smi_data_buf_free();
 }
 
 module_init(dcdbas_init);