root/drivers/char/ipmi/ipmi_poweroff.c

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

DEFINITIONS

This source file includes following definitions.
  1. set_param_ifnum
  2. dummy_smi_free
  3. dummy_recv_free
  4. receive_handler
  5. ipmi_request_wait_for_response
  6. ipmi_request_in_rc_mode
  7. pps_poweroff_atca
  8. ipmi_atca_detect
  9. ipmi_poweroff_atca
  10. ipmi_cpi1_detect
  11. ipmi_poweroff_cpi1
  12. ipmi_dell_chassis_detect
  13. ipmi_hp_chassis_detect
  14. ipmi_chassis_detect
  15. ipmi_poweroff_chassis
  16. ipmi_poweroff_function
  17. ipmi_po_new_smi
  18. ipmi_po_smi_gone
  19. ipmi_poweroff_init
  20. ipmi_poweroff_cleanup

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * ipmi_poweroff.c
   4  *
   5  * MontaVista IPMI Poweroff extension to sys_reboot
   6  *
   7  * Author: MontaVista Software, Inc.
   8  *         Steven Dake <sdake@mvista.com>
   9  *         Corey Minyard <cminyard@mvista.com>
  10  *         source@mvista.com
  11  *
  12  * Copyright 2002,2004 MontaVista Software Inc.
  13  */
  14 
  15 #define pr_fmt(fmt) "IPMI poweroff: " fmt
  16 
  17 #include <linux/module.h>
  18 #include <linux/moduleparam.h>
  19 #include <linux/proc_fs.h>
  20 #include <linux/string.h>
  21 #include <linux/completion.h>
  22 #include <linux/pm.h>
  23 #include <linux/kdev_t.h>
  24 #include <linux/ipmi.h>
  25 #include <linux/ipmi_smi.h>
  26 
  27 static void ipmi_po_smi_gone(int if_num);
  28 static void ipmi_po_new_smi(int if_num, struct device *device);
  29 
  30 /* Definitions for controlling power off (if the system supports it).  It
  31  * conveniently matches the IPMI chassis control values. */
  32 #define IPMI_CHASSIS_POWER_DOWN         0       /* power down, the default. */
  33 #define IPMI_CHASSIS_POWER_CYCLE        0x02    /* power cycle */
  34 
  35 /* the IPMI data command */
  36 static int poweroff_powercycle;
  37 
  38 /* Which interface to use, -1 means the first we see. */
  39 static int ifnum_to_use = -1;
  40 
  41 /* Our local state. */
  42 static int ready;
  43 static struct ipmi_user *ipmi_user;
  44 static int ipmi_ifnum;
  45 static void (*specific_poweroff_func)(struct ipmi_user *user);
  46 
  47 /* Holds the old poweroff function so we can restore it on removal. */
  48 static void (*old_poweroff_func)(void);
  49 
  50 static int set_param_ifnum(const char *val, const struct kernel_param *kp)
  51 {
  52         int rv = param_set_int(val, kp);
  53         if (rv)
  54                 return rv;
  55         if ((ifnum_to_use < 0) || (ifnum_to_use == ipmi_ifnum))
  56                 return 0;
  57 
  58         ipmi_po_smi_gone(ipmi_ifnum);
  59         ipmi_po_new_smi(ifnum_to_use, NULL);
  60         return 0;
  61 }
  62 
  63 module_param_call(ifnum_to_use, set_param_ifnum, param_get_int,
  64                   &ifnum_to_use, 0644);
  65 MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
  66                  "timer.  Setting to -1 defaults to the first registered "
  67                  "interface");
  68 
  69 /* parameter definition to allow user to flag power cycle */
  70 module_param(poweroff_powercycle, int, 0644);
  71 MODULE_PARM_DESC(poweroff_powercycle,
  72                  " Set to non-zero to enable power cycle instead of power"
  73                  " down. Power cycle is contingent on hardware support,"
  74                  " otherwise it defaults back to power down.");
  75 
  76 /* Stuff from the get device id command. */
  77 static unsigned int mfg_id;
  78 static unsigned int prod_id;
  79 static unsigned char capabilities;
  80 static unsigned char ipmi_version;
  81 
  82 /*
  83  * We use our own messages for this operation, we don't let the system
  84  * allocate them, since we may be in a panic situation.  The whole
  85  * thing is single-threaded, anyway, so multiple messages are not
  86  * required.
  87  */
  88 static atomic_t dummy_count = ATOMIC_INIT(0);
  89 static void dummy_smi_free(struct ipmi_smi_msg *msg)
  90 {
  91         atomic_dec(&dummy_count);
  92 }
  93 static void dummy_recv_free(struct ipmi_recv_msg *msg)
  94 {
  95         atomic_dec(&dummy_count);
  96 }
  97 static struct ipmi_smi_msg halt_smi_msg = {
  98         .done = dummy_smi_free
  99 };
 100 static struct ipmi_recv_msg halt_recv_msg = {
 101         .done = dummy_recv_free
 102 };
 103 
 104 
 105 /*
 106  * Code to send a message and wait for the response.
 107  */
 108 
 109 static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
 110 {
 111         struct completion *comp = recv_msg->user_msg_data;
 112 
 113         if (comp)
 114                 complete(comp);
 115 }
 116 
 117 static const struct ipmi_user_hndl ipmi_poweroff_handler = {
 118         .ipmi_recv_hndl = receive_handler
 119 };
 120 
 121 
 122 static int ipmi_request_wait_for_response(struct ipmi_user       *user,
 123                                           struct ipmi_addr       *addr,
 124                                           struct kernel_ipmi_msg *send_msg)
 125 {
 126         int               rv;
 127         struct completion comp;
 128 
 129         init_completion(&comp);
 130 
 131         rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp,
 132                                       &halt_smi_msg, &halt_recv_msg, 0);
 133         if (rv)
 134                 return rv;
 135 
 136         wait_for_completion(&comp);
 137 
 138         return halt_recv_msg.msg.data[0];
 139 }
 140 
 141 /* Wait for message to complete, spinning. */
 142 static int ipmi_request_in_rc_mode(struct ipmi_user       *user,
 143                                    struct ipmi_addr       *addr,
 144                                    struct kernel_ipmi_msg *send_msg)
 145 {
 146         int rv;
 147 
 148         atomic_set(&dummy_count, 2);
 149         rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
 150                                       &halt_smi_msg, &halt_recv_msg, 0);
 151         if (rv) {
 152                 atomic_set(&dummy_count, 0);
 153                 return rv;
 154         }
 155 
 156         /*
 157          * Spin until our message is done.
 158          */
 159         while (atomic_read(&dummy_count) > 0) {
 160                 ipmi_poll_interface(user);
 161                 cpu_relax();
 162         }
 163 
 164         return halt_recv_msg.msg.data[0];
 165 }
 166 
 167 /*
 168  * ATCA Support
 169  */
 170 
 171 #define IPMI_NETFN_ATCA                 0x2c
 172 #define IPMI_ATCA_SET_POWER_CMD         0x11
 173 #define IPMI_ATCA_GET_ADDR_INFO_CMD     0x01
 174 #define IPMI_PICMG_ID                   0
 175 
 176 #define IPMI_NETFN_OEM                          0x2e
 177 #define IPMI_ATCA_PPS_GRACEFUL_RESTART          0x11
 178 #define IPMI_ATCA_PPS_IANA                      "\x00\x40\x0A"
 179 #define IPMI_MOTOROLA_MANUFACTURER_ID           0x0000A1
 180 #define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID       0x0051
 181 
 182 static void (*atca_oem_poweroff_hook)(struct ipmi_user *user);
 183 
 184 static void pps_poweroff_atca(struct ipmi_user *user)
 185 {
 186         struct ipmi_system_interface_addr smi_addr;
 187         struct kernel_ipmi_msg            send_msg;
 188         int                               rv;
 189         /*
 190          * Configure IPMI address for local access
 191          */
 192         smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
 193         smi_addr.channel = IPMI_BMC_CHANNEL;
 194         smi_addr.lun = 0;
 195 
 196         pr_info("PPS powerdown hook used\n");
 197 
 198         send_msg.netfn = IPMI_NETFN_OEM;
 199         send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART;
 200         send_msg.data = IPMI_ATCA_PPS_IANA;
 201         send_msg.data_len = 3;
 202         rv = ipmi_request_in_rc_mode(user,
 203                                      (struct ipmi_addr *) &smi_addr,
 204                                      &send_msg);
 205         if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE)
 206                 pr_err("Unable to send ATCA, IPMI error 0x%x\n", rv);
 207 
 208         return;
 209 }
 210 
 211 static int ipmi_atca_detect(struct ipmi_user *user)
 212 {
 213         struct ipmi_system_interface_addr smi_addr;
 214         struct kernel_ipmi_msg            send_msg;
 215         int                               rv;
 216         unsigned char                     data[1];
 217 
 218         /*
 219          * Configure IPMI address for local access
 220          */
 221         smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
 222         smi_addr.channel = IPMI_BMC_CHANNEL;
 223         smi_addr.lun = 0;
 224 
 225         /*
 226          * Use get address info to check and see if we are ATCA
 227          */
 228         send_msg.netfn = IPMI_NETFN_ATCA;
 229         send_msg.cmd = IPMI_ATCA_GET_ADDR_INFO_CMD;
 230         data[0] = IPMI_PICMG_ID;
 231         send_msg.data = data;
 232         send_msg.data_len = sizeof(data);
 233         rv = ipmi_request_wait_for_response(user,
 234                                             (struct ipmi_addr *) &smi_addr,
 235                                             &send_msg);
 236 
 237         pr_info("ATCA Detect mfg 0x%X prod 0x%X\n", mfg_id, prod_id);
 238         if ((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID)
 239             && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) {
 240                 pr_info("Installing Pigeon Point Systems Poweroff Hook\n");
 241                 atca_oem_poweroff_hook = pps_poweroff_atca;
 242         }
 243         return !rv;
 244 }
 245 
 246 static void ipmi_poweroff_atca(struct ipmi_user *user)
 247 {
 248         struct ipmi_system_interface_addr smi_addr;
 249         struct kernel_ipmi_msg            send_msg;
 250         int                               rv;
 251         unsigned char                     data[4];
 252 
 253         /*
 254          * Configure IPMI address for local access
 255          */
 256         smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
 257         smi_addr.channel = IPMI_BMC_CHANNEL;
 258         smi_addr.lun = 0;
 259 
 260         pr_info("Powering down via ATCA power command\n");
 261 
 262         /*
 263          * Power down
 264          */
 265         send_msg.netfn = IPMI_NETFN_ATCA;
 266         send_msg.cmd = IPMI_ATCA_SET_POWER_CMD;
 267         data[0] = IPMI_PICMG_ID;
 268         data[1] = 0; /* FRU id */
 269         data[2] = 0; /* Power Level */
 270         data[3] = 0; /* Don't change saved presets */
 271         send_msg.data = data;
 272         send_msg.data_len = sizeof(data);
 273         rv = ipmi_request_in_rc_mode(user,
 274                                      (struct ipmi_addr *) &smi_addr,
 275                                      &send_msg);
 276         /*
 277          * At this point, the system may be shutting down, and most
 278          * serial drivers (if used) will have interrupts turned off
 279          * it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE
 280          * return code
 281          */
 282         if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
 283                 pr_err("Unable to send ATCA powerdown message, IPMI error 0x%x\n",
 284                        rv);
 285                 goto out;
 286         }
 287 
 288         if (atca_oem_poweroff_hook)
 289                 atca_oem_poweroff_hook(user);
 290  out:
 291         return;
 292 }
 293 
 294 /*
 295  * CPI1 Support
 296  */
 297 
 298 #define IPMI_NETFN_OEM_1                                0xf8
 299 #define OEM_GRP_CMD_SET_RESET_STATE             0x84
 300 #define OEM_GRP_CMD_SET_POWER_STATE             0x82
 301 #define IPMI_NETFN_OEM_8                                0xf8
 302 #define OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL        0x80
 303 #define OEM_GRP_CMD_GET_SLOT_GA                 0xa3
 304 #define IPMI_NETFN_SENSOR_EVT                   0x10
 305 #define IPMI_CMD_GET_EVENT_RECEIVER             0x01
 306 
 307 #define IPMI_CPI1_PRODUCT_ID            0x000157
 308 #define IPMI_CPI1_MANUFACTURER_ID       0x0108
 309 
 310 static int ipmi_cpi1_detect(struct ipmi_user *user)
 311 {
 312         return ((mfg_id == IPMI_CPI1_MANUFACTURER_ID)
 313                 && (prod_id == IPMI_CPI1_PRODUCT_ID));
 314 }
 315 
 316 static void ipmi_poweroff_cpi1(struct ipmi_user *user)
 317 {
 318         struct ipmi_system_interface_addr smi_addr;
 319         struct ipmi_ipmb_addr             ipmb_addr;
 320         struct kernel_ipmi_msg            send_msg;
 321         int                               rv;
 322         unsigned char                     data[1];
 323         int                               slot;
 324         unsigned char                     hotswap_ipmb;
 325         unsigned char                     aer_addr;
 326         unsigned char                     aer_lun;
 327 
 328         /*
 329          * Configure IPMI address for local access
 330          */
 331         smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
 332         smi_addr.channel = IPMI_BMC_CHANNEL;
 333         smi_addr.lun = 0;
 334 
 335         pr_info("Powering down via CPI1 power command\n");
 336 
 337         /*
 338          * Get IPMI ipmb address
 339          */
 340         send_msg.netfn = IPMI_NETFN_OEM_8 >> 2;
 341         send_msg.cmd = OEM_GRP_CMD_GET_SLOT_GA;
 342         send_msg.data = NULL;
 343         send_msg.data_len = 0;
 344         rv = ipmi_request_in_rc_mode(user,
 345                                      (struct ipmi_addr *) &smi_addr,
 346                                      &send_msg);
 347         if (rv)
 348                 goto out;
 349         slot = halt_recv_msg.msg.data[1];
 350         hotswap_ipmb = (slot > 9) ? (0xb0 + 2 * slot) : (0xae + 2 * slot);
 351 
 352         /*
 353          * Get active event receiver
 354          */
 355         send_msg.netfn = IPMI_NETFN_SENSOR_EVT >> 2;
 356         send_msg.cmd = IPMI_CMD_GET_EVENT_RECEIVER;
 357         send_msg.data = NULL;
 358         send_msg.data_len = 0;
 359         rv = ipmi_request_in_rc_mode(user,
 360                                      (struct ipmi_addr *) &smi_addr,
 361                                      &send_msg);
 362         if (rv)
 363                 goto out;
 364         aer_addr = halt_recv_msg.msg.data[1];
 365         aer_lun = halt_recv_msg.msg.data[2];
 366 
 367         /*
 368          * Setup IPMB address target instead of local target
 369          */
 370         ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
 371         ipmb_addr.channel = 0;
 372         ipmb_addr.slave_addr = aer_addr;
 373         ipmb_addr.lun = aer_lun;
 374 
 375         /*
 376          * Send request hotswap control to remove blade from dpv
 377          */
 378         send_msg.netfn = IPMI_NETFN_OEM_8 >> 2;
 379         send_msg.cmd = OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL;
 380         send_msg.data = &hotswap_ipmb;
 381         send_msg.data_len = 1;
 382         ipmi_request_in_rc_mode(user,
 383                                 (struct ipmi_addr *) &ipmb_addr,
 384                                 &send_msg);
 385 
 386         /*
 387          * Set reset asserted
 388          */
 389         send_msg.netfn = IPMI_NETFN_OEM_1 >> 2;
 390         send_msg.cmd = OEM_GRP_CMD_SET_RESET_STATE;
 391         send_msg.data = data;
 392         data[0] = 1; /* Reset asserted state */
 393         send_msg.data_len = 1;
 394         rv = ipmi_request_in_rc_mode(user,
 395                                      (struct ipmi_addr *) &smi_addr,
 396                                      &send_msg);
 397         if (rv)
 398                 goto out;
 399 
 400         /*
 401          * Power down
 402          */
 403         send_msg.netfn = IPMI_NETFN_OEM_1 >> 2;
 404         send_msg.cmd = OEM_GRP_CMD_SET_POWER_STATE;
 405         send_msg.data = data;
 406         data[0] = 1; /* Power down state */
 407         send_msg.data_len = 1;
 408         rv = ipmi_request_in_rc_mode(user,
 409                                      (struct ipmi_addr *) &smi_addr,
 410                                      &send_msg);
 411         if (rv)
 412                 goto out;
 413 
 414  out:
 415         return;
 416 }
 417 
 418 /*
 419  * ipmi_dell_chassis_detect()
 420  * Dell systems with IPMI < 1.5 don't set the chassis capability bit
 421  * but they can handle a chassis poweroff or powercycle command.
 422  */
 423 
 424 #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
 425 static int ipmi_dell_chassis_detect(struct ipmi_user *user)
 426 {
 427         const char ipmi_version_major = ipmi_version & 0xF;
 428         const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;
 429         const char mfr[3] = DELL_IANA_MFR_ID;
 430         if (!memcmp(mfr, &mfg_id, sizeof(mfr)) &&
 431             ipmi_version_major <= 1 &&
 432             ipmi_version_minor < 5)
 433                 return 1;
 434         return 0;
 435 }
 436 
 437 /*
 438  * ipmi_hp_chassis_detect()
 439  * HP PA-RISC servers rp3410/rp3440, the C8000 workstation and the rx2600 and
 440  * zx6000 machines support IPMI vers 1 and don't set the chassis capability bit
 441  * but they can handle a chassis poweroff or powercycle command.
 442  */
 443 
 444 #define HP_IANA_MFR_ID 0x0b
 445 #define HP_BMC_PROD_ID 0x8201
 446 static int ipmi_hp_chassis_detect(struct ipmi_user *user)
 447 {
 448         if (mfg_id == HP_IANA_MFR_ID
 449                 && prod_id == HP_BMC_PROD_ID
 450                 && ipmi_version == 1)
 451                 return 1;
 452         return 0;
 453 }
 454 
 455 /*
 456  * Standard chassis support
 457  */
 458 
 459 #define IPMI_NETFN_CHASSIS_REQUEST      0
 460 #define IPMI_CHASSIS_CONTROL_CMD        0x02
 461 
 462 static int ipmi_chassis_detect(struct ipmi_user *user)
 463 {
 464         /* Chassis support, use it. */
 465         return (capabilities & 0x80);
 466 }
 467 
 468 static void ipmi_poweroff_chassis(struct ipmi_user *user)
 469 {
 470         struct ipmi_system_interface_addr smi_addr;
 471         struct kernel_ipmi_msg            send_msg;
 472         int                               rv;
 473         unsigned char                     data[1];
 474 
 475         /*
 476          * Configure IPMI address for local access
 477          */
 478         smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
 479         smi_addr.channel = IPMI_BMC_CHANNEL;
 480         smi_addr.lun = 0;
 481 
 482  powercyclefailed:
 483         pr_info("Powering %s via IPMI chassis control command\n",
 484                 (poweroff_powercycle ? "cycle" : "down"));
 485 
 486         /*
 487          * Power down
 488          */
 489         send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
 490         send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
 491         if (poweroff_powercycle)
 492                 data[0] = IPMI_CHASSIS_POWER_CYCLE;
 493         else
 494                 data[0] = IPMI_CHASSIS_POWER_DOWN;
 495         send_msg.data = data;
 496         send_msg.data_len = sizeof(data);
 497         rv = ipmi_request_in_rc_mode(user,
 498                                      (struct ipmi_addr *) &smi_addr,
 499                                      &send_msg);
 500         if (rv) {
 501                 if (poweroff_powercycle) {
 502                         /* power cycle failed, default to power down */
 503                         pr_err("Unable to send chassis power cycle message, IPMI error 0x%x\n",
 504                                rv);
 505                         poweroff_powercycle = 0;
 506                         goto powercyclefailed;
 507                 }
 508 
 509                 pr_err("Unable to send chassis power down message, IPMI error 0x%x\n",
 510                        rv);
 511         }
 512 }
 513 
 514 
 515 /* Table of possible power off functions. */
 516 struct poweroff_function {
 517         char *platform_type;
 518         int  (*detect)(struct ipmi_user *user);
 519         void (*poweroff_func)(struct ipmi_user *user);
 520 };
 521 
 522 static struct poweroff_function poweroff_functions[] = {
 523         { .platform_type        = "ATCA",
 524           .detect               = ipmi_atca_detect,
 525           .poweroff_func        = ipmi_poweroff_atca },
 526         { .platform_type        = "CPI1",
 527           .detect               = ipmi_cpi1_detect,
 528           .poweroff_func        = ipmi_poweroff_cpi1 },
 529         { .platform_type        = "chassis",
 530           .detect               = ipmi_dell_chassis_detect,
 531           .poweroff_func        = ipmi_poweroff_chassis },
 532         { .platform_type        = "chassis",
 533           .detect               = ipmi_hp_chassis_detect,
 534           .poweroff_func        = ipmi_poweroff_chassis },
 535         /* Chassis should generally be last, other things should override
 536            it. */
 537         { .platform_type        = "chassis",
 538           .detect               = ipmi_chassis_detect,
 539           .poweroff_func        = ipmi_poweroff_chassis },
 540 };
 541 #define NUM_PO_FUNCS ARRAY_SIZE(poweroff_functions)
 542 
 543 
 544 /* Called on a powerdown request. */
 545 static void ipmi_poweroff_function(void)
 546 {
 547         if (!ready)
 548                 return;
 549 
 550         /* Use run-to-completion mode, since interrupts may be off. */
 551         specific_poweroff_func(ipmi_user);
 552 }
 553 
 554 /* Wait for an IPMI interface to be installed, the first one installed
 555    will be grabbed by this code and used to perform the powerdown. */
 556 static void ipmi_po_new_smi(int if_num, struct device *device)
 557 {
 558         struct ipmi_system_interface_addr smi_addr;
 559         struct kernel_ipmi_msg            send_msg;
 560         int                               rv;
 561         int                               i;
 562 
 563         if (ready)
 564                 return;
 565 
 566         if ((ifnum_to_use >= 0) && (ifnum_to_use != if_num))
 567                 return;
 568 
 569         rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,
 570                               &ipmi_user);
 571         if (rv) {
 572                 pr_err("could not create IPMI user, error %d\n", rv);
 573                 return;
 574         }
 575 
 576         ipmi_ifnum = if_num;
 577 
 578         /*
 579          * Do a get device ide and store some results, since this is
 580          * used by several functions.
 581          */
 582         smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
 583         smi_addr.channel = IPMI_BMC_CHANNEL;
 584         smi_addr.lun = 0;
 585 
 586         send_msg.netfn = IPMI_NETFN_APP_REQUEST;
 587         send_msg.cmd = IPMI_GET_DEVICE_ID_CMD;
 588         send_msg.data = NULL;
 589         send_msg.data_len = 0;
 590         rv = ipmi_request_wait_for_response(ipmi_user,
 591                                             (struct ipmi_addr *) &smi_addr,
 592                                             &send_msg);
 593         if (rv) {
 594                 pr_err("Unable to send IPMI get device id info, IPMI error 0x%x\n",
 595                        rv);
 596                 goto out_err;
 597         }
 598 
 599         if (halt_recv_msg.msg.data_len < 12) {
 600                 pr_err("(chassis) IPMI get device id info too short, was %d bytes, needed %d bytes\n",
 601                        halt_recv_msg.msg.data_len, 12);
 602                 goto out_err;
 603         }
 604 
 605         mfg_id = (halt_recv_msg.msg.data[7]
 606                   | (halt_recv_msg.msg.data[8] << 8)
 607                   | (halt_recv_msg.msg.data[9] << 16));
 608         prod_id = (halt_recv_msg.msg.data[10]
 609                    | (halt_recv_msg.msg.data[11] << 8));
 610         capabilities = halt_recv_msg.msg.data[6];
 611         ipmi_version = halt_recv_msg.msg.data[5];
 612 
 613 
 614         /* Scan for a poweroff method */
 615         for (i = 0; i < NUM_PO_FUNCS; i++) {
 616                 if (poweroff_functions[i].detect(ipmi_user))
 617                         goto found;
 618         }
 619 
 620  out_err:
 621         pr_err("Unable to find a poweroff function that will work, giving up\n");
 622         ipmi_destroy_user(ipmi_user);
 623         return;
 624 
 625  found:
 626         pr_info("Found a %s style poweroff function\n",
 627                 poweroff_functions[i].platform_type);
 628         specific_poweroff_func = poweroff_functions[i].poweroff_func;
 629         old_poweroff_func = pm_power_off;
 630         pm_power_off = ipmi_poweroff_function;
 631         ready = 1;
 632 }
 633 
 634 static void ipmi_po_smi_gone(int if_num)
 635 {
 636         if (!ready)
 637                 return;
 638 
 639         if (ipmi_ifnum != if_num)
 640                 return;
 641 
 642         ready = 0;
 643         ipmi_destroy_user(ipmi_user);
 644         pm_power_off = old_poweroff_func;
 645 }
 646 
 647 static struct ipmi_smi_watcher smi_watcher = {
 648         .owner    = THIS_MODULE,
 649         .new_smi  = ipmi_po_new_smi,
 650         .smi_gone = ipmi_po_smi_gone
 651 };
 652 
 653 
 654 #ifdef CONFIG_PROC_FS
 655 #include <linux/sysctl.h>
 656 
 657 static struct ctl_table ipmi_table[] = {
 658         { .procname     = "poweroff_powercycle",
 659           .data         = &poweroff_powercycle,
 660           .maxlen       = sizeof(poweroff_powercycle),
 661           .mode         = 0644,
 662           .proc_handler = proc_dointvec },
 663         { }
 664 };
 665 
 666 static struct ctl_table ipmi_dir_table[] = {
 667         { .procname     = "ipmi",
 668           .mode         = 0555,
 669           .child        = ipmi_table },
 670         { }
 671 };
 672 
 673 static struct ctl_table ipmi_root_table[] = {
 674         { .procname     = "dev",
 675           .mode         = 0555,
 676           .child        = ipmi_dir_table },
 677         { }
 678 };
 679 
 680 static struct ctl_table_header *ipmi_table_header;
 681 #endif /* CONFIG_PROC_FS */
 682 
 683 /*
 684  * Startup and shutdown functions.
 685  */
 686 static int __init ipmi_poweroff_init(void)
 687 {
 688         int rv;
 689 
 690         pr_info("Copyright (C) 2004 MontaVista Software - IPMI Powerdown via sys_reboot\n");
 691 
 692         if (poweroff_powercycle)
 693                 pr_info("Power cycle is enabled\n");
 694 
 695 #ifdef CONFIG_PROC_FS
 696         ipmi_table_header = register_sysctl_table(ipmi_root_table);
 697         if (!ipmi_table_header) {
 698                 pr_err("Unable to register powercycle sysctl\n");
 699                 rv = -ENOMEM;
 700                 goto out_err;
 701         }
 702 #endif
 703 
 704         rv = ipmi_smi_watcher_register(&smi_watcher);
 705 
 706 #ifdef CONFIG_PROC_FS
 707         if (rv) {
 708                 unregister_sysctl_table(ipmi_table_header);
 709                 pr_err("Unable to register SMI watcher: %d\n", rv);
 710                 goto out_err;
 711         }
 712 
 713  out_err:
 714 #endif
 715         return rv;
 716 }
 717 
 718 #ifdef MODULE
 719 static void __exit ipmi_poweroff_cleanup(void)
 720 {
 721         int rv;
 722 
 723 #ifdef CONFIG_PROC_FS
 724         unregister_sysctl_table(ipmi_table_header);
 725 #endif
 726 
 727         ipmi_smi_watcher_unregister(&smi_watcher);
 728 
 729         if (ready) {
 730                 rv = ipmi_destroy_user(ipmi_user);
 731                 if (rv)
 732                         pr_err("could not cleanup the IPMI user: 0x%x\n", rv);
 733                 pm_power_off = old_poweroff_func;
 734         }
 735 }
 736 module_exit(ipmi_poweroff_cleanup);
 737 #endif
 738 
 739 module_init(ipmi_poweroff_init);
 740 MODULE_LICENSE("GPL");
 741 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
 742 MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot");

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