root/drivers/char/ipmi/ipmi_devintf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. file_receive_handler
  2. ipmi_poll
  3. ipmi_fasync
  4. ipmi_open
  5. ipmi_release
  6. handle_send_req
  7. handle_recv
  8. copyout_recv
  9. ipmi_ioctl
  10. get_compat_ipmi_msg
  11. get_compat_ipmi_req
  12. get_compat_ipmi_req_settime
  13. get_compat_ipmi_recv
  14. copyout_recv32
  15. compat_ipmi_ioctl
  16. ipmi_new_smi
  17. ipmi_smi_gone
  18. init_ipmi_devintf
  19. cleanup_ipmi

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * ipmi_devintf.c
   4  *
   5  * Linux device interface for the IPMI message handler.
   6  *
   7  * Author: MontaVista Software, Inc.
   8  *         Corey Minyard <minyard@mvista.com>
   9  *         source@mvista.com
  10  *
  11  * Copyright 2002 MontaVista Software Inc.
  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 
  27 struct 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 
  39 static 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 
  57 static __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 
  75 static 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 
  82 static const struct ipmi_user_hndl ipmi_hndlrs =
  83 {
  84         .ipmi_recv_hndl = file_receive_handler,
  85 };
  86 
  87 static 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         /* Use the low-level defaults. */
 115         priv->default_retries = -1;
 116         priv->default_retry_time_ms = 0;
 117 
 118 out:
 119         return rv;
 120 }
 121 
 122 static 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 
 140 static 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         /* From here out we cannot return, we must jump to "out" for
 163            error exits to free msgdata. */
 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 
 198 static 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         /* We claim a mutex because we don't want two
 210            users getting something from the queue at a time.
 211            Since we have to release the spinlock before we can
 212            copy the data to the user, it's possible another
 213            user will grab something from the queue, too.  Then
 214            the messages might get out of order if something
 215            fails and the message gets put back onto the
 216            queue.  This mutex prevents that problem. */
 217         mutex_lock(&priv->recv_mutex);
 218 
 219         /* Grab the message off the list. */
 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                         rv2 = -EMSGSIZE;
 251                         if (trunc)
 252                                 msg->msg.data_len = rsp->msg.data_len;
 253                         else
 254                                 goto recv_putback_on_err;
 255                 }
 256 
 257                 if (copy_to_user(rsp->msg.data,
 258                                  msg->msg.data,
 259                                  msg->msg.data_len)) {
 260                         rv = -EFAULT;
 261                         goto recv_putback_on_err;
 262                 }
 263                 rsp->msg.data_len = msg->msg.data_len;
 264         } else {
 265                 rsp->msg.data_len = 0;
 266         }
 267 
 268         rv = copyout(rsp, to);
 269         if (rv)
 270                 goto recv_putback_on_err;
 271 
 272         mutex_unlock(&priv->recv_mutex);
 273         ipmi_free_recv_msg(msg);
 274         return rv2;
 275 
 276 recv_putback_on_err:
 277         /* If we got an error, put the message back onto
 278            the head of the queue. */
 279         spin_lock_irqsave(&priv->recv_msg_lock, flags);
 280         list_add(entry, &priv->recv_msgs);
 281         spin_unlock_irqrestore(&priv->recv_msg_lock, flags);
 282 recv_err:
 283         mutex_unlock(&priv->recv_mutex);
 284         return rv;
 285 }
 286 
 287 static int copyout_recv(struct ipmi_recv *rsp, void __user *to)
 288 {
 289         return copy_to_user(to, rsp, sizeof(struct ipmi_recv)) ? -EFAULT : 0;
 290 }
 291 
 292 static long ipmi_ioctl(struct file   *file,
 293                        unsigned int  cmd,
 294                        unsigned long data)
 295 {
 296         int                      rv = -EINVAL;
 297         struct ipmi_file_private *priv = file->private_data;
 298         void __user *arg = (void __user *)data;
 299 
 300         switch (cmd) 
 301         {
 302         case IPMICTL_SEND_COMMAND:
 303         {
 304                 struct ipmi_req req;
 305                 int retries;
 306                 unsigned int retry_time_ms;
 307 
 308                 if (copy_from_user(&req, arg, sizeof(req))) {
 309                         rv = -EFAULT;
 310                         break;
 311                 }
 312 
 313                 mutex_lock(&priv->recv_mutex);
 314                 retries = priv->default_retries;
 315                 retry_time_ms = priv->default_retry_time_ms;
 316                 mutex_unlock(&priv->recv_mutex);
 317 
 318                 rv = handle_send_req(priv->user, &req, retries, retry_time_ms);
 319                 break;
 320         }
 321 
 322         case IPMICTL_SEND_COMMAND_SETTIME:
 323         {
 324                 struct ipmi_req_settime req;
 325 
 326                 if (copy_from_user(&req, arg, sizeof(req))) {
 327                         rv = -EFAULT;
 328                         break;
 329                 }
 330 
 331                 rv = handle_send_req(priv->user,
 332                                      &req.req,
 333                                      req.retries,
 334                                      req.retry_time_ms);
 335                 break;
 336         }
 337 
 338         case IPMICTL_RECEIVE_MSG:
 339         case IPMICTL_RECEIVE_MSG_TRUNC:
 340         {
 341                 struct ipmi_recv      rsp;
 342 
 343                 if (copy_from_user(&rsp, arg, sizeof(rsp)))
 344                         rv = -EFAULT;
 345                 else
 346                         rv = handle_recv(priv, cmd == IPMICTL_RECEIVE_MSG_TRUNC,
 347                                          &rsp, copyout_recv, arg);
 348                 break;
 349         }
 350 
 351         case IPMICTL_REGISTER_FOR_CMD:
 352         {
 353                 struct ipmi_cmdspec val;
 354 
 355                 if (copy_from_user(&val, arg, sizeof(val))) {
 356                         rv = -EFAULT;
 357                         break;
 358                 }
 359 
 360                 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
 361                                            IPMI_CHAN_ALL);
 362                 break;
 363         }
 364 
 365         case IPMICTL_UNREGISTER_FOR_CMD:
 366         {
 367                 struct ipmi_cmdspec   val;
 368 
 369                 if (copy_from_user(&val, arg, sizeof(val))) {
 370                         rv = -EFAULT;
 371                         break;
 372                 }
 373 
 374                 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
 375                                              IPMI_CHAN_ALL);
 376                 break;
 377         }
 378 
 379         case IPMICTL_REGISTER_FOR_CMD_CHANS:
 380         {
 381                 struct ipmi_cmdspec_chans val;
 382 
 383                 if (copy_from_user(&val, arg, sizeof(val))) {
 384                         rv = -EFAULT;
 385                         break;
 386                 }
 387 
 388                 rv = ipmi_register_for_cmd(priv->user, val.netfn, val.cmd,
 389                                            val.chans);
 390                 break;
 391         }
 392 
 393         case IPMICTL_UNREGISTER_FOR_CMD_CHANS:
 394         {
 395                 struct ipmi_cmdspec_chans val;
 396 
 397                 if (copy_from_user(&val, arg, sizeof(val))) {
 398                         rv = -EFAULT;
 399                         break;
 400                 }
 401 
 402                 rv = ipmi_unregister_for_cmd(priv->user, val.netfn, val.cmd,
 403                                              val.chans);
 404                 break;
 405         }
 406 
 407         case IPMICTL_SET_GETS_EVENTS_CMD:
 408         {
 409                 int val;
 410 
 411                 if (copy_from_user(&val, arg, sizeof(val))) {
 412                         rv = -EFAULT;
 413                         break;
 414                 }
 415 
 416                 rv = ipmi_set_gets_events(priv->user, val);
 417                 break;
 418         }
 419 
 420         /* The next four are legacy, not per-channel. */
 421         case IPMICTL_SET_MY_ADDRESS_CMD:
 422         {
 423                 unsigned int val;
 424 
 425                 if (copy_from_user(&val, arg, sizeof(val))) {
 426                         rv = -EFAULT;
 427                         break;
 428                 }
 429 
 430                 rv = ipmi_set_my_address(priv->user, 0, val);
 431                 break;
 432         }
 433 
 434         case IPMICTL_GET_MY_ADDRESS_CMD:
 435         {
 436                 unsigned int  val;
 437                 unsigned char rval;
 438 
 439                 rv = ipmi_get_my_address(priv->user, 0, &rval);
 440                 if (rv)
 441                         break;
 442 
 443                 val = rval;
 444 
 445                 if (copy_to_user(arg, &val, sizeof(val))) {
 446                         rv = -EFAULT;
 447                         break;
 448                 }
 449                 break;
 450         }
 451 
 452         case IPMICTL_SET_MY_LUN_CMD:
 453         {
 454                 unsigned int val;
 455 
 456                 if (copy_from_user(&val, arg, sizeof(val))) {
 457                         rv = -EFAULT;
 458                         break;
 459                 }
 460 
 461                 rv = ipmi_set_my_LUN(priv->user, 0, val);
 462                 break;
 463         }
 464 
 465         case IPMICTL_GET_MY_LUN_CMD:
 466         {
 467                 unsigned int  val;
 468                 unsigned char rval;
 469 
 470                 rv = ipmi_get_my_LUN(priv->user, 0, &rval);
 471                 if (rv)
 472                         break;
 473 
 474                 val = rval;
 475 
 476                 if (copy_to_user(arg, &val, sizeof(val))) {
 477                         rv = -EFAULT;
 478                         break;
 479                 }
 480                 break;
 481         }
 482 
 483         case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD:
 484         {
 485                 struct ipmi_channel_lun_address_set val;
 486 
 487                 if (copy_from_user(&val, arg, sizeof(val))) {
 488                         rv = -EFAULT;
 489                         break;
 490                 }
 491 
 492                 return ipmi_set_my_address(priv->user, val.channel, val.value);
 493                 break;
 494         }
 495 
 496         case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD:
 497         {
 498                 struct ipmi_channel_lun_address_set val;
 499 
 500                 if (copy_from_user(&val, arg, sizeof(val))) {
 501                         rv = -EFAULT;
 502                         break;
 503                 }
 504 
 505                 rv = ipmi_get_my_address(priv->user, val.channel, &val.value);
 506                 if (rv)
 507                         break;
 508 
 509                 if (copy_to_user(arg, &val, sizeof(val))) {
 510                         rv = -EFAULT;
 511                         break;
 512                 }
 513                 break;
 514         }
 515 
 516         case IPMICTL_SET_MY_CHANNEL_LUN_CMD:
 517         {
 518                 struct ipmi_channel_lun_address_set val;
 519 
 520                 if (copy_from_user(&val, arg, sizeof(val))) {
 521                         rv = -EFAULT;
 522                         break;
 523                 }
 524 
 525                 rv = ipmi_set_my_LUN(priv->user, val.channel, val.value);
 526                 break;
 527         }
 528 
 529         case IPMICTL_GET_MY_CHANNEL_LUN_CMD:
 530         {
 531                 struct ipmi_channel_lun_address_set val;
 532 
 533                 if (copy_from_user(&val, arg, sizeof(val))) {
 534                         rv = -EFAULT;
 535                         break;
 536                 }
 537 
 538                 rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value);
 539                 if (rv)
 540                         break;
 541 
 542                 if (copy_to_user(arg, &val, sizeof(val))) {
 543                         rv = -EFAULT;
 544                         break;
 545                 }
 546                 break;
 547         }
 548 
 549         case IPMICTL_SET_TIMING_PARMS_CMD:
 550         {
 551                 struct ipmi_timing_parms parms;
 552 
 553                 if (copy_from_user(&parms, arg, sizeof(parms))) {
 554                         rv = -EFAULT;
 555                         break;
 556                 }
 557 
 558                 mutex_lock(&priv->recv_mutex);
 559                 priv->default_retries = parms.retries;
 560                 priv->default_retry_time_ms = parms.retry_time_ms;
 561                 mutex_unlock(&priv->recv_mutex);
 562                 rv = 0;
 563                 break;
 564         }
 565 
 566         case IPMICTL_GET_TIMING_PARMS_CMD:
 567         {
 568                 struct ipmi_timing_parms parms;
 569 
 570                 mutex_lock(&priv->recv_mutex);
 571                 parms.retries = priv->default_retries;
 572                 parms.retry_time_ms = priv->default_retry_time_ms;
 573                 mutex_unlock(&priv->recv_mutex);
 574 
 575                 if (copy_to_user(arg, &parms, sizeof(parms))) {
 576                         rv = -EFAULT;
 577                         break;
 578                 }
 579 
 580                 rv = 0;
 581                 break;
 582         }
 583 
 584         case IPMICTL_GET_MAINTENANCE_MODE_CMD:
 585         {
 586                 int mode;
 587 
 588                 mode = ipmi_get_maintenance_mode(priv->user);
 589                 if (copy_to_user(arg, &mode, sizeof(mode))) {
 590                         rv = -EFAULT;
 591                         break;
 592                 }
 593                 rv = 0;
 594                 break;
 595         }
 596 
 597         case IPMICTL_SET_MAINTENANCE_MODE_CMD:
 598         {
 599                 int mode;
 600 
 601                 if (copy_from_user(&mode, arg, sizeof(mode))) {
 602                         rv = -EFAULT;
 603                         break;
 604                 }
 605                 rv = ipmi_set_maintenance_mode(priv->user, mode);
 606                 break;
 607         }
 608 
 609         default:
 610                 rv = -ENOTTY;
 611                 break;
 612         }
 613   
 614         return rv;
 615 }
 616 
 617 #ifdef CONFIG_COMPAT
 618 /*
 619  * The following code contains code for supporting 32-bit compatible
 620  * ioctls on 64-bit kernels.  This allows running 32-bit apps on the
 621  * 64-bit kernel
 622  */
 623 #define COMPAT_IPMICTL_SEND_COMMAND     \
 624         _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
 625 #define COMPAT_IPMICTL_SEND_COMMAND_SETTIME     \
 626         _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
 627 #define COMPAT_IPMICTL_RECEIVE_MSG      \
 628         _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
 629 #define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC        \
 630         _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
 631 
 632 struct compat_ipmi_msg {
 633         u8              netfn;
 634         u8              cmd;
 635         u16             data_len;
 636         compat_uptr_t   data;
 637 };
 638 
 639 struct compat_ipmi_req {
 640         compat_uptr_t           addr;
 641         compat_uint_t           addr_len;
 642         compat_long_t           msgid;
 643         struct compat_ipmi_msg  msg;
 644 };
 645 
 646 struct compat_ipmi_recv {
 647         compat_int_t            recv_type;
 648         compat_uptr_t           addr;
 649         compat_uint_t           addr_len;
 650         compat_long_t           msgid;
 651         struct compat_ipmi_msg  msg;
 652 };
 653 
 654 struct compat_ipmi_req_settime {
 655         struct compat_ipmi_req  req;
 656         compat_int_t            retries;
 657         compat_uint_t           retry_time_ms;
 658 };
 659 
 660 /*
 661  * Define some helper functions for copying IPMI data
 662  */
 663 static void get_compat_ipmi_msg(struct ipmi_msg *p64,
 664                                 struct compat_ipmi_msg *p32)
 665 {
 666         p64->netfn = p32->netfn;
 667         p64->cmd = p32->cmd;
 668         p64->data_len = p32->data_len;
 669         p64->data = compat_ptr(p32->data);
 670 }
 671 
 672 static void get_compat_ipmi_req(struct ipmi_req *p64,
 673                                 struct compat_ipmi_req *p32)
 674 {
 675         p64->addr = compat_ptr(p32->addr);
 676         p64->addr_len = p32->addr_len;
 677         p64->msgid = p32->msgid;
 678         get_compat_ipmi_msg(&p64->msg, &p32->msg);
 679 }
 680 
 681 static void get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
 682                 struct compat_ipmi_req_settime *p32)
 683 {
 684         get_compat_ipmi_req(&p64->req, &p32->req);
 685         p64->retries = p32->retries;
 686         p64->retry_time_ms = p32->retry_time_ms;
 687 }
 688 
 689 static void get_compat_ipmi_recv(struct ipmi_recv *p64,
 690                                  struct compat_ipmi_recv *p32)
 691 {
 692         memset(p64, 0, sizeof(struct ipmi_recv));
 693         p64->recv_type = p32->recv_type;
 694         p64->addr = compat_ptr(p32->addr);
 695         p64->addr_len = p32->addr_len;
 696         p64->msgid = p32->msgid;
 697         get_compat_ipmi_msg(&p64->msg, &p32->msg);
 698 }
 699 
 700 static int copyout_recv32(struct ipmi_recv *p64, void __user *to)
 701 {
 702         struct compat_ipmi_recv v32;
 703         memset(&v32, 0, sizeof(struct compat_ipmi_recv));
 704         v32.recv_type = p64->recv_type;
 705         v32.addr = ptr_to_compat(p64->addr);
 706         v32.addr_len = p64->addr_len;
 707         v32.msgid = p64->msgid;
 708         v32.msg.netfn = p64->msg.netfn;
 709         v32.msg.cmd = p64->msg.cmd;
 710         v32.msg.data_len = p64->msg.data_len;
 711         v32.msg.data = ptr_to_compat(p64->msg.data);
 712         return copy_to_user(to, &v32, sizeof(v32)) ? -EFAULT : 0;
 713 }
 714 
 715 /*
 716  * Handle compatibility ioctls
 717  */
 718 static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
 719                               unsigned long arg)
 720 {
 721         struct ipmi_file_private *priv = filep->private_data;
 722 
 723         switch(cmd) {
 724         case COMPAT_IPMICTL_SEND_COMMAND:
 725         {
 726                 struct ipmi_req rp;
 727                 struct compat_ipmi_req r32;
 728                 int retries;
 729                 unsigned int retry_time_ms;
 730 
 731                 if (copy_from_user(&r32, compat_ptr(arg), sizeof(r32)))
 732                         return -EFAULT;
 733 
 734                 get_compat_ipmi_req(&rp, &r32);
 735 
 736                 mutex_lock(&priv->recv_mutex);
 737                 retries = priv->default_retries;
 738                 retry_time_ms = priv->default_retry_time_ms;
 739                 mutex_unlock(&priv->recv_mutex);
 740 
 741                 return handle_send_req(priv->user, &rp,
 742                                        retries, retry_time_ms);
 743         }
 744         case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
 745         {
 746                 struct ipmi_req_settime sp;
 747                 struct compat_ipmi_req_settime sp32;
 748 
 749                 if (copy_from_user(&sp32, compat_ptr(arg), sizeof(sp32)))
 750                         return -EFAULT;
 751 
 752                 get_compat_ipmi_req_settime(&sp, &sp32);
 753 
 754                 return handle_send_req(priv->user, &sp.req,
 755                                 sp.retries, sp.retry_time_ms);
 756         }
 757         case COMPAT_IPMICTL_RECEIVE_MSG:
 758         case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
 759         {
 760                 struct ipmi_recv   recv64;
 761                 struct compat_ipmi_recv recv32;
 762 
 763                 if (copy_from_user(&recv32, compat_ptr(arg), sizeof(recv32)))
 764                         return -EFAULT;
 765 
 766                 get_compat_ipmi_recv(&recv64, &recv32);
 767 
 768                 return handle_recv(priv,
 769                                  cmd == COMPAT_IPMICTL_RECEIVE_MSG_TRUNC,
 770                                  &recv64, copyout_recv32, compat_ptr(arg));
 771         }
 772         default:
 773                 return ipmi_ioctl(filep, cmd, arg);
 774         }
 775 }
 776 #endif
 777 
 778 static const struct file_operations ipmi_fops = {
 779         .owner          = THIS_MODULE,
 780         .unlocked_ioctl = ipmi_ioctl,
 781 #ifdef CONFIG_COMPAT
 782         .compat_ioctl   = compat_ipmi_ioctl,
 783 #endif
 784         .open           = ipmi_open,
 785         .release        = ipmi_release,
 786         .fasync         = ipmi_fasync,
 787         .poll           = ipmi_poll,
 788         .llseek         = noop_llseek,
 789 };
 790 
 791 #define DEVICE_NAME     "ipmidev"
 792 
 793 static int ipmi_major;
 794 module_param(ipmi_major, int, 0);
 795 MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device.  By"
 796                  " default, or if you set it to zero, it will choose the next"
 797                  " available device.  Setting it to -1 will disable the"
 798                  " interface.  Other values will set the major device number"
 799                  " to that value.");
 800 
 801 /* Keep track of the devices that are registered. */
 802 struct ipmi_reg_list {
 803         dev_t            dev;
 804         struct list_head link;
 805 };
 806 static LIST_HEAD(reg_list);
 807 static DEFINE_MUTEX(reg_list_mutex);
 808 
 809 static struct class *ipmi_class;
 810 
 811 static void ipmi_new_smi(int if_num, struct device *device)
 812 {
 813         dev_t dev = MKDEV(ipmi_major, if_num);
 814         struct ipmi_reg_list *entry;
 815 
 816         entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 817         if (!entry) {
 818                 pr_err("ipmi_devintf: Unable to create the ipmi class device link\n");
 819                 return;
 820         }
 821         entry->dev = dev;
 822 
 823         mutex_lock(&reg_list_mutex);
 824         device_create(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
 825         list_add(&entry->link, &reg_list);
 826         mutex_unlock(&reg_list_mutex);
 827 }
 828 
 829 static void ipmi_smi_gone(int if_num)
 830 {
 831         dev_t dev = MKDEV(ipmi_major, if_num);
 832         struct ipmi_reg_list *entry;
 833 
 834         mutex_lock(&reg_list_mutex);
 835         list_for_each_entry(entry, &reg_list, link) {
 836                 if (entry->dev == dev) {
 837                         list_del(&entry->link);
 838                         kfree(entry);
 839                         break;
 840                 }
 841         }
 842         device_destroy(ipmi_class, dev);
 843         mutex_unlock(&reg_list_mutex);
 844 }
 845 
 846 static struct ipmi_smi_watcher smi_watcher =
 847 {
 848         .owner    = THIS_MODULE,
 849         .new_smi  = ipmi_new_smi,
 850         .smi_gone = ipmi_smi_gone,
 851 };
 852 
 853 static int __init init_ipmi_devintf(void)
 854 {
 855         int rv;
 856 
 857         if (ipmi_major < 0)
 858                 return -EINVAL;
 859 
 860         pr_info("ipmi device interface\n");
 861 
 862         ipmi_class = class_create(THIS_MODULE, "ipmi");
 863         if (IS_ERR(ipmi_class)) {
 864                 pr_err("ipmi: can't register device class\n");
 865                 return PTR_ERR(ipmi_class);
 866         }
 867 
 868         rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
 869         if (rv < 0) {
 870                 class_destroy(ipmi_class);
 871                 pr_err("ipmi: can't get major %d\n", ipmi_major);
 872                 return rv;
 873         }
 874 
 875         if (ipmi_major == 0) {
 876                 ipmi_major = rv;
 877         }
 878 
 879         rv = ipmi_smi_watcher_register(&smi_watcher);
 880         if (rv) {
 881                 unregister_chrdev(ipmi_major, DEVICE_NAME);
 882                 class_destroy(ipmi_class);
 883                 pr_warn("ipmi: can't register smi watcher\n");
 884                 return rv;
 885         }
 886 
 887         return 0;
 888 }
 889 module_init(init_ipmi_devintf);
 890 
 891 static void __exit cleanup_ipmi(void)
 892 {
 893         struct ipmi_reg_list *entry, *entry2;
 894         mutex_lock(&reg_list_mutex);
 895         list_for_each_entry_safe(entry, entry2, &reg_list, link) {
 896                 list_del(&entry->link);
 897                 device_destroy(ipmi_class, entry->dev);
 898                 kfree(entry);
 899         }
 900         mutex_unlock(&reg_list_mutex);
 901         class_destroy(ipmi_class);
 902         ipmi_smi_watcher_unregister(&smi_watcher);
 903         unregister_chrdev(ipmi_major, DEVICE_NAME);
 904 }
 905 module_exit(cleanup_ipmi);
 906 
 907 MODULE_LICENSE("GPL");
 908 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
 909 MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");

/* [<][>][^][v][top][bottom][index][help] */