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