linux/drivers/char/ipmi/ipmi_poweroff.c
<<
>>
Prefs
   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
  27static void ipmi_po_smi_gone(int if_num);
  28static 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 */
  36static int poweroff_powercycle;
  37
  38/* Which interface to use, -1 means the first we see. */
  39static int ifnum_to_use = -1;
  40
  41/* Our local state. */
  42static int ready;
  43static struct ipmi_user *ipmi_user;
  44static int ipmi_ifnum;
  45static void (*specific_poweroff_func)(struct ipmi_user *user);
  46
  47/* Holds the old poweroff function so we can restore it on removal. */
  48static void (*old_poweroff_func)(void);
  49
  50static 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
  63module_param_call(ifnum_to_use, set_param_ifnum, param_get_int,
  64                  &ifnum_to_use, 0644);
  65MODULE_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 */
  70module_param(poweroff_powercycle, int, 0644);
  71MODULE_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. */
  77static unsigned int mfg_id;
  78static unsigned int prod_id;
  79static unsigned char capabilities;
  80static 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 */
  88static atomic_t dummy_count = ATOMIC_INIT(0);
  89static void dummy_smi_free(struct ipmi_smi_msg *msg)
  90{
  91        atomic_dec(&dummy_count);
  92}
  93static void dummy_recv_free(struct ipmi_recv_msg *msg)
  94{
  95        atomic_dec(&dummy_count);
  96}
  97static struct ipmi_smi_msg halt_smi_msg = {
  98        .done = dummy_smi_free
  99};
 100static 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
 109static 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
 117static const struct ipmi_user_hndl ipmi_poweroff_handler = {
 118        .ipmi_recv_hndl = receive_handler
 119};
 120
 121
 122static 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. */
 142static 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
 182static void (*atca_oem_poweroff_hook)(struct ipmi_user *user);
 183
 184static 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
 211static 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
 246static 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
 310static 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
 316static 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}
 425static 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
 446static 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
 462static int ipmi_chassis_detect(struct ipmi_user *user)
 463{
 464        /* Chassis support, use it. */
 465        return (capabilities & 0x80);
 466}
 467
 468static 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. */
 516struct poweroff_function {
 517        char *platform_type;
 518        int  (*detect)(struct ipmi_user *user);
 519        void (*poweroff_func)(struct ipmi_user *user);
 520};
 521
 522static 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. */
 545static 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. */
 556static 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
 634static 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
 647static 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
 657static 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
 666static struct ctl_table ipmi_dir_table[] = {
 667        { .procname     = "ipmi",
 668          .mode         = 0555,
 669          .child        = ipmi_table },
 670        { }
 671};
 672
 673static struct ctl_table ipmi_root_table[] = {
 674        { .procname     = "dev",
 675          .mode         = 0555,
 676          .child        = ipmi_dir_table },
 677        { }
 678};
 679
 680static struct ctl_table_header *ipmi_table_header;
 681#endif /* CONFIG_PROC_FS */
 682
 683/*
 684 * Startup and shutdown functions.
 685 */
 686static 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
 719static 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}
 736module_exit(ipmi_poweroff_cleanup);
 737#endif
 738
 739module_init(ipmi_poweroff_init);
 740MODULE_LICENSE("GPL");
 741MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
 742MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot");
 743