Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * ipmi_devintf.c
0004  *
0005  * Linux device interface for the IPMI message handler.
0006  *
0007  * Author: MontaVista Software, Inc.
0008  *         Corey Minyard <minyard@mvista.com>
0009  *         source@mvista.com
0010  *
0011  * Copyright 2002 MontaVista Software Inc.
0012  */
0013 
0014 #include <linux/module.h>
0015 #include <linux/moduleparam.h>
0016 #include <linux/errno.h>
0017 #include <linux/poll.h>
0018 #include <linux/sched.h>
0019 #include <linux/spinlock.h>
0020 #include <linux/slab.h>
0021 #include <linux/ipmi.h>
0022 #include <linux/mutex.h>
0023 #include <linux/init.h>
0024 #include <linux/device.h>
0025 #include <linux/compat.h>
0026 
0027 struct ipmi_file_private
0028 {
0029     struct ipmi_user     *user;
0030     spinlock_t           recv_msg_lock;
0031     struct list_head     recv_msgs;
0032     struct fasync_struct *fasync_queue;
0033     wait_queue_head_t    wait;
0034     struct mutex         recv_mutex;
0035     int                  default_retries;
0036     unsigned int         default_retry_time_ms;
0037 };
0038 
0039 static void file_receive_handler(struct ipmi_recv_msg *msg,
0040                  void                 *handler_data)
0041 {
0042     struct ipmi_file_private *priv = handler_data;
0043     int                      was_empty;
0044     unsigned long            flags;
0045 
0046     spin_lock_irqsave(&priv->recv_msg_lock, flags);
0047     was_empty = list_empty(&priv->recv_msgs);
0048     list_add_tail(&msg->link, &priv->recv_msgs);
0049     spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0050 
0051     if (was_empty) {
0052         wake_up_interruptible(&priv->wait);
0053         kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
0054     }
0055 }
0056 
0057 static __poll_t ipmi_poll(struct file *file, poll_table *wait)
0058 {
0059     struct ipmi_file_private *priv = file->private_data;
0060     __poll_t             mask = 0;
0061     unsigned long            flags;
0062 
0063     poll_wait(file, &priv->wait, wait);
0064 
0065     spin_lock_irqsave(&priv->recv_msg_lock, flags);
0066 
0067     if (!list_empty(&priv->recv_msgs))
0068         mask |= (EPOLLIN | EPOLLRDNORM);
0069 
0070     spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0071 
0072     return mask;
0073 }
0074 
0075 static int ipmi_fasync(int fd, struct file *file, int on)
0076 {
0077     struct ipmi_file_private *priv = file->private_data;
0078 
0079     return fasync_helper(fd, file, on, &priv->fasync_queue);
0080 }
0081 
0082 static const struct ipmi_user_hndl ipmi_hndlrs =
0083 {
0084     .ipmi_recv_hndl = file_receive_handler,
0085 };
0086 
0087 static int ipmi_open(struct inode *inode, struct file *file)
0088 {
0089     int                      if_num = iminor(inode);
0090     int                      rv;
0091     struct ipmi_file_private *priv;
0092 
0093     priv = kmalloc(sizeof(*priv), GFP_KERNEL);
0094     if (!priv)
0095         return -ENOMEM;
0096 
0097     rv = ipmi_create_user(if_num,
0098                   &ipmi_hndlrs,
0099                   priv,
0100                   &priv->user);
0101     if (rv) {
0102         kfree(priv);
0103         goto out;
0104     }
0105 
0106     file->private_data = priv;
0107 
0108     spin_lock_init(&priv->recv_msg_lock);
0109     INIT_LIST_HEAD(&priv->recv_msgs);
0110     init_waitqueue_head(&priv->wait);
0111     priv->fasync_queue = NULL;
0112     mutex_init(&priv->recv_mutex);
0113 
0114     /* Use the low-level defaults. */
0115     priv->default_retries = -1;
0116     priv->default_retry_time_ms = 0;
0117 
0118 out:
0119     return rv;
0120 }
0121 
0122 static int ipmi_release(struct inode *inode, struct file *file)
0123 {
0124     struct ipmi_file_private *priv = file->private_data;
0125     int                      rv;
0126     struct ipmi_recv_msg *msg, *next;
0127 
0128     rv = ipmi_destroy_user(priv->user);
0129     if (rv)
0130         return rv;
0131 
0132     list_for_each_entry_safe(msg, next, &priv->recv_msgs, link)
0133         ipmi_free_recv_msg(msg);
0134 
0135     kfree(priv);
0136 
0137     return 0;
0138 }
0139 
0140 static int handle_send_req(struct ipmi_user *user,
0141                struct ipmi_req *req,
0142                int             retries,
0143                unsigned int    retry_time_ms)
0144 {
0145     int              rv;
0146     struct ipmi_addr addr;
0147     struct kernel_ipmi_msg msg;
0148 
0149     if (req->addr_len > sizeof(struct ipmi_addr))
0150         return -EINVAL;
0151 
0152     if (copy_from_user(&addr, req->addr, req->addr_len))
0153         return -EFAULT;
0154 
0155     msg.netfn = req->msg.netfn;
0156     msg.cmd = req->msg.cmd;
0157     msg.data_len = req->msg.data_len;
0158     msg.data = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
0159     if (!msg.data)
0160         return -ENOMEM;
0161 
0162     /* From here out we cannot return, we must jump to "out" for
0163        error exits to free msgdata. */
0164 
0165     rv = ipmi_validate_addr(&addr, req->addr_len);
0166     if (rv)
0167         goto out;
0168 
0169     if (req->msg.data != NULL) {
0170         if (req->msg.data_len > IPMI_MAX_MSG_LENGTH) {
0171             rv = -EMSGSIZE;
0172             goto out;
0173         }
0174 
0175         if (copy_from_user(msg.data,
0176                    req->msg.data,
0177                    req->msg.data_len)) {
0178             rv = -EFAULT;
0179             goto out;
0180         }
0181     } else {
0182         msg.data_len = 0;
0183     }
0184 
0185     rv = ipmi_request_settime(user,
0186                   &addr,
0187                   req->msgid,
0188                   &msg,
0189                   NULL,
0190                   0,
0191                   retries,
0192                   retry_time_ms);
0193  out:
0194     kfree(msg.data);
0195     return rv;
0196 }
0197 
0198 static int handle_recv(struct ipmi_file_private *priv,
0199             bool trunc, struct ipmi_recv *rsp,
0200             int (*copyout)(struct ipmi_recv *, void __user *),
0201             void __user *to)
0202 {
0203     int              addr_len;
0204     struct list_head *entry;
0205     struct ipmi_recv_msg  *msg;
0206     unsigned long    flags;
0207     int rv = 0, rv2 = 0;
0208 
0209     /* We claim a mutex because we don't want two
0210        users getting something from the queue at a time.
0211        Since we have to release the spinlock before we can
0212        copy the data to the user, it's possible another
0213        user will grab something from the queue, too.  Then
0214        the messages might get out of order if something
0215        fails and the message gets put back onto the
0216        queue.  This mutex prevents that problem. */
0217     mutex_lock(&priv->recv_mutex);
0218 
0219     /* Grab the message off the list. */
0220     spin_lock_irqsave(&priv->recv_msg_lock, flags);
0221     if (list_empty(&(priv->recv_msgs))) {
0222         spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0223         rv = -EAGAIN;
0224         goto recv_err;
0225     }
0226     entry = priv->recv_msgs.next;
0227     msg = list_entry(entry, struct ipmi_recv_msg, link);
0228     list_del(entry);
0229     spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0230 
0231     addr_len = ipmi_addr_length(msg->addr.addr_type);
0232     if (rsp->addr_len < addr_len) {
0233         rv = -EINVAL;
0234         goto recv_putback_on_err;
0235     }
0236 
0237     if (copy_to_user(rsp->addr, &msg->addr, addr_len)) {
0238         rv = -EFAULT;
0239         goto recv_putback_on_err;
0240     }
0241     rsp->addr_len = addr_len;
0242 
0243     rsp->recv_type = msg->recv_type;
0244     rsp->msgid = msg->msgid;
0245     rsp->msg.netfn = msg->msg.netfn;
0246     rsp->msg.cmd = msg->msg.cmd;
0247 
0248     if (msg->msg.data_len > 0) {
0249         if (rsp->msg.data_len < msg->msg.data_len) {
0250             if (trunc) {
0251                 rv2 = -EMSGSIZE;
0252                 msg->msg.data_len = rsp->msg.data_len;
0253             } else {
0254                 rv = -EMSGSIZE;
0255                 goto recv_putback_on_err;
0256             }
0257         }
0258 
0259         if (copy_to_user(rsp->msg.data,
0260                  msg->msg.data,
0261                  msg->msg.data_len)) {
0262             rv = -EFAULT;
0263             goto recv_putback_on_err;
0264         }
0265         rsp->msg.data_len = msg->msg.data_len;
0266     } else {
0267         rsp->msg.data_len = 0;
0268     }
0269 
0270     rv = copyout(rsp, to);
0271     if (rv)
0272         goto recv_putback_on_err;
0273 
0274     mutex_unlock(&priv->recv_mutex);
0275     ipmi_free_recv_msg(msg);
0276     return rv2;
0277 
0278 recv_putback_on_err:
0279     /* If we got an error, put the message back onto
0280        the head of the queue. */
0281     spin_lock_irqsave(&priv->recv_msg_lock, flags);
0282     list_add(entry, &priv->recv_msgs);
0283     spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0284 recv_err:
0285     mutex_unlock(&priv->recv_mutex);
0286     return rv;
0287 }
0288 
0289 static int copyout_recv(struct ipmi_recv *rsp, void __user *to)
0290 {
0291     return copy_to_user(to, rsp, sizeof(struct ipmi_recv)) ? -EFAULT : 0;
0292 }
0293 
0294 static long ipmi_ioctl(struct file   *file,
0295                unsigned int  cmd,
0296                unsigned long data)
0297 {
0298     int                      rv = -EINVAL;
0299     struct ipmi_file_private *priv = file->private_data;
0300     void __user *arg = (void __user *)data;
0301 
0302     switch (cmd) 
0303     {
0304     case IPMICTL_SEND_COMMAND:
0305     {
0306         struct ipmi_req req;
0307         int retries;
0308         unsigned int retry_time_ms;
0309 
0310         if (copy_from_user(&req, arg, sizeof(req))) {
0311             rv = -EFAULT;
0312             break;
0313         }
0314 
0315         mutex_lock(&priv->recv_mutex);
0316         retries = priv->default_retries;
0317         retry_time_ms = priv->default_retry_time_ms;
0318         mutex_unlock(&priv->recv_mutex);
0319 
0320         rv = handle_send_req(priv->user, &req, retries, retry_time_ms);
0321         break;
0322     }
0323 
0324     case IPMICTL_SEND_COMMAND_SETTIME:
0325     {
0326         struct ipmi_req_settime req;
0327 
0328         if (copy_from_user(&req, arg, sizeof(req))) {
0329             rv = -EFAULT;
0330             break;
0331         }
0332 
0333         rv = handle_send_req(priv->user,
0334                      &req.req,
0335                      req.retries,
0336                      req.retry_time_ms);
0337         break;
0338     }
0339 
0340     case IPMICTL_RECEIVE_MSG:
0341     case IPMICTL_RECEIVE_MSG_TRUNC:
0342     {
0343         struct ipmi_recv      rsp;
0344 
0345         if (copy_from_user(&rsp, arg, sizeof(rsp)))
0346             rv = -EFAULT;
0347         else
0348             rv = handle_recv(priv, cmd == IPMICTL_RECEIVE_MSG_TRUNC,
0349                      &rsp, copyout_recv, arg);
0350         break;
0351     }
0352 
0353     case IPMICTL_REGISTER_FOR_CMD:
0354     {
0355         struct ipmi_cmdspec val;
0356 
0357         if (copy_from_user(&val, arg, sizeof(val))) {
0358             rv = -EFAULT;
0359             break;
0360         }
0361 
0362         rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
0363                        IPMI_CHAN_ALL);
0364         break;
0365     }
0366 
0367     case IPMICTL_UNREGISTER_FOR_CMD:
0368     {
0369         struct ipmi_cmdspec   val;
0370 
0371         if (copy_from_user(&val, arg, sizeof(val))) {
0372             rv = -EFAULT;
0373             break;
0374         }
0375 
0376         rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
0377                          IPMI_CHAN_ALL);
0378         break;
0379     }
0380 
0381     case IPMICTL_REGISTER_FOR_CMD_CHANS:
0382     {
0383         struct ipmi_cmdspec_chans val;
0384 
0385         if (copy_from_user(&val, arg, sizeof(val))) {
0386             rv = -EFAULT;
0387             break;
0388         }
0389 
0390         rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
0391                        val.chans);
0392         break;
0393     }
0394 
0395     case IPMICTL_UNREGISTER_FOR_CMD_CHANS:
0396     {
0397         struct ipmi_cmdspec_chans val;
0398 
0399         if (copy_from_user(&val, arg, sizeof(val))) {
0400             rv = -EFAULT;
0401             break;
0402         }
0403 
0404         rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
0405                          val.chans);
0406         break;
0407     }
0408 
0409     case IPMICTL_SET_GETS_EVENTS_CMD:
0410     {
0411         int val;
0412 
0413         if (copy_from_user(&val, arg, sizeof(val))) {
0414             rv = -EFAULT;
0415             break;
0416         }
0417 
0418         rv = ipmi_set_gets_events(priv->user, val);
0419         break;
0420     }
0421 
0422     /* The next four are legacy, not per-channel. */
0423     case IPMICTL_SET_MY_ADDRESS_CMD:
0424     {
0425         unsigned int val;
0426 
0427         if (copy_from_user(&val, arg, sizeof(val))) {
0428             rv = -EFAULT;
0429             break;
0430         }
0431 
0432         rv = ipmi_set_my_address(priv->user, 0, val);
0433         break;
0434     }
0435 
0436     case IPMICTL_GET_MY_ADDRESS_CMD:
0437     {
0438         unsigned int  val;
0439         unsigned char rval;
0440 
0441         rv = ipmi_get_my_address(priv->user, 0, &rval);
0442         if (rv)
0443             break;
0444 
0445         val = rval;
0446 
0447         if (copy_to_user(arg, &val, sizeof(val))) {
0448             rv = -EFAULT;
0449             break;
0450         }
0451         break;
0452     }
0453 
0454     case IPMICTL_SET_MY_LUN_CMD:
0455     {
0456         unsigned int val;
0457 
0458         if (copy_from_user(&val, arg, sizeof(val))) {
0459             rv = -EFAULT;
0460             break;
0461         }
0462 
0463         rv = ipmi_set_my_LUN(priv->user, 0, val);
0464         break;
0465     }
0466 
0467     case IPMICTL_GET_MY_LUN_CMD:
0468     {
0469         unsigned int  val;
0470         unsigned char rval;
0471 
0472         rv = ipmi_get_my_LUN(priv->user, 0, &rval);
0473         if (rv)
0474             break;
0475 
0476         val = rval;
0477 
0478         if (copy_to_user(arg, &val, sizeof(val))) {
0479             rv = -EFAULT;
0480             break;
0481         }
0482         break;
0483     }
0484 
0485     case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
0486     {
0487         struct ipmi_channel_lun_address_set val;
0488 
0489         if (copy_from_user(&val, arg, sizeof(val))) {
0490             rv = -EFAULT;
0491             break;
0492         }
0493 
0494         return ipmi_set_my_address(priv->user, val.channel, val.value);
0495     }
0496 
0497     case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
0498     {
0499         struct ipmi_channel_lun_address_set val;
0500 
0501         if (copy_from_user(&val, arg, sizeof(val))) {
0502             rv = -EFAULT;
0503             break;
0504         }
0505 
0506         rv = ipmi_get_my_address(priv->user, val.channel, &val.value);
0507         if (rv)
0508             break;
0509 
0510         if (copy_to_user(arg, &val, sizeof(val))) {
0511             rv = -EFAULT;
0512             break;
0513         }
0514         break;
0515     }
0516 
0517     case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
0518     {
0519         struct ipmi_channel_lun_address_set val;
0520 
0521         if (copy_from_user(&val, arg, sizeof(val))) {
0522             rv = -EFAULT;
0523             break;
0524         }
0525 
0526         rv = ipmi_set_my_LUN(priv->user, val.channel, val.value);
0527         break;
0528     }
0529 
0530     case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
0531     {
0532         struct ipmi_channel_lun_address_set val;
0533 
0534         if (copy_from_user(&val, arg, sizeof(val))) {
0535             rv = -EFAULT;
0536             break;
0537         }
0538 
0539         rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value);
0540         if (rv)
0541             break;
0542 
0543         if (copy_to_user(arg, &val, sizeof(val))) {
0544             rv = -EFAULT;
0545             break;
0546         }
0547         break;
0548     }
0549 
0550     case IPMICTL_SET_TIMING_PARMS_CMD:
0551     {
0552         struct ipmi_timing_parms parms;
0553 
0554         if (copy_from_user(&parms, arg, sizeof(parms))) {
0555             rv = -EFAULT;
0556             break;
0557         }
0558 
0559         mutex_lock(&priv->recv_mutex);
0560         priv->default_retries = parms.retries;
0561         priv->default_retry_time_ms = parms.retry_time_ms;
0562         mutex_unlock(&priv->recv_mutex);
0563         rv = 0;
0564         break;
0565     }
0566 
0567     case IPMICTL_GET_TIMING_PARMS_CMD:
0568     {
0569         struct ipmi_timing_parms parms;
0570 
0571         mutex_lock(&priv->recv_mutex);
0572         parms.retries = priv->default_retries;
0573         parms.retry_time_ms = priv->default_retry_time_ms;
0574         mutex_unlock(&priv->recv_mutex);
0575 
0576         if (copy_to_user(arg, &parms, sizeof(parms))) {
0577             rv = -EFAULT;
0578             break;
0579         }
0580 
0581         rv = 0;
0582         break;
0583     }
0584 
0585     case IPMICTL_GET_MAINTENANCE_MODE_CMD:
0586     {
0587         int mode;
0588 
0589         mode = ipmi_get_maintenance_mode(priv->user);
0590         if (copy_to_user(arg, &mode, sizeof(mode))) {
0591             rv = -EFAULT;
0592             break;
0593         }
0594         rv = 0;
0595         break;
0596     }
0597 
0598     case IPMICTL_SET_MAINTENANCE_MODE_CMD:
0599     {
0600         int mode;
0601 
0602         if (copy_from_user(&mode, arg, sizeof(mode))) {
0603             rv = -EFAULT;
0604             break;
0605         }
0606         rv = ipmi_set_maintenance_mode(priv->user, mode);
0607         break;
0608     }
0609 
0610     default:
0611         rv = -ENOTTY;
0612         break;
0613     }
0614   
0615     return rv;
0616 }
0617 
0618 #ifdef CONFIG_COMPAT
0619 /*
0620  * The following code contains code for supporting 32-bit compatible
0621  * ioctls on 64-bit kernels.  This allows running 32-bit apps on the
0622  * 64-bit kernel
0623  */
0624 #define COMPAT_IPMICTL_SEND_COMMAND \
0625     _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
0626 #define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \
0627     _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
0628 #define COMPAT_IPMICTL_RECEIVE_MSG  \
0629     _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
0630 #define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC    \
0631     _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
0632 
0633 struct compat_ipmi_msg {
0634     u8      netfn;
0635     u8      cmd;
0636     u16     data_len;
0637     compat_uptr_t   data;
0638 };
0639 
0640 struct compat_ipmi_req {
0641     compat_uptr_t       addr;
0642     compat_uint_t       addr_len;
0643     compat_long_t       msgid;
0644     struct compat_ipmi_msg  msg;
0645 };
0646 
0647 struct compat_ipmi_recv {
0648     compat_int_t        recv_type;
0649     compat_uptr_t       addr;
0650     compat_uint_t       addr_len;
0651     compat_long_t       msgid;
0652     struct compat_ipmi_msg  msg;
0653 };
0654 
0655 struct compat_ipmi_req_settime {
0656     struct compat_ipmi_req  req;
0657     compat_int_t        retries;
0658     compat_uint_t       retry_time_ms;
0659 };
0660 
0661 /*
0662  * Define some helper functions for copying IPMI data
0663  */
0664 static void get_compat_ipmi_msg(struct ipmi_msg *p64,
0665                 struct compat_ipmi_msg *p32)
0666 {
0667     p64->netfn = p32->netfn;
0668     p64->cmd = p32->cmd;
0669     p64->data_len = p32->data_len;
0670     p64->data = compat_ptr(p32->data);
0671 }
0672 
0673 static void get_compat_ipmi_req(struct ipmi_req *p64,
0674                 struct compat_ipmi_req *p32)
0675 {
0676     p64->addr = compat_ptr(p32->addr);
0677     p64->addr_len = p32->addr_len;
0678     p64->msgid = p32->msgid;
0679     get_compat_ipmi_msg(&p64->msg, &p32->msg);
0680 }
0681 
0682 static void get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
0683         struct compat_ipmi_req_settime *p32)
0684 {
0685     get_compat_ipmi_req(&p64->req, &p32->req);
0686     p64->retries = p32->retries;
0687     p64->retry_time_ms = p32->retry_time_ms;
0688 }
0689 
0690 static void get_compat_ipmi_recv(struct ipmi_recv *p64,
0691                  struct compat_ipmi_recv *p32)
0692 {
0693     memset(p64, 0, sizeof(struct ipmi_recv));
0694     p64->recv_type = p32->recv_type;
0695     p64->addr = compat_ptr(p32->addr);
0696     p64->addr_len = p32->addr_len;
0697     p64->msgid = p32->msgid;
0698     get_compat_ipmi_msg(&p64->msg, &p32->msg);
0699 }
0700 
0701 static int copyout_recv32(struct ipmi_recv *p64, void __user *to)
0702 {
0703     struct compat_ipmi_recv v32;
0704     memset(&v32, 0, sizeof(struct compat_ipmi_recv));
0705     v32.recv_type = p64->recv_type;
0706     v32.addr = ptr_to_compat(p64->addr);
0707     v32.addr_len = p64->addr_len;
0708     v32.msgid = p64->msgid;
0709     v32.msg.netfn = p64->msg.netfn;
0710     v32.msg.cmd = p64->msg.cmd;
0711     v32.msg.data_len = p64->msg.data_len;
0712     v32.msg.data = ptr_to_compat(p64->msg.data);
0713     return copy_to_user(to, &v32, sizeof(v32)) ? -EFAULT : 0;
0714 }
0715 
0716 /*
0717  * Handle compatibility ioctls
0718  */
0719 static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
0720                   unsigned long arg)
0721 {
0722     struct ipmi_file_private *priv = filep->private_data;
0723 
0724     switch(cmd) {
0725     case COMPAT_IPMICTL_SEND_COMMAND:
0726     {
0727         struct ipmi_req rp;
0728         struct compat_ipmi_req r32;
0729         int retries;
0730         unsigned int retry_time_ms;
0731 
0732         if (copy_from_user(&r32, compat_ptr(arg), sizeof(r32)))
0733             return -EFAULT;
0734 
0735         get_compat_ipmi_req(&rp, &r32);
0736 
0737         mutex_lock(&priv->recv_mutex);
0738         retries = priv->default_retries;
0739         retry_time_ms = priv->default_retry_time_ms;
0740         mutex_unlock(&priv->recv_mutex);
0741 
0742         return handle_send_req(priv->user, &rp,
0743                        retries, retry_time_ms);
0744     }
0745     case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
0746     {
0747         struct ipmi_req_settime sp;
0748         struct compat_ipmi_req_settime sp32;
0749 
0750         if (copy_from_user(&sp32, compat_ptr(arg), sizeof(sp32)))
0751             return -EFAULT;
0752 
0753         get_compat_ipmi_req_settime(&sp, &sp32);
0754 
0755         return handle_send_req(priv->user, &sp.req,
0756                 sp.retries, sp.retry_time_ms);
0757     }
0758     case COMPAT_IPMICTL_RECEIVE_MSG:
0759     case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
0760     {
0761         struct ipmi_recv   recv64;
0762         struct compat_ipmi_recv recv32;
0763 
0764         if (copy_from_user(&recv32, compat_ptr(arg), sizeof(recv32)))
0765             return -EFAULT;
0766 
0767         get_compat_ipmi_recv(&recv64, &recv32);
0768 
0769         return handle_recv(priv,
0770                  cmd == COMPAT_IPMICTL_RECEIVE_MSG_TRUNC,
0771                  &recv64, copyout_recv32, compat_ptr(arg));
0772     }
0773     default:
0774         return ipmi_ioctl(filep, cmd, arg);
0775     }
0776 }
0777 #endif
0778 
0779 static const struct file_operations ipmi_fops = {
0780     .owner      = THIS_MODULE,
0781     .unlocked_ioctl = ipmi_ioctl,
0782 #ifdef CONFIG_COMPAT
0783     .compat_ioctl   = compat_ipmi_ioctl,
0784 #endif
0785     .open       = ipmi_open,
0786     .release    = ipmi_release,
0787     .fasync     = ipmi_fasync,
0788     .poll       = ipmi_poll,
0789     .llseek     = noop_llseek,
0790 };
0791 
0792 #define DEVICE_NAME     "ipmidev"
0793 
0794 static int ipmi_major;
0795 module_param(ipmi_major, int, 0);
0796 MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device.  By"
0797          " default, or if you set it to zero, it will choose the next"
0798          " available device.  Setting it to -1 will disable the"
0799          " interface.  Other values will set the major device number"
0800          " to that value.");
0801 
0802 /* Keep track of the devices that are registered. */
0803 struct ipmi_reg_list {
0804     dev_t            dev;
0805     struct list_head link;
0806 };
0807 static LIST_HEAD(reg_list);
0808 static DEFINE_MUTEX(reg_list_mutex);
0809 
0810 static struct class *ipmi_class;
0811 
0812 static void ipmi_new_smi(int if_num, struct device *device)
0813 {
0814     dev_t dev = MKDEV(ipmi_major, if_num);
0815     struct ipmi_reg_list *entry;
0816 
0817     entry = kmalloc(sizeof(*entry), GFP_KERNEL);
0818     if (!entry) {
0819         pr_err("ipmi_devintf: Unable to create the ipmi class device link\n");
0820         return;
0821     }
0822     entry->dev = dev;
0823 
0824     mutex_lock(&reg_list_mutex);
0825     device_create(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
0826     list_add(&entry->link, &reg_list);
0827     mutex_unlock(&reg_list_mutex);
0828 }
0829 
0830 static void ipmi_smi_gone(int if_num)
0831 {
0832     dev_t dev = MKDEV(ipmi_major, if_num);
0833     struct ipmi_reg_list *entry;
0834 
0835     mutex_lock(&reg_list_mutex);
0836     list_for_each_entry(entry, &reg_list, link) {
0837         if (entry->dev == dev) {
0838             list_del(&entry->link);
0839             kfree(entry);
0840             break;
0841         }
0842     }
0843     device_destroy(ipmi_class, dev);
0844     mutex_unlock(&reg_list_mutex);
0845 }
0846 
0847 static struct ipmi_smi_watcher smi_watcher =
0848 {
0849     .owner    = THIS_MODULE,
0850     .new_smi  = ipmi_new_smi,
0851     .smi_gone = ipmi_smi_gone,
0852 };
0853 
0854 static int __init init_ipmi_devintf(void)
0855 {
0856     int rv;
0857 
0858     if (ipmi_major < 0)
0859         return -EINVAL;
0860 
0861     pr_info("ipmi device interface\n");
0862 
0863     ipmi_class = class_create(THIS_MODULE, "ipmi");
0864     if (IS_ERR(ipmi_class)) {
0865         pr_err("ipmi: can't register device class\n");
0866         return PTR_ERR(ipmi_class);
0867     }
0868 
0869     rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
0870     if (rv < 0) {
0871         class_destroy(ipmi_class);
0872         pr_err("ipmi: can't get major %d\n", ipmi_major);
0873         return rv;
0874     }
0875 
0876     if (ipmi_major == 0) {
0877         ipmi_major = rv;
0878     }
0879 
0880     rv = ipmi_smi_watcher_register(&smi_watcher);
0881     if (rv) {
0882         unregister_chrdev(ipmi_major, DEVICE_NAME);
0883         class_destroy(ipmi_class);
0884         pr_warn("ipmi: can't register smi watcher\n");
0885         return rv;
0886     }
0887 
0888     return 0;
0889 }
0890 module_init(init_ipmi_devintf);
0891 
0892 static void __exit cleanup_ipmi(void)
0893 {
0894     struct ipmi_reg_list *entry, *entry2;
0895     mutex_lock(&reg_list_mutex);
0896     list_for_each_entry_safe(entry, entry2, &reg_list, link) {
0897         list_del(&entry->link);
0898         device_destroy(ipmi_class, entry->dev);
0899         kfree(entry);
0900     }
0901     mutex_unlock(&reg_list_mutex);
0902     class_destroy(ipmi_class);
0903     ipmi_smi_watcher_unregister(&smi_watcher);
0904     unregister_chrdev(ipmi_major, DEVICE_NAME);
0905 }
0906 module_exit(cleanup_ipmi);
0907 
0908 MODULE_LICENSE("GPL");
0909 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
0910 MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");