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