Pull trivial into test branch
[linux-2.6] / drivers / char / ipmi / ipmi_devintf.c
1 /*
2  * ipmi_devintf.c
3  *
4  * Linux device interface for the IPMI message handler.
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2002 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or modify it
13  *  under the terms of the GNU General Public License as published by the
14  *  Free Software Foundation; either version 2 of the License, or (at your
15  *  option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU General Public License along
30  *  with this program; if not, write to the Free Software Foundation, Inc.,
31  *  675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33
34 #include <linux/module.h>
35 #include <linux/moduleparam.h>
36 #include <linux/errno.h>
37 #include <asm/system.h>
38 #include <linux/sched.h>
39 #include <linux/poll.h>
40 #include <linux/spinlock.h>
41 #include <linux/slab.h>
42 #include <linux/ipmi.h>
43 #include <linux/mutex.h>
44 #include <linux/init.h>
45 #include <linux/device.h>
46 #include <linux/compat.h>
47
48 struct ipmi_file_private
49 {
50         ipmi_user_t          user;
51         spinlock_t           recv_msg_lock;
52         struct list_head     recv_msgs;
53         struct file          *file;
54         struct fasync_struct *fasync_queue;
55         wait_queue_head_t    wait;
56         struct mutex         recv_mutex;
57         int                  default_retries;
58         unsigned int         default_retry_time_ms;
59 };
60
61 static void file_receive_handler(struct ipmi_recv_msg *msg,
62                                  void                 *handler_data)
63 {
64         struct ipmi_file_private *priv = handler_data;
65         int                      was_empty;
66         unsigned long            flags;
67
68         spin_lock_irqsave(&(priv->recv_msg_lock), flags);
69
70         was_empty = list_empty(&(priv->recv_msgs));
71         list_add_tail(&(msg->link), &(priv->recv_msgs));
72
73         if (was_empty) {
74                 wake_up_interruptible(&priv->wait);
75                 kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
76         }
77
78         spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
79 }
80
81 static unsigned int ipmi_poll(struct file *file, poll_table *wait)
82 {
83         struct ipmi_file_private *priv = file->private_data;
84         unsigned int             mask = 0;
85         unsigned long            flags;
86
87         poll_wait(file, &priv->wait, wait);
88
89         spin_lock_irqsave(&priv->recv_msg_lock, flags);
90
91         if (!list_empty(&(priv->recv_msgs)))
92                 mask |= (POLLIN | POLLRDNORM);
93
94         spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
95
96         return mask;
97 }
98
99 static int ipmi_fasync(int fd, struct file *file, int on)
100 {
101         struct ipmi_file_private *priv = file->private_data;
102         int                      result;
103
104         result = fasync_helper(fd, file, on, &priv->fasync_queue);
105
106         return (result);
107 }
108
109 static struct ipmi_user_hndl ipmi_hndlrs =
110 {
111         .ipmi_recv_hndl = file_receive_handler,
112 };
113
114 static int ipmi_open(struct inode *inode, struct file *file)
115 {
116         int                      if_num = iminor(inode);
117         int                      rv;
118         struct ipmi_file_private *priv;
119
120
121         priv = kmalloc(sizeof(*priv), GFP_KERNEL);
122         if (!priv)
123                 return -ENOMEM;
124
125         priv->file = file;
126
127         rv = ipmi_create_user(if_num,
128                               &ipmi_hndlrs,
129                               priv,
130                               &(priv->user));
131         if (rv) {
132                 kfree(priv);
133                 return rv;
134         }
135
136         file->private_data = priv;
137
138         spin_lock_init(&(priv->recv_msg_lock));
139         INIT_LIST_HEAD(&(priv->recv_msgs));
140         init_waitqueue_head(&priv->wait);
141         priv->fasync_queue = NULL;
142         mutex_init(&priv->recv_mutex);
143
144         /* Use the low-level defaults. */
145         priv->default_retries = -1;
146         priv->default_retry_time_ms = 0;
147
148         return 0;
149 }
150
151 static int ipmi_release(struct inode *inode, struct file *file)
152 {
153         struct ipmi_file_private *priv = file->private_data;
154         int                      rv;
155
156         rv = ipmi_destroy_user(priv->user);
157         if (rv)
158                 return rv;
159
160         ipmi_fasync (-1, file, 0);
161
162         /* FIXME - free the messages in the list. */
163         kfree(priv);
164
165         return 0;
166 }
167
168 static int handle_send_req(ipmi_user_t     user,
169                            struct ipmi_req *req,
170                            int             retries,
171                            unsigned int    retry_time_ms)
172 {
173         int              rv;
174         struct ipmi_addr addr;
175         struct kernel_ipmi_msg msg;
176
177         if (req->addr_len > sizeof(struct ipmi_addr))
178                 return -EINVAL;
179
180         if (copy_from_user(&addr, req->addr, req->addr_len))
181                 return -EFAULT;
182
183         msg.netfn = req->msg.netfn;
184         msg.cmd = req->msg.cmd;
185         msg.data_len = req->msg.data_len;
186         msg.data = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
187         if (!msg.data)
188                 return -ENOMEM;
189
190         /* From here out we cannot return, we must jump to "out" for
191            error exits to free msgdata. */
192
193         rv = ipmi_validate_addr(&addr, req->addr_len);
194         if (rv)
195                 goto out;
196
197         if (req->msg.data != NULL) {
198                 if (req->msg.data_len > IPMI_MAX_MSG_LENGTH) {
199                         rv = -EMSGSIZE;
200                         goto out;
201                 }
202
203                 if (copy_from_user(msg.data,
204                                    req->msg.data,
205                                    req->msg.data_len))
206                 {
207                         rv = -EFAULT;
208                         goto out;
209                 }
210         } else {
211                 msg.data_len = 0;
212         }
213
214         rv = ipmi_request_settime(user,
215                                   &addr,
216                                   req->msgid,
217                                   &msg,
218                                   NULL,
219                                   0,
220                                   retries,
221                                   retry_time_ms);
222  out:
223         kfree(msg.data);
224         return rv;
225 }
226
227 static int ipmi_ioctl(struct inode  *inode,
228                       struct file   *file,
229                       unsigned int  cmd,
230                       unsigned long data)
231 {
232         int                      rv = -EINVAL;
233         struct ipmi_file_private *priv = file->private_data;
234         void __user *arg = (void __user *)data;
235
236         switch (cmd) 
237         {
238         case IPMICTL_SEND_COMMAND:
239         {
240                 struct ipmi_req req;
241
242                 if (copy_from_user(&req, arg, sizeof(req))) {
243                         rv = -EFAULT;
244                         break;
245                 }
246
247                 rv = handle_send_req(priv->user,
248                                      &req,
249                                      priv->default_retries,
250                                      priv->default_retry_time_ms);
251                 break;
252         }
253
254         case IPMICTL_SEND_COMMAND_SETTIME:
255         {
256                 struct ipmi_req_settime req;
257
258                 if (copy_from_user(&req, arg, sizeof(req))) {
259                         rv = -EFAULT;
260                         break;
261                 }
262
263                 rv = handle_send_req(priv->user,
264                                      &req.req,
265                                      req.retries,
266                                      req.retry_time_ms);
267                 break;
268         }
269
270         case IPMICTL_RECEIVE_MSG:
271         case IPMICTL_RECEIVE_MSG_TRUNC:
272         {
273                 struct ipmi_recv      rsp;
274                 int              addr_len;
275                 struct list_head *entry;
276                 struct ipmi_recv_msg  *msg;
277                 unsigned long    flags;
278                 
279
280                 rv = 0;
281                 if (copy_from_user(&rsp, arg, sizeof(rsp))) {
282                         rv = -EFAULT;
283                         break;
284                 }
285
286                 /* We claim a mutex because we don't want two
287                    users getting something from the queue at a time.
288                    Since we have to release the spinlock before we can
289                    copy the data to the user, it's possible another
290                    user will grab something from the queue, too.  Then
291                    the messages might get out of order if something
292                    fails and the message gets put back onto the
293                    queue.  This mutex prevents that problem. */
294                 mutex_lock(&priv->recv_mutex);
295
296                 /* Grab the message off the list. */
297                 spin_lock_irqsave(&(priv->recv_msg_lock), flags);
298                 if (list_empty(&(priv->recv_msgs))) {
299                         spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
300                         rv = -EAGAIN;
301                         goto recv_err;
302                 }
303                 entry = priv->recv_msgs.next;
304                 msg = list_entry(entry, struct ipmi_recv_msg, link);
305                 list_del(entry);
306                 spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
307
308                 addr_len = ipmi_addr_length(msg->addr.addr_type);
309                 if (rsp.addr_len < addr_len)
310                 {
311                         rv = -EINVAL;
312                         goto recv_putback_on_err;
313                 }
314
315                 if (copy_to_user(rsp.addr, &(msg->addr), addr_len)) {
316                         rv = -EFAULT;
317                         goto recv_putback_on_err;
318                 }
319                 rsp.addr_len = addr_len;
320
321                 rsp.recv_type = msg->recv_type;
322                 rsp.msgid = msg->msgid;
323                 rsp.msg.netfn = msg->msg.netfn;
324                 rsp.msg.cmd = msg->msg.cmd;
325
326                 if (msg->msg.data_len > 0) {
327                         if (rsp.msg.data_len < msg->msg.data_len) {
328                                 rv = -EMSGSIZE;
329                                 if (cmd == IPMICTL_RECEIVE_MSG_TRUNC) {
330                                         msg->msg.data_len = rsp.msg.data_len;
331                                 } else {
332                                         goto recv_putback_on_err;
333                                 }
334                         }
335
336                         if (copy_to_user(rsp.msg.data,
337                                          msg->msg.data,
338                                          msg->msg.data_len))
339                         {
340                                 rv = -EFAULT;
341                                 goto recv_putback_on_err;
342                         }
343                         rsp.msg.data_len = msg->msg.data_len;
344                 } else {
345                         rsp.msg.data_len = 0;
346                 }
347
348                 if (copy_to_user(arg, &rsp, sizeof(rsp))) {
349                         rv = -EFAULT;
350                         goto recv_putback_on_err;
351                 }
352
353                 mutex_unlock(&priv->recv_mutex);
354                 ipmi_free_recv_msg(msg);
355                 break;
356
357         recv_putback_on_err:
358                 /* If we got an error, put the message back onto
359                    the head of the queue. */
360                 spin_lock_irqsave(&(priv->recv_msg_lock), flags);
361                 list_add(entry, &(priv->recv_msgs));
362                 spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
363                 mutex_unlock(&priv->recv_mutex);
364                 break;
365
366         recv_err:
367                 mutex_unlock(&priv->recv_mutex);
368                 break;
369         }
370
371         case IPMICTL_REGISTER_FOR_CMD:
372         {
373                 struct ipmi_cmdspec val;
374
375                 if (copy_from_user(&val, arg, sizeof(val))) {
376                         rv = -EFAULT;
377                         break;
378                 }
379
380                 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
381                                            IPMI_CHAN_ALL);
382                 break;
383         }
384
385         case IPMICTL_UNREGISTER_FOR_CMD:
386         {
387                 struct ipmi_cmdspec   val;
388
389                 if (copy_from_user(&val, arg, sizeof(val))) {
390                         rv = -EFAULT;
391                         break;
392                 }
393
394                 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
395                                              IPMI_CHAN_ALL);
396                 break;
397         }
398
399         case IPMICTL_REGISTER_FOR_CMD_CHANS:
400         {
401                 struct ipmi_cmdspec_chans val;
402
403                 if (copy_from_user(&val, arg, sizeof(val))) {
404                         rv = -EFAULT;
405                         break;
406                 }
407
408                 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
409                                            val.chans);
410                 break;
411         }
412
413         case IPMICTL_UNREGISTER_FOR_CMD_CHANS:
414         {
415                 struct ipmi_cmdspec_chans val;
416
417                 if (copy_from_user(&val, arg, sizeof(val))) {
418                         rv = -EFAULT;
419                         break;
420                 }
421
422                 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
423                                              val.chans);
424                 break;
425         }
426
427         case IPMICTL_SET_GETS_EVENTS_CMD:
428         {
429                 int val;
430
431                 if (copy_from_user(&val, arg, sizeof(val))) {
432                         rv = -EFAULT;
433                         break;
434                 }
435
436                 rv = ipmi_set_gets_events(priv->user, val);
437                 break;
438         }
439
440         /* The next four are legacy, not per-channel. */
441         case IPMICTL_SET_MY_ADDRESS_CMD:
442         {
443                 unsigned int val;
444
445                 if (copy_from_user(&val, arg, sizeof(val))) {
446                         rv = -EFAULT;
447                         break;
448                 }
449
450                 rv = ipmi_set_my_address(priv->user, 0, val);
451                 break;
452         }
453
454         case IPMICTL_GET_MY_ADDRESS_CMD:
455         {
456                 unsigned int  val;
457                 unsigned char rval;
458
459                 rv = ipmi_get_my_address(priv->user, 0, &rval);
460                 if (rv)
461                         break;
462
463                 val = rval;
464
465                 if (copy_to_user(arg, &val, sizeof(val))) {
466                         rv = -EFAULT;
467                         break;
468                 }
469                 break;
470         }
471
472         case IPMICTL_SET_MY_LUN_CMD:
473         {
474                 unsigned int val;
475
476                 if (copy_from_user(&val, arg, sizeof(val))) {
477                         rv = -EFAULT;
478                         break;
479                 }
480
481                 rv = ipmi_set_my_LUN(priv->user, 0, val);
482                 break;
483         }
484
485         case IPMICTL_GET_MY_LUN_CMD:
486         {
487                 unsigned int  val;
488                 unsigned char rval;
489
490                 rv = ipmi_get_my_LUN(priv->user, 0, &rval);
491                 if (rv)
492                         break;
493
494                 val = rval;
495
496                 if (copy_to_user(arg, &val, sizeof(val))) {
497                         rv = -EFAULT;
498                         break;
499                 }
500                 break;
501         }
502
503         case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
504         {
505                 struct ipmi_channel_lun_address_set val;
506
507                 if (copy_from_user(&val, arg, sizeof(val))) {
508                         rv = -EFAULT;
509                         break;
510                 }
511
512                 return ipmi_set_my_address(priv->user, val.channel, val.value);
513                 break;
514         }
515
516         case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
517         {
518                 struct ipmi_channel_lun_address_set val;
519
520                 if (copy_from_user(&val, arg, sizeof(val))) {
521                         rv = -EFAULT;
522                         break;
523                 }
524
525                 rv = ipmi_get_my_address(priv->user, val.channel, &val.value);
526                 if (rv)
527                         break;
528
529                 if (copy_to_user(arg, &val, sizeof(val))) {
530                         rv = -EFAULT;
531                         break;
532                 }
533                 break;
534         }
535
536         case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
537         {
538                 struct ipmi_channel_lun_address_set val;
539
540                 if (copy_from_user(&val, arg, sizeof(val))) {
541                         rv = -EFAULT;
542                         break;
543                 }
544
545                 rv = ipmi_set_my_LUN(priv->user, val.channel, val.value);
546                 break;
547         }
548
549         case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
550         {
551                 struct ipmi_channel_lun_address_set val;
552
553                 if (copy_from_user(&val, arg, sizeof(val))) {
554                         rv = -EFAULT;
555                         break;
556                 }
557
558                 rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value);
559                 if (rv)
560                         break;
561
562                 if (copy_to_user(arg, &val, sizeof(val))) {
563                         rv = -EFAULT;
564                         break;
565                 }
566                 break;
567         }
568
569         case IPMICTL_SET_TIMING_PARMS_CMD:
570         {
571                 struct ipmi_timing_parms parms;
572
573                 if (copy_from_user(&parms, arg, sizeof(parms))) {
574                         rv = -EFAULT;
575                         break;
576                 }
577
578                 priv->default_retries = parms.retries;
579                 priv->default_retry_time_ms = parms.retry_time_ms;
580                 rv = 0;
581                 break;
582         }
583
584         case IPMICTL_GET_TIMING_PARMS_CMD:
585         {
586                 struct ipmi_timing_parms parms;
587
588                 parms.retries = priv->default_retries;
589                 parms.retry_time_ms = priv->default_retry_time_ms;
590
591                 if (copy_to_user(arg, &parms, sizeof(parms))) {
592                         rv = -EFAULT;
593                         break;
594                 }
595
596                 rv = 0;
597                 break;
598         }
599
600         case IPMICTL_GET_MAINTENANCE_MODE_CMD:
601         {
602                 int mode;
603
604                 mode = ipmi_get_maintenance_mode(priv->user);
605                 if (copy_to_user(arg, &mode, sizeof(mode))) {
606                         rv = -EFAULT;
607                         break;
608                 }
609                 rv = 0;
610                 break;
611         }
612
613         case IPMICTL_SET_MAINTENANCE_MODE_CMD:
614         {
615                 int mode;
616
617                 if (copy_from_user(&mode, arg, sizeof(mode))) {
618                         rv = -EFAULT;
619                         break;
620                 }
621                 rv = ipmi_set_maintenance_mode(priv->user, mode);
622                 break;
623         }
624         }
625   
626         return rv;
627 }
628
629 #ifdef CONFIG_COMPAT
630
631 /*
632  * The following code contains code for supporting 32-bit compatible
633  * ioctls on 64-bit kernels.  This allows running 32-bit apps on the
634  * 64-bit kernel
635  */
636 #define COMPAT_IPMICTL_SEND_COMMAND     \
637         _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
638 #define COMPAT_IPMICTL_SEND_COMMAND_SETTIME     \
639         _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
640 #define COMPAT_IPMICTL_RECEIVE_MSG      \
641         _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
642 #define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC        \
643         _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
644
645 struct compat_ipmi_msg {
646         u8              netfn;
647         u8              cmd;
648         u16             data_len;
649         compat_uptr_t   data;
650 };
651
652 struct compat_ipmi_req {
653         compat_uptr_t           addr;
654         compat_uint_t           addr_len;
655         compat_long_t           msgid;
656         struct compat_ipmi_msg  msg;
657 };
658
659 struct compat_ipmi_recv {
660         compat_int_t            recv_type;
661         compat_uptr_t           addr;
662         compat_uint_t           addr_len;
663         compat_long_t           msgid;
664         struct compat_ipmi_msg  msg;
665 };
666
667 struct compat_ipmi_req_settime {
668         struct compat_ipmi_req  req;
669         compat_int_t            retries;
670         compat_uint_t           retry_time_ms;
671 };
672
673 /*
674  * Define some helper functions for copying IPMI data
675  */
676 static long get_compat_ipmi_msg(struct ipmi_msg *p64,
677                                 struct compat_ipmi_msg __user *p32)
678 {
679         compat_uptr_t tmp;
680
681         if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
682                         __get_user(p64->netfn, &p32->netfn) ||
683                         __get_user(p64->cmd, &p32->cmd) ||
684                         __get_user(p64->data_len, &p32->data_len) ||
685                         __get_user(tmp, &p32->data))
686                 return -EFAULT;
687         p64->data = compat_ptr(tmp);
688         return 0;
689 }
690
691 static long put_compat_ipmi_msg(struct ipmi_msg *p64,
692                                 struct compat_ipmi_msg __user *p32)
693 {
694         if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
695                         __put_user(p64->netfn, &p32->netfn) ||
696                         __put_user(p64->cmd, &p32->cmd) ||
697                         __put_user(p64->data_len, &p32->data_len))
698                 return -EFAULT;
699         return 0;
700 }
701
702 static long get_compat_ipmi_req(struct ipmi_req *p64,
703                                 struct compat_ipmi_req __user *p32)
704 {
705
706         compat_uptr_t   tmp;
707
708         if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
709                         __get_user(tmp, &p32->addr) ||
710                         __get_user(p64->addr_len, &p32->addr_len) ||
711                         __get_user(p64->msgid, &p32->msgid) ||
712                         get_compat_ipmi_msg(&p64->msg, &p32->msg))
713                 return -EFAULT;
714         p64->addr = compat_ptr(tmp);
715         return 0;
716 }
717
718 static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
719                 struct compat_ipmi_req_settime __user *p32)
720 {
721         if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
722                         get_compat_ipmi_req(&p64->req, &p32->req) ||
723                         __get_user(p64->retries, &p32->retries) ||
724                         __get_user(p64->retry_time_ms, &p32->retry_time_ms))
725                 return -EFAULT;
726         return 0;
727 }
728
729 static long get_compat_ipmi_recv(struct ipmi_recv *p64,
730                                  struct compat_ipmi_recv __user *p32)
731 {
732         compat_uptr_t tmp;
733
734         if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
735                         __get_user(p64->recv_type, &p32->recv_type) ||
736                         __get_user(tmp, &p32->addr) ||
737                         __get_user(p64->addr_len, &p32->addr_len) ||
738                         __get_user(p64->msgid, &p32->msgid) ||
739                         get_compat_ipmi_msg(&p64->msg, &p32->msg))
740                 return -EFAULT;
741         p64->addr = compat_ptr(tmp);
742         return 0;
743 }
744
745 static long put_compat_ipmi_recv(struct ipmi_recv *p64,
746                                  struct compat_ipmi_recv __user *p32)
747 {
748         if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
749                         __put_user(p64->recv_type, &p32->recv_type) ||
750                         __put_user(p64->addr_len, &p32->addr_len) ||
751                         __put_user(p64->msgid, &p32->msgid) ||
752                         put_compat_ipmi_msg(&p64->msg, &p32->msg))
753                 return -EFAULT;
754         return 0;
755 }
756
757 /*
758  * Handle compatibility ioctls
759  */
760 static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
761                               unsigned long arg)
762 {
763         int rc;
764         struct ipmi_file_private *priv = filep->private_data;
765
766         switch(cmd) {
767         case COMPAT_IPMICTL_SEND_COMMAND:
768         {
769                 struct ipmi_req rp;
770
771                 if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
772                         return -EFAULT;
773
774                 return handle_send_req(priv->user, &rp,
775                                 priv->default_retries,
776                                 priv->default_retry_time_ms);
777         }
778         case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
779         {
780                 struct ipmi_req_settime sp;
781
782                 if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
783                         return -EFAULT;
784
785                 return handle_send_req(priv->user, &sp.req,
786                                 sp.retries, sp.retry_time_ms);
787         }
788         case COMPAT_IPMICTL_RECEIVE_MSG:
789         case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
790         {
791                 struct ipmi_recv   __user *precv64;
792                 struct ipmi_recv   recv64;
793
794                 if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
795                         return -EFAULT;
796
797                 precv64 = compat_alloc_user_space(sizeof(recv64));
798                 if (copy_to_user(precv64, &recv64, sizeof(recv64)))
799                         return -EFAULT;
800
801                 rc = ipmi_ioctl(filep->f_path.dentry->d_inode, filep,
802                                 ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
803                                  ? IPMICTL_RECEIVE_MSG
804                                  : IPMICTL_RECEIVE_MSG_TRUNC),
805                                 (unsigned long) precv64);
806                 if (rc != 0)
807                         return rc;
808
809                 if (copy_from_user(&recv64, precv64, sizeof(recv64)))
810                         return -EFAULT;
811
812                 if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
813                         return -EFAULT;
814
815                 return rc;
816         }
817         default:
818                 return ipmi_ioctl(filep->f_path.dentry->d_inode, filep, cmd, arg);
819         }
820 }
821 #endif
822
823 static const struct file_operations ipmi_fops = {
824         .owner          = THIS_MODULE,
825         .ioctl          = ipmi_ioctl,
826 #ifdef CONFIG_COMPAT
827         .compat_ioctl   = compat_ipmi_ioctl,
828 #endif
829         .open           = ipmi_open,
830         .release        = ipmi_release,
831         .fasync         = ipmi_fasync,
832         .poll           = ipmi_poll,
833 };
834
835 #define DEVICE_NAME     "ipmidev"
836
837 static int ipmi_major;
838 module_param(ipmi_major, int, 0);
839 MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device.  By"
840                  " default, or if you set it to zero, it will choose the next"
841                  " available device.  Setting it to -1 will disable the"
842                  " interface.  Other values will set the major device number"
843                  " to that value.");
844
845 /* Keep track of the devices that are registered. */
846 struct ipmi_reg_list {
847         dev_t            dev;
848         struct list_head link;
849 };
850 static LIST_HEAD(reg_list);
851 static DEFINE_MUTEX(reg_list_mutex);
852
853 static struct class *ipmi_class;
854
855 static void ipmi_new_smi(int if_num, struct device *device)
856 {
857         dev_t dev = MKDEV(ipmi_major, if_num);
858         struct ipmi_reg_list *entry;
859
860         entry = kmalloc(sizeof(*entry), GFP_KERNEL);
861         if (!entry) {
862                 printk(KERN_ERR "ipmi_devintf: Unable to create the"
863                        " ipmi class device link\n");
864                 return;
865         }
866         entry->dev = dev;
867
868         mutex_lock(&reg_list_mutex);
869         class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num);
870         list_add(&entry->link, &reg_list);
871         mutex_unlock(&reg_list_mutex);
872 }
873
874 static void ipmi_smi_gone(int if_num)
875 {
876         dev_t dev = MKDEV(ipmi_major, if_num);
877         struct ipmi_reg_list *entry;
878
879         mutex_lock(&reg_list_mutex);
880         list_for_each_entry(entry, &reg_list, link) {
881                 if (entry->dev == dev) {
882                         list_del(&entry->link);
883                         kfree(entry);
884                         break;
885                 }
886         }
887         class_device_destroy(ipmi_class, dev);
888         mutex_unlock(&reg_list_mutex);
889 }
890
891 static struct ipmi_smi_watcher smi_watcher =
892 {
893         .owner    = THIS_MODULE,
894         .new_smi  = ipmi_new_smi,
895         .smi_gone = ipmi_smi_gone,
896 };
897
898 static __init int init_ipmi_devintf(void)
899 {
900         int rv;
901
902         if (ipmi_major < 0)
903                 return -EINVAL;
904
905         printk(KERN_INFO "ipmi device interface\n");
906
907         ipmi_class = class_create(THIS_MODULE, "ipmi");
908         if (IS_ERR(ipmi_class)) {
909                 printk(KERN_ERR "ipmi: can't register device class\n");
910                 return PTR_ERR(ipmi_class);
911         }
912
913         rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
914         if (rv < 0) {
915                 class_destroy(ipmi_class);
916                 printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
917                 return rv;
918         }
919
920         if (ipmi_major == 0) {
921                 ipmi_major = rv;
922         }
923
924         rv = ipmi_smi_watcher_register(&smi_watcher);
925         if (rv) {
926                 unregister_chrdev(ipmi_major, DEVICE_NAME);
927                 class_destroy(ipmi_class);
928                 printk(KERN_WARNING "ipmi: can't register smi watcher\n");
929                 return rv;
930         }
931
932         return 0;
933 }
934 module_init(init_ipmi_devintf);
935
936 static __exit void cleanup_ipmi(void)
937 {
938         struct ipmi_reg_list *entry, *entry2;
939         mutex_lock(&reg_list_mutex);
940         list_for_each_entry_safe(entry, entry2, &reg_list, link) {
941                 list_del(&entry->link);
942                 class_device_destroy(ipmi_class, entry->dev);
943                 kfree(entry);
944         }
945         mutex_unlock(&reg_list_mutex);
946         class_destroy(ipmi_class);
947         ipmi_smi_watcher_unregister(&smi_watcher);
948         unregister_chrdev(ipmi_major, DEVICE_NAME);
949 }
950 module_exit(cleanup_ipmi);
951
952 MODULE_LICENSE("GPL");
953 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
954 MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");