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