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