1
2
3
4
5
6
7
8
9
10
11
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
27struct 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
39static 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
57static __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
75static 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
82static const struct ipmi_user_hndl ipmi_hndlrs =
83{
84 .ipmi_recv_hndl = file_receive_handler,
85};
86
87static 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
115 priv->default_retries = -1;
116 priv->default_retry_time_ms = 0;
117
118out:
119 return rv;
120}
121
122static 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
140static 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
163
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
198static 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
210
211
212
213
214
215
216
217 mutex_lock(&priv->recv_mutex);
218
219
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
278recv_putback_on_err:
279
280
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);
284recv_err:
285 mutex_unlock(&priv->recv_mutex);
286 return rv;
287}
288
289static 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
294static 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
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
621
622
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
633struct compat_ipmi_msg {
634 u8 netfn;
635 u8 cmd;
636 u16 data_len;
637 compat_uptr_t data;
638};
639
640struct 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
647struct 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
655struct 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
663
664static 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
673static 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
682static 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
690static 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
701static 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
718
719static 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
779static 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
794static int ipmi_major;
795module_param(ipmi_major, int, 0);
796MODULE_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
803struct ipmi_reg_list {
804 dev_t dev;
805 struct list_head link;
806};
807static LIST_HEAD(reg_list);
808static DEFINE_MUTEX(reg_list_mutex);
809
810static struct class *ipmi_class;
811
812static 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(®_list_mutex);
825 device_create(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
826 list_add(&entry->link, ®_list);
827 mutex_unlock(®_list_mutex);
828}
829
830static 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(®_list_mutex);
836 list_for_each_entry(entry, ®_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(®_list_mutex);
845}
846
847static 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
854static 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(THIS_MODULE, "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}
890module_init(init_ipmi_devintf);
891
892static void __exit cleanup_ipmi(void)
893{
894 struct ipmi_reg_list *entry, *entry2;
895 mutex_lock(®_list_mutex);
896 list_for_each_entry_safe(entry, entry2, ®_list, link) {
897 list_del(&entry->link);
898 device_destroy(ipmi_class, entry->dev);
899 kfree(entry);
900 }
901 mutex_unlock(®_list_mutex);
902 class_destroy(ipmi_class);
903 ipmi_smi_watcher_unregister(&smi_watcher);
904 unregister_chrdev(ipmi_major, DEVICE_NAME);
905}
906module_exit(cleanup_ipmi);
907
908MODULE_LICENSE("GPL");
909MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
910MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");
911