drivers: Push down BKL into various drivers
[safe/jmp/linux-2.6] / drivers / char / ipmi / ipmi_devintf.c
index 81fcf0c..d8ec92a 100644 (file)
@@ -35,8 +35,8 @@
 #include <linux/moduleparam.h>
 #include <linux/errno.h>
 #include <asm/system.h>
-#include <linux/sched.h>
 #include <linux/poll.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/ipmi.h>
@@ -44,6 +44,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/compat.h>
+#include <linux/smp_lock.h>
 
 struct ipmi_file_private
 {
@@ -101,7 +102,9 @@ static int ipmi_fasync(int fd, struct file *file, int on)
        struct ipmi_file_private *priv = file->private_data;
        int                      result;
 
+       lock_kernel(); /* could race against open() otherwise */
        result = fasync_helper(fd, file, on, &priv->fasync_queue);
+       unlock_kernel();
 
        return (result);
 }
@@ -122,6 +125,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
        if (!priv)
                return -ENOMEM;
 
+       lock_kernel();
        priv->file = file;
 
        rv = ipmi_create_user(if_num,
@@ -130,7 +134,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
                              &(priv->user));
        if (rv) {
                kfree(priv);
-               return rv;
+               goto out;
        }
 
        file->private_data = priv;
@@ -145,7 +149,9 @@ static int ipmi_open(struct inode *inode, struct file *file)
        priv->default_retries = -1;
        priv->default_retry_time_ms = 0;
 
-       return 0;
+out:
+       unlock_kernel();
+       return rv;
 }
 
 static int ipmi_release(struct inode *inode, struct file *file)
@@ -157,8 +163,6 @@ static int ipmi_release(struct inode *inode, struct file *file)
        if (rv)
                return rv;
 
-       ipmi_fasync (-1, file, 0);
-
        /* FIXME - free the messages in the list. */
        kfree(priv);
 
@@ -224,8 +228,7 @@ static int handle_send_req(ipmi_user_t     user,
        return rv;
 }
 
-static int ipmi_ioctl(struct inode  *inode,
-                     struct file   *file,
+static int ipmi_ioctl(struct file   *file,
                      unsigned int  cmd,
                      unsigned long data)
 {
@@ -596,11 +599,53 @@ static int ipmi_ioctl(struct inode  *inode,
                rv = 0;
                break;
        }
+
+       case IPMICTL_GET_MAINTENANCE_MODE_CMD:
+       {
+               int mode;
+
+               mode = ipmi_get_maintenance_mode(priv->user);
+               if (copy_to_user(arg, &mode, sizeof(mode))) {
+                       rv = -EFAULT;
+                       break;
+               }
+               rv = 0;
+               break;
+       }
+
+       case IPMICTL_SET_MAINTENANCE_MODE_CMD:
+       {
+               int mode;
+
+               if (copy_from_user(&mode, arg, sizeof(mode))) {
+                       rv = -EFAULT;
+                       break;
+               }
+               rv = ipmi_set_maintenance_mode(priv->user, mode);
+               break;
+       }
        }
   
        return rv;
 }
 
+/*
+ * Note: it doesn't make sense to take the BKL here but
+ *       not in compat_ipmi_ioctl. -arnd
+ */
+static long ipmi_unlocked_ioctl(struct file   *file,
+                               unsigned int  cmd,
+                               unsigned long data)
+{
+       int ret;
+
+       lock_kernel();
+       ret = ipmi_ioctl(file, cmd, data);
+       unlock_kernel();
+
+       return ret;
+}
+
 #ifdef CONFIG_COMPAT
 
 /*
@@ -773,7 +818,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
                if (copy_to_user(precv64, &recv64, sizeof(recv64)))
                        return -EFAULT;
 
-               rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
+               rc = ipmi_ioctl(filep,
                                ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
                                 ? IPMICTL_RECEIVE_MSG
                                 : IPMICTL_RECEIVE_MSG_TRUNC),
@@ -790,14 +835,14 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
                return rc;
        }
        default:
-               return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
+               return ipmi_ioctl(filep, cmd, arg);
        }
 }
 #endif
 
 static const struct file_operations ipmi_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = ipmi_ioctl,
+       .unlocked_ioctl = ipmi_unlocked_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_ipmi_ioctl,
 #endif
@@ -809,7 +854,7 @@ static const struct file_operations ipmi_fops = {
 
 #define DEVICE_NAME     "ipmidev"
 
-static int ipmi_major = 0;
+static int ipmi_major;
 module_param(ipmi_major, int, 0);
 MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device.  By"
                 " default, or if you set it to zero, it will choose the next"
@@ -841,7 +886,7 @@ static void ipmi_new_smi(int if_num, struct device *device)
        entry->dev = dev;
 
        mutex_lock(&reg_list_mutex);
-       class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num);
+       device_create(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
        list_add(&entry->link, &reg_list);
        mutex_unlock(&reg_list_mutex);
 }
@@ -859,7 +904,7 @@ static void ipmi_smi_gone(int if_num)
                        break;
                }
        }
-       class_device_destroy(ipmi_class, dev);
+       device_destroy(ipmi_class, dev);
        mutex_unlock(&reg_list_mutex);
 }
 
@@ -914,7 +959,7 @@ static __exit void cleanup_ipmi(void)
        mutex_lock(&reg_list_mutex);
        list_for_each_entry_safe(entry, entry2, &reg_list, link) {
                list_del(&entry->link);
-               class_device_destroy(ipmi_class, entry->dev);
+               device_destroy(ipmi_class, entry->dev);
                kfree(entry);
        }
        mutex_unlock(&reg_list_mutex);
@@ -927,3 +972,4 @@ module_exit(cleanup_ipmi);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
 MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");
+MODULE_ALIAS("platform:ipmi_si");