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