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