xref: /openbmc/linux/drivers/char/ipmi/ipmi_devintf.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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");
583