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(®_list_mutex); 867 class_device_create(ipmi_class, NULL, dev, device, "ipmi%d", if_num); 868 list_add(&entry->link, ®_list); 869 mutex_unlock(®_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(®_list_mutex); 878 list_for_each_entry(entry, ®_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(®_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(®_list_mutex); 938 list_for_each_entry_safe(entry, entry2, ®_list, link) { 939 list_del(&entry->link); 940 class_device_destroy(ipmi_class, entry->dev); 941 kfree(entry); 942 } 943 mutex_unlock(®_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