0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/module.h>
0015 #include <linux/moduleparam.h>
0016 #include <linux/errno.h>
0017 #include <linux/poll.h>
0018 #include <linux/sched.h>
0019 #include <linux/spinlock.h>
0020 #include <linux/slab.h>
0021 #include <linux/ipmi.h>
0022 #include <linux/mutex.h>
0023 #include <linux/init.h>
0024 #include <linux/device.h>
0025 #include <linux/compat.h>
0026
0027 struct ipmi_file_private
0028 {
0029 struct ipmi_user *user;
0030 spinlock_t recv_msg_lock;
0031 struct list_head recv_msgs;
0032 struct fasync_struct *fasync_queue;
0033 wait_queue_head_t wait;
0034 struct mutex recv_mutex;
0035 int default_retries;
0036 unsigned int default_retry_time_ms;
0037 };
0038
0039 static void file_receive_handler(struct ipmi_recv_msg *msg,
0040 void *handler_data)
0041 {
0042 struct ipmi_file_private *priv = handler_data;
0043 int was_empty;
0044 unsigned long flags;
0045
0046 spin_lock_irqsave(&priv->recv_msg_lock, flags);
0047 was_empty = list_empty(&priv->recv_msgs);
0048 list_add_tail(&msg->link, &priv->recv_msgs);
0049 spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0050
0051 if (was_empty) {
0052 wake_up_interruptible(&priv->wait);
0053 kill_fasync(&priv->fasync_queue, SIGIO, POLL_IN);
0054 }
0055 }
0056
0057 static __poll_t ipmi_poll(struct file *file, poll_table *wait)
0058 {
0059 struct ipmi_file_private *priv = file->private_data;
0060 __poll_t mask = 0;
0061 unsigned long flags;
0062
0063 poll_wait(file, &priv->wait, wait);
0064
0065 spin_lock_irqsave(&priv->recv_msg_lock, flags);
0066
0067 if (!list_empty(&priv->recv_msgs))
0068 mask |= (EPOLLIN | EPOLLRDNORM);
0069
0070 spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0071
0072 return mask;
0073 }
0074
0075 static int ipmi_fasync(int fd, struct file *file, int on)
0076 {
0077 struct ipmi_file_private *priv = file->private_data;
0078
0079 return fasync_helper(fd, file, on, &priv->fasync_queue);
0080 }
0081
0082 static const struct ipmi_user_hndl ipmi_hndlrs =
0083 {
0084 .ipmi_recv_hndl = file_receive_handler,
0085 };
0086
0087 static int ipmi_open(struct inode *inode, struct file *file)
0088 {
0089 int if_num = iminor(inode);
0090 int rv;
0091 struct ipmi_file_private *priv;
0092
0093 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
0094 if (!priv)
0095 return -ENOMEM;
0096
0097 rv = ipmi_create_user(if_num,
0098 &ipmi_hndlrs,
0099 priv,
0100 &priv->user);
0101 if (rv) {
0102 kfree(priv);
0103 goto out;
0104 }
0105
0106 file->private_data = priv;
0107
0108 spin_lock_init(&priv->recv_msg_lock);
0109 INIT_LIST_HEAD(&priv->recv_msgs);
0110 init_waitqueue_head(&priv->wait);
0111 priv->fasync_queue = NULL;
0112 mutex_init(&priv->recv_mutex);
0113
0114
0115 priv->default_retries = -1;
0116 priv->default_retry_time_ms = 0;
0117
0118 out:
0119 return rv;
0120 }
0121
0122 static int ipmi_release(struct inode *inode, struct file *file)
0123 {
0124 struct ipmi_file_private *priv = file->private_data;
0125 int rv;
0126 struct ipmi_recv_msg *msg, *next;
0127
0128 rv = ipmi_destroy_user(priv->user);
0129 if (rv)
0130 return rv;
0131
0132 list_for_each_entry_safe(msg, next, &priv->recv_msgs, link)
0133 ipmi_free_recv_msg(msg);
0134
0135 kfree(priv);
0136
0137 return 0;
0138 }
0139
0140 static int handle_send_req(struct ipmi_user *user,
0141 struct ipmi_req *req,
0142 int retries,
0143 unsigned int retry_time_ms)
0144 {
0145 int rv;
0146 struct ipmi_addr addr;
0147 struct kernel_ipmi_msg msg;
0148
0149 if (req->addr_len > sizeof(struct ipmi_addr))
0150 return -EINVAL;
0151
0152 if (copy_from_user(&addr, req->addr, req->addr_len))
0153 return -EFAULT;
0154
0155 msg.netfn = req->msg.netfn;
0156 msg.cmd = req->msg.cmd;
0157 msg.data_len = req->msg.data_len;
0158 msg.data = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
0159 if (!msg.data)
0160 return -ENOMEM;
0161
0162
0163
0164
0165 rv = ipmi_validate_addr(&addr, req->addr_len);
0166 if (rv)
0167 goto out;
0168
0169 if (req->msg.data != NULL) {
0170 if (req->msg.data_len > IPMI_MAX_MSG_LENGTH) {
0171 rv = -EMSGSIZE;
0172 goto out;
0173 }
0174
0175 if (copy_from_user(msg.data,
0176 req->msg.data,
0177 req->msg.data_len)) {
0178 rv = -EFAULT;
0179 goto out;
0180 }
0181 } else {
0182 msg.data_len = 0;
0183 }
0184
0185 rv = ipmi_request_settime(user,
0186 &addr,
0187 req->msgid,
0188 &msg,
0189 NULL,
0190 0,
0191 retries,
0192 retry_time_ms);
0193 out:
0194 kfree(msg.data);
0195 return rv;
0196 }
0197
0198 static int handle_recv(struct ipmi_file_private *priv,
0199 bool trunc, struct ipmi_recv *rsp,
0200 int (*copyout)(struct ipmi_recv *, void __user *),
0201 void __user *to)
0202 {
0203 int addr_len;
0204 struct list_head *entry;
0205 struct ipmi_recv_msg *msg;
0206 unsigned long flags;
0207 int rv = 0, rv2 = 0;
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217 mutex_lock(&priv->recv_mutex);
0218
0219
0220 spin_lock_irqsave(&priv->recv_msg_lock, flags);
0221 if (list_empty(&(priv->recv_msgs))) {
0222 spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0223 rv = -EAGAIN;
0224 goto recv_err;
0225 }
0226 entry = priv->recv_msgs.next;
0227 msg = list_entry(entry, struct ipmi_recv_msg, link);
0228 list_del(entry);
0229 spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0230
0231 addr_len = ipmi_addr_length(msg->addr.addr_type);
0232 if (rsp->addr_len < addr_len) {
0233 rv = -EINVAL;
0234 goto recv_putback_on_err;
0235 }
0236
0237 if (copy_to_user(rsp->addr, &msg->addr, addr_len)) {
0238 rv = -EFAULT;
0239 goto recv_putback_on_err;
0240 }
0241 rsp->addr_len = addr_len;
0242
0243 rsp->recv_type = msg->recv_type;
0244 rsp->msgid = msg->msgid;
0245 rsp->msg.netfn = msg->msg.netfn;
0246 rsp->msg.cmd = msg->msg.cmd;
0247
0248 if (msg->msg.data_len > 0) {
0249 if (rsp->msg.data_len < msg->msg.data_len) {
0250 if (trunc) {
0251 rv2 = -EMSGSIZE;
0252 msg->msg.data_len = rsp->msg.data_len;
0253 } else {
0254 rv = -EMSGSIZE;
0255 goto recv_putback_on_err;
0256 }
0257 }
0258
0259 if (copy_to_user(rsp->msg.data,
0260 msg->msg.data,
0261 msg->msg.data_len)) {
0262 rv = -EFAULT;
0263 goto recv_putback_on_err;
0264 }
0265 rsp->msg.data_len = msg->msg.data_len;
0266 } else {
0267 rsp->msg.data_len = 0;
0268 }
0269
0270 rv = copyout(rsp, to);
0271 if (rv)
0272 goto recv_putback_on_err;
0273
0274 mutex_unlock(&priv->recv_mutex);
0275 ipmi_free_recv_msg(msg);
0276 return rv2;
0277
0278 recv_putback_on_err:
0279
0280
0281 spin_lock_irqsave(&priv->recv_msg_lock, flags);
0282 list_add(entry, &priv->recv_msgs);
0283 spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
0284 recv_err:
0285 mutex_unlock(&priv->recv_mutex);
0286 return rv;
0287 }
0288
0289 static int copyout_recv(struct ipmi_recv *rsp, void __user *to)
0290 {
0291 return copy_to_user(to, rsp, sizeof(struct ipmi_recv)) ? -EFAULT : 0;
0292 }
0293
0294 static long ipmi_ioctl(struct file *file,
0295 unsigned int cmd,
0296 unsigned long data)
0297 {
0298 int rv = -EINVAL;
0299 struct ipmi_file_private *priv = file->private_data;
0300 void __user *arg = (void __user *)data;
0301
0302 switch (cmd)
0303 {
0304 case IPMICTL_SEND_COMMAND:
0305 {
0306 struct ipmi_req req;
0307 int retries;
0308 unsigned int retry_time_ms;
0309
0310 if (copy_from_user(&req, arg, sizeof(req))) {
0311 rv = -EFAULT;
0312 break;
0313 }
0314
0315 mutex_lock(&priv->recv_mutex);
0316 retries = priv->default_retries;
0317 retry_time_ms = priv->default_retry_time_ms;
0318 mutex_unlock(&priv->recv_mutex);
0319
0320 rv = handle_send_req(priv->user, &req, retries, retry_time_ms);
0321 break;
0322 }
0323
0324 case IPMICTL_SEND_COMMAND_SETTIME:
0325 {
0326 struct ipmi_req_settime req;
0327
0328 if (copy_from_user(&req, arg, sizeof(req))) {
0329 rv = -EFAULT;
0330 break;
0331 }
0332
0333 rv = handle_send_req(priv->user,
0334 &req.req,
0335 req.retries,
0336 req.retry_time_ms);
0337 break;
0338 }
0339
0340 case IPMICTL_RECEIVE_MSG:
0341 case IPMICTL_RECEIVE_MSG_TRUNC:
0342 {
0343 struct ipmi_recv rsp;
0344
0345 if (copy_from_user(&rsp, arg, sizeof(rsp)))
0346 rv = -EFAULT;
0347 else
0348 rv = handle_recv(priv, cmd == IPMICTL_RECEIVE_MSG_TRUNC,
0349 &rsp, copyout_recv, arg);
0350 break;
0351 }
0352
0353 case IPMICTL_REGISTER_FOR_CMD:
0354 {
0355 struct ipmi_cmdspec val;
0356
0357 if (copy_from_user(&val, arg, sizeof(val))) {
0358 rv = -EFAULT;
0359 break;
0360 }
0361
0362 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
0363 IPMI_CHAN_ALL);
0364 break;
0365 }
0366
0367 case IPMICTL_UNREGISTER_FOR_CMD:
0368 {
0369 struct ipmi_cmdspec val;
0370
0371 if (copy_from_user(&val, arg, sizeof(val))) {
0372 rv = -EFAULT;
0373 break;
0374 }
0375
0376 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
0377 IPMI_CHAN_ALL);
0378 break;
0379 }
0380
0381 case IPMICTL_REGISTER_FOR_CMD_CHANS:
0382 {
0383 struct ipmi_cmdspec_chans val;
0384
0385 if (copy_from_user(&val, arg, sizeof(val))) {
0386 rv = -EFAULT;
0387 break;
0388 }
0389
0390 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
0391 val.chans);
0392 break;
0393 }
0394
0395 case IPMICTL_UNREGISTER_FOR_CMD_CHANS:
0396 {
0397 struct ipmi_cmdspec_chans val;
0398
0399 if (copy_from_user(&val, arg, sizeof(val))) {
0400 rv = -EFAULT;
0401 break;
0402 }
0403
0404 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
0405 val.chans);
0406 break;
0407 }
0408
0409 case IPMICTL_SET_GETS_EVENTS_CMD:
0410 {
0411 int val;
0412
0413 if (copy_from_user(&val, arg, sizeof(val))) {
0414 rv = -EFAULT;
0415 break;
0416 }
0417
0418 rv = ipmi_set_gets_events(priv->user, val);
0419 break;
0420 }
0421
0422
0423 case IPMICTL_SET_MY_ADDRESS_CMD:
0424 {
0425 unsigned int val;
0426
0427 if (copy_from_user(&val, arg, sizeof(val))) {
0428 rv = -EFAULT;
0429 break;
0430 }
0431
0432 rv = ipmi_set_my_address(priv->user, 0, val);
0433 break;
0434 }
0435
0436 case IPMICTL_GET_MY_ADDRESS_CMD:
0437 {
0438 unsigned int val;
0439 unsigned char rval;
0440
0441 rv = ipmi_get_my_address(priv->user, 0, &rval);
0442 if (rv)
0443 break;
0444
0445 val = rval;
0446
0447 if (copy_to_user(arg, &val, sizeof(val))) {
0448 rv = -EFAULT;
0449 break;
0450 }
0451 break;
0452 }
0453
0454 case IPMICTL_SET_MY_LUN_CMD:
0455 {
0456 unsigned int val;
0457
0458 if (copy_from_user(&val, arg, sizeof(val))) {
0459 rv = -EFAULT;
0460 break;
0461 }
0462
0463 rv = ipmi_set_my_LUN(priv->user, 0, val);
0464 break;
0465 }
0466
0467 case IPMICTL_GET_MY_LUN_CMD:
0468 {
0469 unsigned int val;
0470 unsigned char rval;
0471
0472 rv = ipmi_get_my_LUN(priv->user, 0, &rval);
0473 if (rv)
0474 break;
0475
0476 val = rval;
0477
0478 if (copy_to_user(arg, &val, sizeof(val))) {
0479 rv = -EFAULT;
0480 break;
0481 }
0482 break;
0483 }
0484
0485 case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
0486 {
0487 struct ipmi_channel_lun_address_set val;
0488
0489 if (copy_from_user(&val, arg, sizeof(val))) {
0490 rv = -EFAULT;
0491 break;
0492 }
0493
0494 return ipmi_set_my_address(priv->user, val.channel, val.value);
0495 }
0496
0497 case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
0498 {
0499 struct ipmi_channel_lun_address_set val;
0500
0501 if (copy_from_user(&val, arg, sizeof(val))) {
0502 rv = -EFAULT;
0503 break;
0504 }
0505
0506 rv = ipmi_get_my_address(priv->user, val.channel, &val.value);
0507 if (rv)
0508 break;
0509
0510 if (copy_to_user(arg, &val, sizeof(val))) {
0511 rv = -EFAULT;
0512 break;
0513 }
0514 break;
0515 }
0516
0517 case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
0518 {
0519 struct ipmi_channel_lun_address_set val;
0520
0521 if (copy_from_user(&val, arg, sizeof(val))) {
0522 rv = -EFAULT;
0523 break;
0524 }
0525
0526 rv = ipmi_set_my_LUN(priv->user, val.channel, val.value);
0527 break;
0528 }
0529
0530 case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
0531 {
0532 struct ipmi_channel_lun_address_set val;
0533
0534 if (copy_from_user(&val, arg, sizeof(val))) {
0535 rv = -EFAULT;
0536 break;
0537 }
0538
0539 rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value);
0540 if (rv)
0541 break;
0542
0543 if (copy_to_user(arg, &val, sizeof(val))) {
0544 rv = -EFAULT;
0545 break;
0546 }
0547 break;
0548 }
0549
0550 case IPMICTL_SET_TIMING_PARMS_CMD:
0551 {
0552 struct ipmi_timing_parms parms;
0553
0554 if (copy_from_user(&parms, arg, sizeof(parms))) {
0555 rv = -EFAULT;
0556 break;
0557 }
0558
0559 mutex_lock(&priv->recv_mutex);
0560 priv->default_retries = parms.retries;
0561 priv->default_retry_time_ms = parms.retry_time_ms;
0562 mutex_unlock(&priv->recv_mutex);
0563 rv = 0;
0564 break;
0565 }
0566
0567 case IPMICTL_GET_TIMING_PARMS_CMD:
0568 {
0569 struct ipmi_timing_parms parms;
0570
0571 mutex_lock(&priv->recv_mutex);
0572 parms.retries = priv->default_retries;
0573 parms.retry_time_ms = priv->default_retry_time_ms;
0574 mutex_unlock(&priv->recv_mutex);
0575
0576 if (copy_to_user(arg, &parms, sizeof(parms))) {
0577 rv = -EFAULT;
0578 break;
0579 }
0580
0581 rv = 0;
0582 break;
0583 }
0584
0585 case IPMICTL_GET_MAINTENANCE_MODE_CMD:
0586 {
0587 int mode;
0588
0589 mode = ipmi_get_maintenance_mode(priv->user);
0590 if (copy_to_user(arg, &mode, sizeof(mode))) {
0591 rv = -EFAULT;
0592 break;
0593 }
0594 rv = 0;
0595 break;
0596 }
0597
0598 case IPMICTL_SET_MAINTENANCE_MODE_CMD:
0599 {
0600 int mode;
0601
0602 if (copy_from_user(&mode, arg, sizeof(mode))) {
0603 rv = -EFAULT;
0604 break;
0605 }
0606 rv = ipmi_set_maintenance_mode(priv->user, mode);
0607 break;
0608 }
0609
0610 default:
0611 rv = -ENOTTY;
0612 break;
0613 }
0614
0615 return rv;
0616 }
0617
0618 #ifdef CONFIG_COMPAT
0619
0620
0621
0622
0623
0624 #define COMPAT_IPMICTL_SEND_COMMAND \
0625 _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
0626 #define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \
0627 _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
0628 #define COMPAT_IPMICTL_RECEIVE_MSG \
0629 _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
0630 #define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC \
0631 _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
0632
0633 struct compat_ipmi_msg {
0634 u8 netfn;
0635 u8 cmd;
0636 u16 data_len;
0637 compat_uptr_t data;
0638 };
0639
0640 struct compat_ipmi_req {
0641 compat_uptr_t addr;
0642 compat_uint_t addr_len;
0643 compat_long_t msgid;
0644 struct compat_ipmi_msg msg;
0645 };
0646
0647 struct compat_ipmi_recv {
0648 compat_int_t recv_type;
0649 compat_uptr_t addr;
0650 compat_uint_t addr_len;
0651 compat_long_t msgid;
0652 struct compat_ipmi_msg msg;
0653 };
0654
0655 struct compat_ipmi_req_settime {
0656 struct compat_ipmi_req req;
0657 compat_int_t retries;
0658 compat_uint_t retry_time_ms;
0659 };
0660
0661
0662
0663
0664 static void get_compat_ipmi_msg(struct ipmi_msg *p64,
0665 struct compat_ipmi_msg *p32)
0666 {
0667 p64->netfn = p32->netfn;
0668 p64->cmd = p32->cmd;
0669 p64->data_len = p32->data_len;
0670 p64->data = compat_ptr(p32->data);
0671 }
0672
0673 static void get_compat_ipmi_req(struct ipmi_req *p64,
0674 struct compat_ipmi_req *p32)
0675 {
0676 p64->addr = compat_ptr(p32->addr);
0677 p64->addr_len = p32->addr_len;
0678 p64->msgid = p32->msgid;
0679 get_compat_ipmi_msg(&p64->msg, &p32->msg);
0680 }
0681
0682 static void get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
0683 struct compat_ipmi_req_settime *p32)
0684 {
0685 get_compat_ipmi_req(&p64->req, &p32->req);
0686 p64->retries = p32->retries;
0687 p64->retry_time_ms = p32->retry_time_ms;
0688 }
0689
0690 static void get_compat_ipmi_recv(struct ipmi_recv *p64,
0691 struct compat_ipmi_recv *p32)
0692 {
0693 memset(p64, 0, sizeof(struct ipmi_recv));
0694 p64->recv_type = p32->recv_type;
0695 p64->addr = compat_ptr(p32->addr);
0696 p64->addr_len = p32->addr_len;
0697 p64->msgid = p32->msgid;
0698 get_compat_ipmi_msg(&p64->msg, &p32->msg);
0699 }
0700
0701 static int copyout_recv32(struct ipmi_recv *p64, void __user *to)
0702 {
0703 struct compat_ipmi_recv v32;
0704 memset(&v32, 0, sizeof(struct compat_ipmi_recv));
0705 v32.recv_type = p64->recv_type;
0706 v32.addr = ptr_to_compat(p64->addr);
0707 v32.addr_len = p64->addr_len;
0708 v32.msgid = p64->msgid;
0709 v32.msg.netfn = p64->msg.netfn;
0710 v32.msg.cmd = p64->msg.cmd;
0711 v32.msg.data_len = p64->msg.data_len;
0712 v32.msg.data = ptr_to_compat(p64->msg.data);
0713 return copy_to_user(to, &v32, sizeof(v32)) ? -EFAULT : 0;
0714 }
0715
0716
0717
0718
0719 static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
0720 unsigned long arg)
0721 {
0722 struct ipmi_file_private *priv = filep->private_data;
0723
0724 switch(cmd) {
0725 case COMPAT_IPMICTL_SEND_COMMAND:
0726 {
0727 struct ipmi_req rp;
0728 struct compat_ipmi_req r32;
0729 int retries;
0730 unsigned int retry_time_ms;
0731
0732 if (copy_from_user(&r32, compat_ptr(arg), sizeof(r32)))
0733 return -EFAULT;
0734
0735 get_compat_ipmi_req(&rp, &r32);
0736
0737 mutex_lock(&priv->recv_mutex);
0738 retries = priv->default_retries;
0739 retry_time_ms = priv->default_retry_time_ms;
0740 mutex_unlock(&priv->recv_mutex);
0741
0742 return handle_send_req(priv->user, &rp,
0743 retries, retry_time_ms);
0744 }
0745 case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
0746 {
0747 struct ipmi_req_settime sp;
0748 struct compat_ipmi_req_settime sp32;
0749
0750 if (copy_from_user(&sp32, compat_ptr(arg), sizeof(sp32)))
0751 return -EFAULT;
0752
0753 get_compat_ipmi_req_settime(&sp, &sp32);
0754
0755 return handle_send_req(priv->user, &sp.req,
0756 sp.retries, sp.retry_time_ms);
0757 }
0758 case COMPAT_IPMICTL_RECEIVE_MSG:
0759 case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
0760 {
0761 struct ipmi_recv recv64;
0762 struct compat_ipmi_recv recv32;
0763
0764 if (copy_from_user(&recv32, compat_ptr(arg), sizeof(recv32)))
0765 return -EFAULT;
0766
0767 get_compat_ipmi_recv(&recv64, &recv32);
0768
0769 return handle_recv(priv,
0770 cmd == COMPAT_IPMICTL_RECEIVE_MSG_TRUNC,
0771 &recv64, copyout_recv32, compat_ptr(arg));
0772 }
0773 default:
0774 return ipmi_ioctl(filep, cmd, arg);
0775 }
0776 }
0777 #endif
0778
0779 static const struct file_operations ipmi_fops = {
0780 .owner = THIS_MODULE,
0781 .unlocked_ioctl = ipmi_ioctl,
0782 #ifdef CONFIG_COMPAT
0783 .compat_ioctl = compat_ipmi_ioctl,
0784 #endif
0785 .open = ipmi_open,
0786 .release = ipmi_release,
0787 .fasync = ipmi_fasync,
0788 .poll = ipmi_poll,
0789 .llseek = noop_llseek,
0790 };
0791
0792 #define DEVICE_NAME "ipmidev"
0793
0794 static int ipmi_major;
0795 module_param(ipmi_major, int, 0);
0796 MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By"
0797 " default, or if you set it to zero, it will choose the next"
0798 " available device. Setting it to -1 will disable the"
0799 " interface. Other values will set the major device number"
0800 " to that value.");
0801
0802
0803 struct ipmi_reg_list {
0804 dev_t dev;
0805 struct list_head link;
0806 };
0807 static LIST_HEAD(reg_list);
0808 static DEFINE_MUTEX(reg_list_mutex);
0809
0810 static struct class *ipmi_class;
0811
0812 static void ipmi_new_smi(int if_num, struct device *device)
0813 {
0814 dev_t dev = MKDEV(ipmi_major, if_num);
0815 struct ipmi_reg_list *entry;
0816
0817 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
0818 if (!entry) {
0819 pr_err("ipmi_devintf: Unable to create the ipmi class device link\n");
0820 return;
0821 }
0822 entry->dev = dev;
0823
0824 mutex_lock(®_list_mutex);
0825 device_create(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
0826 list_add(&entry->link, ®_list);
0827 mutex_unlock(®_list_mutex);
0828 }
0829
0830 static void ipmi_smi_gone(int if_num)
0831 {
0832 dev_t dev = MKDEV(ipmi_major, if_num);
0833 struct ipmi_reg_list *entry;
0834
0835 mutex_lock(®_list_mutex);
0836 list_for_each_entry(entry, ®_list, link) {
0837 if (entry->dev == dev) {
0838 list_del(&entry->link);
0839 kfree(entry);
0840 break;
0841 }
0842 }
0843 device_destroy(ipmi_class, dev);
0844 mutex_unlock(®_list_mutex);
0845 }
0846
0847 static struct ipmi_smi_watcher smi_watcher =
0848 {
0849 .owner = THIS_MODULE,
0850 .new_smi = ipmi_new_smi,
0851 .smi_gone = ipmi_smi_gone,
0852 };
0853
0854 static int __init init_ipmi_devintf(void)
0855 {
0856 int rv;
0857
0858 if (ipmi_major < 0)
0859 return -EINVAL;
0860
0861 pr_info("ipmi device interface\n");
0862
0863 ipmi_class = class_create(THIS_MODULE, "ipmi");
0864 if (IS_ERR(ipmi_class)) {
0865 pr_err("ipmi: can't register device class\n");
0866 return PTR_ERR(ipmi_class);
0867 }
0868
0869 rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
0870 if (rv < 0) {
0871 class_destroy(ipmi_class);
0872 pr_err("ipmi: can't get major %d\n", ipmi_major);
0873 return rv;
0874 }
0875
0876 if (ipmi_major == 0) {
0877 ipmi_major = rv;
0878 }
0879
0880 rv = ipmi_smi_watcher_register(&smi_watcher);
0881 if (rv) {
0882 unregister_chrdev(ipmi_major, DEVICE_NAME);
0883 class_destroy(ipmi_class);
0884 pr_warn("ipmi: can't register smi watcher\n");
0885 return rv;
0886 }
0887
0888 return 0;
0889 }
0890 module_init(init_ipmi_devintf);
0891
0892 static void __exit cleanup_ipmi(void)
0893 {
0894 struct ipmi_reg_list *entry, *entry2;
0895 mutex_lock(®_list_mutex);
0896 list_for_each_entry_safe(entry, entry2, ®_list, link) {
0897 list_del(&entry->link);
0898 device_destroy(ipmi_class, entry->dev);
0899 kfree(entry);
0900 }
0901 mutex_unlock(®_list_mutex);
0902 class_destroy(ipmi_class);
0903 ipmi_smi_watcher_unregister(&smi_watcher);
0904 unregister_chrdev(ipmi_major, DEVICE_NAME);
0905 }
0906 module_exit(cleanup_ipmi);
0907
0908 MODULE_LICENSE("GPL");
0909 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
0910 MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");