Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.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/devfs_fs_kernel.h>
44 #include <linux/ipmi.h>
45 #include <asm/semaphore.h>
46 #include <linux/init.h>
47
48 #define IPMI_DEVINTF_VERSION "v33"
49
50 struct ipmi_file_private
51 {
52         ipmi_user_t          user;
53         spinlock_t           recv_msg_lock;
54         struct list_head     recv_msgs;
55         struct file          *file;
56         struct fasync_struct *fasync_queue;
57         wait_queue_head_t    wait;
58         struct semaphore     recv_sem;
59         int                  default_retries;
60         unsigned int         default_retry_time_ms;
61 };
62
63 static void file_receive_handler(struct ipmi_recv_msg *msg,
64                                  void                 *handler_data)
65 {
66         struct ipmi_file_private *priv = handler_data;
67         int                      was_empty;
68         unsigned long            flags;
69
70         spin_lock_irqsave(&(priv->recv_msg_lock), flags);
71
72         was_empty = list_empty(&(priv->recv_msgs));
73         list_add_tail(&(msg->link), &(priv->recv_msgs));
74
75         if (was_empty) {
76                 wake_up_interruptible(&priv->wait);
77                 kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
78         }
79
80         spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
81 }
82
83 static unsigned int ipmi_poll(struct file *file, poll_table *wait)
84 {
85         struct ipmi_file_private *priv = file->private_data;
86         unsigned int             mask = 0;
87         unsigned long            flags;
88
89         poll_wait(file, &priv->wait, wait);
90
91         spin_lock_irqsave(&priv->recv_msg_lock, flags);
92
93         if (! list_empty(&(priv->recv_msgs)))
94                 mask |= (POLLIN | POLLRDNORM);
95
96         spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
97
98         return mask;
99 }
100
101 static int ipmi_fasync(int fd, struct file *file, int on)
102 {
103         struct ipmi_file_private *priv = file->private_data;
104         int                      result;
105
106         result = fasync_helper(fd, file, on, &priv->fasync_queue);
107
108         return (result);
109 }
110
111 static struct ipmi_user_hndl ipmi_hndlrs =
112 {
113         .ipmi_recv_hndl = file_receive_handler,
114 };
115
116 static int ipmi_open(struct inode *inode, struct file *file)
117 {
118         int                      if_num = iminor(inode);
119         int                      rv;
120         struct ipmi_file_private *priv;
121
122
123         priv = kmalloc(sizeof(*priv), GFP_KERNEL);
124         if (!priv)
125                 return -ENOMEM;
126
127         priv->file = file;
128
129         rv = ipmi_create_user(if_num,
130                               &ipmi_hndlrs,
131                               priv,
132                               &(priv->user));
133         if (rv) {
134                 kfree(priv);
135                 return rv;
136         }
137
138         file->private_data = priv;
139
140         spin_lock_init(&(priv->recv_msg_lock));
141         INIT_LIST_HEAD(&(priv->recv_msgs));
142         init_waitqueue_head(&priv->wait);
143         priv->fasync_queue = NULL;
144         sema_init(&(priv->recv_sem), 1);
145
146         /* Use the low-level defaults. */
147         priv->default_retries = -1;
148         priv->default_retry_time_ms = 0;
149
150         return 0;
151 }
152
153 static int ipmi_release(struct inode *inode, struct file *file)
154 {
155         struct ipmi_file_private *priv = file->private_data;
156         int                      rv;
157
158         rv = ipmi_destroy_user(priv->user);
159         if (rv)
160                 return rv;
161
162         ipmi_fasync (-1, file, 0);
163
164         /* FIXME - free the messages in the list. */
165         kfree(priv);
166
167         return 0;
168 }
169
170 static int handle_send_req(ipmi_user_t     user,
171                            struct ipmi_req *req,
172                            int             retries,
173                            unsigned int    retry_time_ms)
174 {
175         int              rv;
176         struct ipmi_addr addr;
177         struct kernel_ipmi_msg msg;
178
179         if (req->addr_len > sizeof(struct ipmi_addr))
180                 return -EINVAL;
181
182         if (copy_from_user(&addr, req->addr, req->addr_len))
183                 return -EFAULT;
184
185         msg.netfn = req->msg.netfn;
186         msg.cmd = req->msg.cmd;
187         msg.data_len = req->msg.data_len;
188         msg.data = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
189         if (!msg.data)
190                 return -ENOMEM;
191
192         /* From here out we cannot return, we must jump to "out" for
193            error exits to free msgdata. */
194
195         rv = ipmi_validate_addr(&addr, req->addr_len);
196         if (rv)
197                 goto out;
198
199         if (req->msg.data != NULL) {
200                 if (req->msg.data_len > IPMI_MAX_MSG_LENGTH) {
201                         rv = -EMSGSIZE;
202                         goto out;
203                 }
204
205                 if (copy_from_user(msg.data,
206                                    req->msg.data,
207                                    req->msg.data_len))
208                 {
209                         rv = -EFAULT;
210                         goto out;
211                 }
212         } else {
213                 msg.data_len = 0;
214         }
215
216         rv = ipmi_request_settime(user,
217                                   &addr,
218                                   req->msgid,
219                                   &msg,
220                                   NULL,
221                                   0,
222                                   retries,
223                                   retry_time_ms);
224  out:
225         kfree(msg.data);
226         return rv;
227 }
228
229 static int ipmi_ioctl(struct inode  *inode,
230                       struct file   *file,
231                       unsigned int  cmd,
232                       unsigned long data)
233 {
234         int                      rv = -EINVAL;
235         struct ipmi_file_private *priv = file->private_data;
236         void __user *arg = (void __user *)data;
237
238         switch (cmd) 
239         {
240         case IPMICTL_SEND_COMMAND:
241         {
242                 struct ipmi_req req;
243
244                 if (copy_from_user(&req, arg, sizeof(req))) {
245                         rv = -EFAULT;
246                         break;
247                 }
248
249                 rv = handle_send_req(priv->user,
250                                      &req,
251                                      priv->default_retries,
252                                      priv->default_retry_time_ms);
253                 break;
254         }
255
256         case IPMICTL_SEND_COMMAND_SETTIME:
257         {
258                 struct ipmi_req_settime req;
259
260                 if (copy_from_user(&req, arg, sizeof(req))) {
261                         rv = -EFAULT;
262                         break;
263                 }
264
265                 rv = handle_send_req(priv->user,
266                                      &req.req,
267                                      req.retries,
268                                      req.retry_time_ms);
269                 break;
270         }
271
272         case IPMICTL_RECEIVE_MSG:
273         case IPMICTL_RECEIVE_MSG_TRUNC:
274         {
275                 struct ipmi_recv      rsp;
276                 int              addr_len;
277                 struct list_head *entry;
278                 struct ipmi_recv_msg  *msg;
279                 unsigned long    flags;
280                 
281
282                 rv = 0;
283                 if (copy_from_user(&rsp, arg, sizeof(rsp))) {
284                         rv = -EFAULT;
285                         break;
286                 }
287
288                 /* We claim a semaphore because we don't want two
289                    users getting something from the queue at a time.
290                    Since we have to release the spinlock before we can
291                    copy the data to the user, it's possible another
292                    user will grab something from the queue, too.  Then
293                    the messages might get out of order if something
294                    fails and the message gets put back onto the
295                    queue.  This semaphore prevents that problem. */
296                 down(&(priv->recv_sem));
297
298                 /* Grab the message off the list. */
299                 spin_lock_irqsave(&(priv->recv_msg_lock), flags);
300                 if (list_empty(&(priv->recv_msgs))) {
301                         spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
302                         rv = -EAGAIN;
303                         goto recv_err;
304                 }
305                 entry = priv->recv_msgs.next;
306                 msg = list_entry(entry, struct ipmi_recv_msg, link);
307                 list_del(entry);
308                 spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
309
310                 addr_len = ipmi_addr_length(msg->addr.addr_type);
311                 if (rsp.addr_len < addr_len)
312                 {
313                         rv = -EINVAL;
314                         goto recv_putback_on_err;
315                 }
316
317                 if (copy_to_user(rsp.addr, &(msg->addr), addr_len)) {
318                         rv = -EFAULT;
319                         goto recv_putback_on_err;
320                 }
321                 rsp.addr_len = addr_len;
322
323                 rsp.recv_type = msg->recv_type;
324                 rsp.msgid = msg->msgid;
325                 rsp.msg.netfn = msg->msg.netfn;
326                 rsp.msg.cmd = msg->msg.cmd;
327
328                 if (msg->msg.data_len > 0) {
329                         if (rsp.msg.data_len < msg->msg.data_len) {
330                                 rv = -EMSGSIZE;
331                                 if (cmd == IPMICTL_RECEIVE_MSG_TRUNC) {
332                                         msg->msg.data_len = rsp.msg.data_len;
333                                 } else {
334                                         goto recv_putback_on_err;
335                                 }
336                         }
337
338                         if (copy_to_user(rsp.msg.data,
339                                          msg->msg.data,
340                                          msg->msg.data_len))
341                         {
342                                 rv = -EFAULT;
343                                 goto recv_putback_on_err;
344                         }
345                         rsp.msg.data_len = msg->msg.data_len;
346                 } else {
347                         rsp.msg.data_len = 0;
348                 }
349
350                 if (copy_to_user(arg, &rsp, sizeof(rsp))) {
351                         rv = -EFAULT;
352                         goto recv_putback_on_err;
353                 }
354
355                 up(&(priv->recv_sem));
356                 ipmi_free_recv_msg(msg);
357                 break;
358
359         recv_putback_on_err:
360                 /* If we got an error, put the message back onto
361                    the head of the queue. */
362                 spin_lock_irqsave(&(priv->recv_msg_lock), flags);
363                 list_add(entry, &(priv->recv_msgs));
364                 spin_unlock_irqrestore(&(priv->recv_msg_lock), flags);
365                 up(&(priv->recv_sem));
366                 break;
367
368         recv_err:
369                 up(&(priv->recv_sem));
370                 break;
371         }
372
373         case IPMICTL_REGISTER_FOR_CMD:
374         {
375                 struct ipmi_cmdspec val;
376
377                 if (copy_from_user(&val, arg, sizeof(val))) {
378                         rv = -EFAULT;
379                         break;
380                 }
381
382                 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd);
383                 break;
384         }
385
386         case IPMICTL_UNREGISTER_FOR_CMD:
387         {
388                 struct ipmi_cmdspec   val;
389
390                 if (copy_from_user(&val, arg, sizeof(val))) {
391                         rv = -EFAULT;
392                         break;
393                 }
394
395                 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd);
396                 break;
397         }
398
399         case IPMICTL_SET_GETS_EVENTS_CMD:
400         {
401                 int val;
402
403                 if (copy_from_user(&val, arg, sizeof(val))) {
404                         rv = -EFAULT;
405                         break;
406                 }
407
408                 rv = ipmi_set_gets_events(priv->user, val);
409                 break;
410         }
411
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                 ipmi_set_my_address(priv->user, val);
422                 rv = 0;
423                 break;
424         }
425
426         case IPMICTL_GET_MY_ADDRESS_CMD:
427         {
428                 unsigned int val;
429
430                 val = ipmi_get_my_address(priv->user);
431
432                 if (copy_to_user(arg, &val, sizeof(val))) {
433                         rv = -EFAULT;
434                         break;
435                 }
436                 rv = 0;
437                 break;
438         }
439
440         case IPMICTL_SET_MY_LUN_CMD:
441         {
442                 unsigned int val;
443
444                 if (copy_from_user(&val, arg, sizeof(val))) {
445                         rv = -EFAULT;
446                         break;
447                 }
448
449                 ipmi_set_my_LUN(priv->user, val);
450                 rv = 0;
451                 break;
452         }
453
454         case IPMICTL_GET_MY_LUN_CMD:
455         {
456                 unsigned int val;
457
458                 val = ipmi_get_my_LUN(priv->user);
459
460                 if (copy_to_user(arg, &val, sizeof(val))) {
461                         rv = -EFAULT;
462                         break;
463                 }
464                 rv = 0;
465                 break;
466         }
467         case IPMICTL_SET_TIMING_PARMS_CMD:
468         {
469                 struct ipmi_timing_parms parms;
470
471                 if (copy_from_user(&parms, arg, sizeof(parms))) {
472                         rv = -EFAULT;
473                         break;
474                 }
475
476                 priv->default_retries = parms.retries;
477                 priv->default_retry_time_ms = parms.retry_time_ms;
478                 rv = 0;
479                 break;
480         }
481
482         case IPMICTL_GET_TIMING_PARMS_CMD:
483         {
484                 struct ipmi_timing_parms parms;
485
486                 parms.retries = priv->default_retries;
487                 parms.retry_time_ms = priv->default_retry_time_ms;
488
489                 if (copy_to_user(arg, &parms, sizeof(parms))) {
490                         rv = -EFAULT;
491                         break;
492                 }
493
494                 rv = 0;
495                 break;
496         }
497         }
498   
499         return rv;
500 }
501
502
503 static struct file_operations ipmi_fops = {
504         .owner          = THIS_MODULE,
505         .ioctl          = ipmi_ioctl,
506         .open           = ipmi_open,
507         .release        = ipmi_release,
508         .fasync         = ipmi_fasync,
509         .poll           = ipmi_poll,
510 };
511
512 #define DEVICE_NAME     "ipmidev"
513
514 static int ipmi_major = 0;
515 module_param(ipmi_major, int, 0);
516 MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device.  By"
517                  " default, or if you set it to zero, it will choose the next"
518                  " available device.  Setting it to -1 will disable the"
519                  " interface.  Other values will set the major device number"
520                  " to that value.");
521
522 static void ipmi_new_smi(int if_num)
523 {
524         devfs_mk_cdev(MKDEV(ipmi_major, if_num),
525                       S_IFCHR | S_IRUSR | S_IWUSR,
526                       "ipmidev/%d", if_num);
527 }
528
529 static void ipmi_smi_gone(int if_num)
530 {
531         devfs_remove("ipmidev/%d", if_num);
532 }
533
534 static struct ipmi_smi_watcher smi_watcher =
535 {
536         .owner    = THIS_MODULE,
537         .new_smi  = ipmi_new_smi,
538         .smi_gone = ipmi_smi_gone,
539 };
540
541 static __init int init_ipmi_devintf(void)
542 {
543         int rv;
544
545         if (ipmi_major < 0)
546                 return -EINVAL;
547
548         printk(KERN_INFO "ipmi device interface version "
549                IPMI_DEVINTF_VERSION "\n");
550
551         rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
552         if (rv < 0) {
553                 printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
554                 return rv;
555         }
556
557         if (ipmi_major == 0) {
558                 ipmi_major = rv;
559         }
560
561         devfs_mk_dir(DEVICE_NAME);
562
563         rv = ipmi_smi_watcher_register(&smi_watcher);
564         if (rv) {
565                 unregister_chrdev(ipmi_major, DEVICE_NAME);
566                 printk(KERN_WARNING "ipmi: can't register smi watcher\n");
567                 return rv;
568         }
569
570         return 0;
571 }
572 module_init(init_ipmi_devintf);
573
574 static __exit void cleanup_ipmi(void)
575 {
576         ipmi_smi_watcher_unregister(&smi_watcher);
577         devfs_remove(DEVICE_NAME);
578         unregister_chrdev(ipmi_major, DEVICE_NAME);
579 }
580 module_exit(cleanup_ipmi);
581
582 MODULE_LICENSE("GPL");