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 #include <linux/module.h> 15 #include <linux/moduleparam.h> 16 #include <linux/proc_fs.h> 17 #include <linux/string.h> 18 #include <linux/completion.h> 19 #include <linux/pm.h> 20 #include <linux/kdev_t.h> 21 #include <linux/ipmi.h> 22 #include <linux/ipmi_smi.h> 23 24 #define PFX "IPMI poweroff: " 25 26 static void ipmi_po_smi_gone(int if_num); 27 static void ipmi_po_new_smi(int if_num, struct device *device); 28 29 /* Definitions for controlling power off (if the system supports it). It 30 * conveniently matches the IPMI chassis control values. */ 31 #define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */ 32 #define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ 33 34 /* the IPMI data command */ 35 static int poweroff_powercycle; 36 37 /* Which interface to use, -1 means the first we see. */ 38 static int ifnum_to_use = -1; 39 40 /* Our local state. */ 41 static int ready; 42 static struct ipmi_user *ipmi_user; 43 static int ipmi_ifnum; 44 static void (*specific_poweroff_func)(struct ipmi_user *user); 45 46 /* Holds the old poweroff function so we can restore it on removal. */ 47 static void (*old_poweroff_func)(void); 48 49 static int set_param_ifnum(const char *val, const struct kernel_param *kp) 50 { 51 int rv = param_set_int(val, kp); 52 if (rv) 53 return rv; 54 if ((ifnum_to_use < 0) || (ifnum_to_use == ipmi_ifnum)) 55 return 0; 56 57 ipmi_po_smi_gone(ipmi_ifnum); 58 ipmi_po_new_smi(ifnum_to_use, NULL); 59 return 0; 60 } 61 62 module_param_call(ifnum_to_use, set_param_ifnum, param_get_int, 63 &ifnum_to_use, 0644); 64 MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " 65 "timer. Setting to -1 defaults to the first registered " 66 "interface"); 67 68 /* parameter definition to allow user to flag power cycle */ 69 module_param(poweroff_powercycle, int, 0644); 70 MODULE_PARM_DESC(poweroff_powercycle, 71 " Set to non-zero to enable power cycle instead of power" 72 " down. Power cycle is contingent on hardware support," 73 " otherwise it defaults back to power down."); 74 75 /* Stuff from the get device id command. */ 76 static unsigned int mfg_id; 77 static unsigned int prod_id; 78 static unsigned char capabilities; 79 static unsigned char ipmi_version; 80 81 /* 82 * We use our own messages for this operation, we don't let the system 83 * allocate them, since we may be in a panic situation. The whole 84 * thing is single-threaded, anyway, so multiple messages are not 85 * required. 86 */ 87 static atomic_t dummy_count = ATOMIC_INIT(0); 88 static void dummy_smi_free(struct ipmi_smi_msg *msg) 89 { 90 atomic_dec(&dummy_count); 91 } 92 static void dummy_recv_free(struct ipmi_recv_msg *msg) 93 { 94 atomic_dec(&dummy_count); 95 } 96 static struct ipmi_smi_msg halt_smi_msg = { 97 .done = dummy_smi_free 98 }; 99 static struct ipmi_recv_msg halt_recv_msg = { 100 .done = dummy_recv_free 101 }; 102 103 104 /* 105 * Code to send a message and wait for the response. 106 */ 107 108 static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data) 109 { 110 struct completion *comp = recv_msg->user_msg_data; 111 112 if (comp) 113 complete(comp); 114 } 115 116 static const struct ipmi_user_hndl ipmi_poweroff_handler = { 117 .ipmi_recv_hndl = receive_handler 118 }; 119 120 121 static int ipmi_request_wait_for_response(struct ipmi_user *user, 122 struct ipmi_addr *addr, 123 struct kernel_ipmi_msg *send_msg) 124 { 125 int rv; 126 struct completion comp; 127 128 init_completion(&comp); 129 130 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp, 131 &halt_smi_msg, &halt_recv_msg, 0); 132 if (rv) 133 return rv; 134 135 wait_for_completion(&comp); 136 137 return halt_recv_msg.msg.data[0]; 138 } 139 140 /* Wait for message to complete, spinning. */ 141 static int ipmi_request_in_rc_mode(struct ipmi_user *user, 142 struct ipmi_addr *addr, 143 struct kernel_ipmi_msg *send_msg) 144 { 145 int rv; 146 147 atomic_set(&dummy_count, 2); 148 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL, 149 &halt_smi_msg, &halt_recv_msg, 0); 150 if (rv) { 151 atomic_set(&dummy_count, 0); 152 return rv; 153 } 154 155 /* 156 * Spin until our message is done. 157 */ 158 while (atomic_read(&dummy_count) > 0) { 159 ipmi_poll_interface(user); 160 cpu_relax(); 161 } 162 163 return halt_recv_msg.msg.data[0]; 164 } 165 166 /* 167 * ATCA Support 168 */ 169 170 #define IPMI_NETFN_ATCA 0x2c 171 #define IPMI_ATCA_SET_POWER_CMD 0x11 172 #define IPMI_ATCA_GET_ADDR_INFO_CMD 0x01 173 #define IPMI_PICMG_ID 0 174 175 #define IPMI_NETFN_OEM 0x2e 176 #define IPMI_ATCA_PPS_GRACEFUL_RESTART 0x11 177 #define IPMI_ATCA_PPS_IANA "\x00\x40\x0A" 178 #define IPMI_MOTOROLA_MANUFACTURER_ID 0x0000A1 179 #define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID 0x0051 180 181 static void (*atca_oem_poweroff_hook)(struct ipmi_user *user); 182 183 static void pps_poweroff_atca(struct ipmi_user *user) 184 { 185 struct ipmi_system_interface_addr smi_addr; 186 struct kernel_ipmi_msg send_msg; 187 int rv; 188 /* 189 * Configure IPMI address for local access 190 */ 191 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 192 smi_addr.channel = IPMI_BMC_CHANNEL; 193 smi_addr.lun = 0; 194 195 printk(KERN_INFO PFX "PPS powerdown hook used"); 196 197 send_msg.netfn = IPMI_NETFN_OEM; 198 send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART; 199 send_msg.data = IPMI_ATCA_PPS_IANA; 200 send_msg.data_len = 3; 201 rv = ipmi_request_in_rc_mode(user, 202 (struct ipmi_addr *) &smi_addr, 203 &send_msg); 204 if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) { 205 printk(KERN_ERR PFX "Unable to send ATCA ," 206 " 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 printk(KERN_INFO PFX "ATCA Detect mfg 0x%X prod 0x%X\n", 238 mfg_id, prod_id); 239 if ((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID) 240 && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) { 241 printk(KERN_INFO PFX 242 "Installing Pigeon Point Systems Poweroff Hook\n"); 243 atca_oem_poweroff_hook = pps_poweroff_atca; 244 } 245 return !rv; 246 } 247 248 static void ipmi_poweroff_atca(struct ipmi_user *user) 249 { 250 struct ipmi_system_interface_addr smi_addr; 251 struct kernel_ipmi_msg send_msg; 252 int rv; 253 unsigned char data[4]; 254 255 /* 256 * Configure IPMI address for local access 257 */ 258 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 259 smi_addr.channel = IPMI_BMC_CHANNEL; 260 smi_addr.lun = 0; 261 262 printk(KERN_INFO PFX "Powering down via ATCA power command\n"); 263 264 /* 265 * Power down 266 */ 267 send_msg.netfn = IPMI_NETFN_ATCA; 268 send_msg.cmd = IPMI_ATCA_SET_POWER_CMD; 269 data[0] = IPMI_PICMG_ID; 270 data[1] = 0; /* FRU id */ 271 data[2] = 0; /* Power Level */ 272 data[3] = 0; /* Don't change saved presets */ 273 send_msg.data = data; 274 send_msg.data_len = sizeof(data); 275 rv = ipmi_request_in_rc_mode(user, 276 (struct ipmi_addr *) &smi_addr, 277 &send_msg); 278 /* 279 * At this point, the system may be shutting down, and most 280 * serial drivers (if used) will have interrupts turned off 281 * it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE 282 * return code 283 */ 284 if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) { 285 printk(KERN_ERR PFX "Unable to send ATCA powerdown message," 286 " IPMI error 0x%x\n", rv); 287 goto out; 288 } 289 290 if (atca_oem_poweroff_hook) 291 atca_oem_poweroff_hook(user); 292 out: 293 return; 294 } 295 296 /* 297 * CPI1 Support 298 */ 299 300 #define IPMI_NETFN_OEM_1 0xf8 301 #define OEM_GRP_CMD_SET_RESET_STATE 0x84 302 #define OEM_GRP_CMD_SET_POWER_STATE 0x82 303 #define IPMI_NETFN_OEM_8 0xf8 304 #define OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL 0x80 305 #define OEM_GRP_CMD_GET_SLOT_GA 0xa3 306 #define IPMI_NETFN_SENSOR_EVT 0x10 307 #define IPMI_CMD_GET_EVENT_RECEIVER 0x01 308 309 #define IPMI_CPI1_PRODUCT_ID 0x000157 310 #define IPMI_CPI1_MANUFACTURER_ID 0x0108 311 312 static int ipmi_cpi1_detect(struct ipmi_user *user) 313 { 314 return ((mfg_id == IPMI_CPI1_MANUFACTURER_ID) 315 && (prod_id == IPMI_CPI1_PRODUCT_ID)); 316 } 317 318 static void ipmi_poweroff_cpi1(struct ipmi_user *user) 319 { 320 struct ipmi_system_interface_addr smi_addr; 321 struct ipmi_ipmb_addr ipmb_addr; 322 struct kernel_ipmi_msg send_msg; 323 int rv; 324 unsigned char data[1]; 325 int slot; 326 unsigned char hotswap_ipmb; 327 unsigned char aer_addr; 328 unsigned char aer_lun; 329 330 /* 331 * Configure IPMI address for local access 332 */ 333 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 334 smi_addr.channel = IPMI_BMC_CHANNEL; 335 smi_addr.lun = 0; 336 337 printk(KERN_INFO PFX "Powering down via CPI1 power command\n"); 338 339 /* 340 * Get IPMI ipmb address 341 */ 342 send_msg.netfn = IPMI_NETFN_OEM_8 >> 2; 343 send_msg.cmd = OEM_GRP_CMD_GET_SLOT_GA; 344 send_msg.data = NULL; 345 send_msg.data_len = 0; 346 rv = ipmi_request_in_rc_mode(user, 347 (struct ipmi_addr *) &smi_addr, 348 &send_msg); 349 if (rv) 350 goto out; 351 slot = halt_recv_msg.msg.data[1]; 352 hotswap_ipmb = (slot > 9) ? (0xb0 + 2 * slot) : (0xae + 2 * slot); 353 354 /* 355 * Get active event receiver 356 */ 357 send_msg.netfn = IPMI_NETFN_SENSOR_EVT >> 2; 358 send_msg.cmd = IPMI_CMD_GET_EVENT_RECEIVER; 359 send_msg.data = NULL; 360 send_msg.data_len = 0; 361 rv = ipmi_request_in_rc_mode(user, 362 (struct ipmi_addr *) &smi_addr, 363 &send_msg); 364 if (rv) 365 goto out; 366 aer_addr = halt_recv_msg.msg.data[1]; 367 aer_lun = halt_recv_msg.msg.data[2]; 368 369 /* 370 * Setup IPMB address target instead of local target 371 */ 372 ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE; 373 ipmb_addr.channel = 0; 374 ipmb_addr.slave_addr = aer_addr; 375 ipmb_addr.lun = aer_lun; 376 377 /* 378 * Send request hotswap control to remove blade from dpv 379 */ 380 send_msg.netfn = IPMI_NETFN_OEM_8 >> 2; 381 send_msg.cmd = OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL; 382 send_msg.data = &hotswap_ipmb; 383 send_msg.data_len = 1; 384 ipmi_request_in_rc_mode(user, 385 (struct ipmi_addr *) &ipmb_addr, 386 &send_msg); 387 388 /* 389 * Set reset asserted 390 */ 391 send_msg.netfn = IPMI_NETFN_OEM_1 >> 2; 392 send_msg.cmd = OEM_GRP_CMD_SET_RESET_STATE; 393 send_msg.data = data; 394 data[0] = 1; /* Reset asserted state */ 395 send_msg.data_len = 1; 396 rv = ipmi_request_in_rc_mode(user, 397 (struct ipmi_addr *) &smi_addr, 398 &send_msg); 399 if (rv) 400 goto out; 401 402 /* 403 * Power down 404 */ 405 send_msg.netfn = IPMI_NETFN_OEM_1 >> 2; 406 send_msg.cmd = OEM_GRP_CMD_SET_POWER_STATE; 407 send_msg.data = data; 408 data[0] = 1; /* Power down state */ 409 send_msg.data_len = 1; 410 rv = ipmi_request_in_rc_mode(user, 411 (struct ipmi_addr *) &smi_addr, 412 &send_msg); 413 if (rv) 414 goto out; 415 416 out: 417 return; 418 } 419 420 /* 421 * ipmi_dell_chassis_detect() 422 * Dell systems with IPMI < 1.5 don't set the chassis capability bit 423 * but they can handle a chassis poweroff or powercycle command. 424 */ 425 426 #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} 427 static int ipmi_dell_chassis_detect(struct ipmi_user *user) 428 { 429 const char ipmi_version_major = ipmi_version & 0xF; 430 const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; 431 const char mfr[3] = DELL_IANA_MFR_ID; 432 if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && 433 ipmi_version_major <= 1 && 434 ipmi_version_minor < 5) 435 return 1; 436 return 0; 437 } 438 439 /* 440 * ipmi_hp_chassis_detect() 441 * HP PA-RISC servers rp3410/rp3440, the C8000 workstation and the rx2600 and 442 * zx6000 machines support IPMI vers 1 and don't set the chassis capability bit 443 * but they can handle a chassis poweroff or powercycle command. 444 */ 445 446 #define HP_IANA_MFR_ID 0x0b 447 #define HP_BMC_PROD_ID 0x8201 448 static int ipmi_hp_chassis_detect(struct ipmi_user *user) 449 { 450 if (mfg_id == HP_IANA_MFR_ID 451 && prod_id == HP_BMC_PROD_ID 452 && ipmi_version == 1) 453 return 1; 454 return 0; 455 } 456 457 /* 458 * Standard chassis support 459 */ 460 461 #define IPMI_NETFN_CHASSIS_REQUEST 0 462 #define IPMI_CHASSIS_CONTROL_CMD 0x02 463 464 static int ipmi_chassis_detect(struct ipmi_user *user) 465 { 466 /* Chassis support, use it. */ 467 return (capabilities & 0x80); 468 } 469 470 static void ipmi_poweroff_chassis(struct ipmi_user *user) 471 { 472 struct ipmi_system_interface_addr smi_addr; 473 struct kernel_ipmi_msg send_msg; 474 int rv; 475 unsigned char data[1]; 476 477 /* 478 * Configure IPMI address for local access 479 */ 480 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 481 smi_addr.channel = IPMI_BMC_CHANNEL; 482 smi_addr.lun = 0; 483 484 powercyclefailed: 485 printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", 486 (poweroff_powercycle ? "cycle" : "down")); 487 488 /* 489 * Power down 490 */ 491 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; 492 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; 493 if (poweroff_powercycle) 494 data[0] = IPMI_CHASSIS_POWER_CYCLE; 495 else 496 data[0] = IPMI_CHASSIS_POWER_DOWN; 497 send_msg.data = data; 498 send_msg.data_len = sizeof(data); 499 rv = ipmi_request_in_rc_mode(user, 500 (struct ipmi_addr *) &smi_addr, 501 &send_msg); 502 if (rv) { 503 if (poweroff_powercycle) { 504 /* power cycle failed, default to power down */ 505 printk(KERN_ERR PFX "Unable to send chassis power " \ 506 "cycle message, IPMI error 0x%x\n", rv); 507 poweroff_powercycle = 0; 508 goto powercyclefailed; 509 } 510 511 printk(KERN_ERR PFX "Unable to send chassis power " \ 512 "down message, IPMI error 0x%x\n", rv); 513 } 514 } 515 516 517 /* Table of possible power off functions. */ 518 struct poweroff_function { 519 char *platform_type; 520 int (*detect)(struct ipmi_user *user); 521 void (*poweroff_func)(struct ipmi_user *user); 522 }; 523 524 static struct poweroff_function poweroff_functions[] = { 525 { .platform_type = "ATCA", 526 .detect = ipmi_atca_detect, 527 .poweroff_func = ipmi_poweroff_atca }, 528 { .platform_type = "CPI1", 529 .detect = ipmi_cpi1_detect, 530 .poweroff_func = ipmi_poweroff_cpi1 }, 531 { .platform_type = "chassis", 532 .detect = ipmi_dell_chassis_detect, 533 .poweroff_func = ipmi_poweroff_chassis }, 534 { .platform_type = "chassis", 535 .detect = ipmi_hp_chassis_detect, 536 .poweroff_func = ipmi_poweroff_chassis }, 537 /* Chassis should generally be last, other things should override 538 it. */ 539 { .platform_type = "chassis", 540 .detect = ipmi_chassis_detect, 541 .poweroff_func = ipmi_poweroff_chassis }, 542 }; 543 #define NUM_PO_FUNCS ARRAY_SIZE(poweroff_functions) 544 545 546 /* Called on a powerdown request. */ 547 static 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. */ 558 static 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 639 static 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 652 static 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 662 static 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 671 static struct ctl_table ipmi_dir_table[] = { 672 { .procname = "ipmi", 673 .mode = 0555, 674 .child = ipmi_table }, 675 { } 676 }; 677 678 static struct ctl_table ipmi_root_table[] = { 679 { .procname = "dev", 680 .mode = 0555, 681 .child = ipmi_dir_table }, 682 { } 683 }; 684 685 static struct ctl_table_header *ipmi_table_header; 686 #endif /* CONFIG_PROC_FS */ 687 688 /* 689 * Startup and shutdown functions. 690 */ 691 static 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 725 static 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 } 743 module_exit(ipmi_poweroff_cleanup); 744 #endif 745 746 module_init(ipmi_poweroff_init); 747 MODULE_LICENSE("GPL"); 748 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); 749 MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot"); 750