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