ipmi_poweroff.c revision 168524d673f99550d75af49eb3f5d2850420eb66
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/config.h> 35#include <linux/module.h> 36#include <linux/moduleparam.h> 37#include <linux/proc_fs.h> 38#include <linux/string.h> 39#include <linux/completion.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 46/* Where to we insert our poweroff function? */ 47extern void (*pm_power_off)(void); 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_control = IPMI_CHASSIS_POWER_DOWN; 56 57/* parameter definition to allow user to flag power cycle */ 58module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); 59MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); 60 61/* Stuff from the get device id command. */ 62static unsigned int mfg_id; 63static unsigned int prod_id; 64static unsigned char capabilities; 65static unsigned char ipmi_version; 66 67/* We use our own messages for this operation, we don't let the system 68 allocate them, since we may be in a panic situation. The whole 69 thing is single-threaded, anyway, so multiple messages are not 70 required. */ 71static void dummy_smi_free(struct ipmi_smi_msg *msg) 72{ 73} 74static void dummy_recv_free(struct ipmi_recv_msg *msg) 75{ 76} 77static struct ipmi_smi_msg halt_smi_msg = 78{ 79 .done = dummy_smi_free 80}; 81static struct ipmi_recv_msg halt_recv_msg = 82{ 83 .done = dummy_recv_free 84}; 85 86 87/* 88 * Code to send a message and wait for the reponse. 89 */ 90 91static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data) 92{ 93 struct completion *comp = recv_msg->user_msg_data; 94 95 if (comp) 96 complete(comp); 97} 98 99static struct ipmi_user_hndl ipmi_poweroff_handler = 100{ 101 .ipmi_recv_hndl = receive_handler 102}; 103 104 105static int ipmi_request_wait_for_response(ipmi_user_t user, 106 struct ipmi_addr *addr, 107 struct kernel_ipmi_msg *send_msg) 108{ 109 int rv; 110 struct completion comp; 111 112 init_completion(&comp); 113 114 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp, 115 &halt_smi_msg, &halt_recv_msg, 0); 116 if (rv) 117 return rv; 118 119 wait_for_completion(&comp); 120 121 return halt_recv_msg.msg.data[0]; 122} 123 124/* We are in run-to-completion mode, no completion is desired. */ 125static int ipmi_request_in_rc_mode(ipmi_user_t user, 126 struct ipmi_addr *addr, 127 struct kernel_ipmi_msg *send_msg) 128{ 129 int rv; 130 131 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL, 132 &halt_smi_msg, &halt_recv_msg, 0); 133 if (rv) 134 return rv; 135 136 return halt_recv_msg.msg.data[0]; 137} 138 139/* 140 * ATCA Support 141 */ 142 143#define IPMI_NETFN_ATCA 0x2c 144#define IPMI_ATCA_SET_POWER_CMD 0x11 145#define IPMI_ATCA_GET_ADDR_INFO_CMD 0x01 146#define IPMI_PICMG_ID 0 147 148static int ipmi_atca_detect (ipmi_user_t user) 149{ 150 struct ipmi_system_interface_addr smi_addr; 151 struct kernel_ipmi_msg send_msg; 152 int rv; 153 unsigned char data[1]; 154 155 /* 156 * Configure IPMI address for local access 157 */ 158 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 159 smi_addr.channel = IPMI_BMC_CHANNEL; 160 smi_addr.lun = 0; 161 162 /* 163 * Use get address info to check and see if we are ATCA 164 */ 165 send_msg.netfn = IPMI_NETFN_ATCA; 166 send_msg.cmd = IPMI_ATCA_GET_ADDR_INFO_CMD; 167 data[0] = IPMI_PICMG_ID; 168 send_msg.data = data; 169 send_msg.data_len = sizeof(data); 170 rv = ipmi_request_wait_for_response(user, 171 (struct ipmi_addr *) &smi_addr, 172 &send_msg); 173 return !rv; 174} 175 176static void ipmi_poweroff_atca (ipmi_user_t user) 177{ 178 struct ipmi_system_interface_addr smi_addr; 179 struct kernel_ipmi_msg send_msg; 180 int rv; 181 unsigned char data[4]; 182 183 /* 184 * Configure IPMI address for local access 185 */ 186 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 187 smi_addr.channel = IPMI_BMC_CHANNEL; 188 smi_addr.lun = 0; 189 190 printk(KERN_INFO PFX "Powering down via ATCA power command\n"); 191 192 /* 193 * Power down 194 */ 195 send_msg.netfn = IPMI_NETFN_ATCA; 196 send_msg.cmd = IPMI_ATCA_SET_POWER_CMD; 197 data[0] = IPMI_PICMG_ID; 198 data[1] = 0; /* FRU id */ 199 data[2] = 0; /* Power Level */ 200 data[3] = 0; /* Don't change saved presets */ 201 send_msg.data = data; 202 send_msg.data_len = sizeof (data); 203 rv = ipmi_request_in_rc_mode(user, 204 (struct ipmi_addr *) &smi_addr, 205 &send_msg); 206 if (rv) { 207 printk(KERN_ERR PFX "Unable to send ATCA powerdown message," 208 " IPMI error 0x%x\n", rv); 209 goto out; 210 } 211 212 out: 213 return; 214} 215 216/* 217 * CPI1 Support 218 */ 219 220#define IPMI_NETFN_OEM_1 0xf8 221#define OEM_GRP_CMD_SET_RESET_STATE 0x84 222#define OEM_GRP_CMD_SET_POWER_STATE 0x82 223#define IPMI_NETFN_OEM_8 0xf8 224#define OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL 0x80 225#define OEM_GRP_CMD_GET_SLOT_GA 0xa3 226#define IPMI_NETFN_SENSOR_EVT 0x10 227#define IPMI_CMD_GET_EVENT_RECEIVER 0x01 228 229#define IPMI_CPI1_PRODUCT_ID 0x000157 230#define IPMI_CPI1_MANUFACTURER_ID 0x0108 231 232static int ipmi_cpi1_detect (ipmi_user_t user) 233{ 234 return ((mfg_id == IPMI_CPI1_MANUFACTURER_ID) 235 && (prod_id == IPMI_CPI1_PRODUCT_ID)); 236} 237 238static void ipmi_poweroff_cpi1 (ipmi_user_t user) 239{ 240 struct ipmi_system_interface_addr smi_addr; 241 struct ipmi_ipmb_addr ipmb_addr; 242 struct kernel_ipmi_msg send_msg; 243 int rv; 244 unsigned char data[1]; 245 int slot; 246 unsigned char hotswap_ipmb; 247 unsigned char aer_addr; 248 unsigned char aer_lun; 249 250 /* 251 * Configure IPMI address for local access 252 */ 253 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 254 smi_addr.channel = IPMI_BMC_CHANNEL; 255 smi_addr.lun = 0; 256 257 printk(KERN_INFO PFX "Powering down via CPI1 power command\n"); 258 259 /* 260 * Get IPMI ipmb address 261 */ 262 send_msg.netfn = IPMI_NETFN_OEM_8 >> 2; 263 send_msg.cmd = OEM_GRP_CMD_GET_SLOT_GA; 264 send_msg.data = NULL; 265 send_msg.data_len = 0; 266 rv = ipmi_request_in_rc_mode(user, 267 (struct ipmi_addr *) &smi_addr, 268 &send_msg); 269 if (rv) 270 goto out; 271 slot = halt_recv_msg.msg.data[1]; 272 hotswap_ipmb = (slot > 9) ? (0xb0 + 2 * slot) : (0xae + 2 * slot); 273 274 /* 275 * Get active event receiver 276 */ 277 send_msg.netfn = IPMI_NETFN_SENSOR_EVT >> 2; 278 send_msg.cmd = IPMI_CMD_GET_EVENT_RECEIVER; 279 send_msg.data = NULL; 280 send_msg.data_len = 0; 281 rv = ipmi_request_in_rc_mode(user, 282 (struct ipmi_addr *) &smi_addr, 283 &send_msg); 284 if (rv) 285 goto out; 286 aer_addr = halt_recv_msg.msg.data[1]; 287 aer_lun = halt_recv_msg.msg.data[2]; 288 289 /* 290 * Setup IPMB address target instead of local target 291 */ 292 ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE; 293 ipmb_addr.channel = 0; 294 ipmb_addr.slave_addr = aer_addr; 295 ipmb_addr.lun = aer_lun; 296 297 /* 298 * Send request hotswap control to remove blade from dpv 299 */ 300 send_msg.netfn = IPMI_NETFN_OEM_8 >> 2; 301 send_msg.cmd = OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL; 302 send_msg.data = &hotswap_ipmb; 303 send_msg.data_len = 1; 304 ipmi_request_in_rc_mode(user, 305 (struct ipmi_addr *) &ipmb_addr, 306 &send_msg); 307 308 /* 309 * Set reset asserted 310 */ 311 send_msg.netfn = IPMI_NETFN_OEM_1 >> 2; 312 send_msg.cmd = OEM_GRP_CMD_SET_RESET_STATE; 313 send_msg.data = data; 314 data[0] = 1; /* Reset asserted state */ 315 send_msg.data_len = 1; 316 rv = ipmi_request_in_rc_mode(user, 317 (struct ipmi_addr *) &smi_addr, 318 &send_msg); 319 if (rv) 320 goto out; 321 322 /* 323 * Power down 324 */ 325 send_msg.netfn = IPMI_NETFN_OEM_1 >> 2; 326 send_msg.cmd = OEM_GRP_CMD_SET_POWER_STATE; 327 send_msg.data = data; 328 data[0] = 1; /* Power down state */ 329 send_msg.data_len = 1; 330 rv = ipmi_request_in_rc_mode(user, 331 (struct ipmi_addr *) &smi_addr, 332 &send_msg); 333 if (rv) 334 goto out; 335 336 out: 337 return; 338} 339 340/* 341 * ipmi_dell_chassis_detect() 342 * Dell systems with IPMI < 1.5 don't set the chassis capability bit 343 * but they can handle a chassis poweroff or powercycle command. 344 */ 345 346#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} 347static int ipmi_dell_chassis_detect (ipmi_user_t user) 348{ 349 const char ipmi_version_major = ipmi_version & 0xF; 350 const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; 351 const char mfr[3]=DELL_IANA_MFR_ID; 352 if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && 353 ipmi_version_major <= 1 && 354 ipmi_version_minor < 5) 355 return 1; 356 return 0; 357} 358 359/* 360 * Standard chassis support 361 */ 362 363#define IPMI_NETFN_CHASSIS_REQUEST 0 364#define IPMI_CHASSIS_CONTROL_CMD 0x02 365 366static int ipmi_chassis_detect (ipmi_user_t user) 367{ 368 /* Chassis support, use it. */ 369 return (capabilities & 0x80); 370} 371 372static void ipmi_poweroff_chassis (ipmi_user_t user) 373{ 374 struct ipmi_system_interface_addr smi_addr; 375 struct kernel_ipmi_msg send_msg; 376 int rv; 377 unsigned char data[1]; 378 379 /* 380 * Configure IPMI address for local access 381 */ 382 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 383 smi_addr.channel = IPMI_BMC_CHANNEL; 384 smi_addr.lun = 0; 385 386 powercyclefailed: 387 printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", 388 ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle")); 389 390 /* 391 * Power down 392 */ 393 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; 394 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; 395 data[0] = poweroff_control; 396 send_msg.data = data; 397 send_msg.data_len = sizeof(data); 398 rv = ipmi_request_in_rc_mode(user, 399 (struct ipmi_addr *) &smi_addr, 400 &send_msg); 401 if (rv) { 402 switch (poweroff_control) { 403 case IPMI_CHASSIS_POWER_CYCLE: 404 /* power cycle failed, default to power down */ 405 printk(KERN_ERR PFX "Unable to send chassis power " \ 406 "cycle message, IPMI error 0x%x\n", rv); 407 poweroff_control = IPMI_CHASSIS_POWER_DOWN; 408 goto powercyclefailed; 409 410 case IPMI_CHASSIS_POWER_DOWN: 411 default: 412 printk(KERN_ERR PFX "Unable to send chassis power " \ 413 "down message, IPMI error 0x%x\n", rv); 414 break; 415 } 416 } 417 418 return; 419} 420 421 422/* Table of possible power off functions. */ 423struct poweroff_function { 424 char *platform_type; 425 int (*detect)(ipmi_user_t user); 426 void (*poweroff_func)(ipmi_user_t user); 427}; 428 429static struct poweroff_function poweroff_functions[] = { 430 { .platform_type = "ATCA", 431 .detect = ipmi_atca_detect, 432 .poweroff_func = ipmi_poweroff_atca }, 433 { .platform_type = "CPI1", 434 .detect = ipmi_cpi1_detect, 435 .poweroff_func = ipmi_poweroff_cpi1 }, 436 { .platform_type = "chassis", 437 .detect = ipmi_dell_chassis_detect, 438 .poweroff_func = ipmi_poweroff_chassis }, 439 /* Chassis should generally be last, other things should override 440 it. */ 441 { .platform_type = "chassis", 442 .detect = ipmi_chassis_detect, 443 .poweroff_func = ipmi_poweroff_chassis }, 444}; 445#define NUM_PO_FUNCS (sizeof(poweroff_functions) \ 446 / sizeof(struct poweroff_function)) 447 448 449/* Our local state. */ 450static int ready = 0; 451static ipmi_user_t ipmi_user; 452static void (*specific_poweroff_func)(ipmi_user_t user) = NULL; 453 454/* Holds the old poweroff function so we can restore it on removal. */ 455static void (*old_poweroff_func)(void); 456 457 458/* Called on a powerdown request. */ 459static void ipmi_poweroff_function (void) 460{ 461 if (!ready) 462 return; 463 464 /* Use run-to-completion mode, since interrupts may be off. */ 465 ipmi_user_set_run_to_completion(ipmi_user, 1); 466 specific_poweroff_func(ipmi_user); 467 ipmi_user_set_run_to_completion(ipmi_user, 0); 468} 469 470/* Wait for an IPMI interface to be installed, the first one installed 471 will be grabbed by this code and used to perform the powerdown. */ 472static void ipmi_po_new_smi(int if_num) 473{ 474 struct ipmi_system_interface_addr smi_addr; 475 struct kernel_ipmi_msg send_msg; 476 int rv; 477 int i; 478 479 if (ready) 480 return; 481 482 rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, 483 &ipmi_user); 484 if (rv) { 485 printk(KERN_ERR PFX "could not create IPMI user, error %d\n", 486 rv); 487 return; 488 } 489 490 /* 491 * Do a get device ide and store some results, since this is 492 * used by several functions. 493 */ 494 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 495 smi_addr.channel = IPMI_BMC_CHANNEL; 496 smi_addr.lun = 0; 497 498 send_msg.netfn = IPMI_NETFN_APP_REQUEST; 499 send_msg.cmd = IPMI_GET_DEVICE_ID_CMD; 500 send_msg.data = NULL; 501 send_msg.data_len = 0; 502 rv = ipmi_request_wait_for_response(ipmi_user, 503 (struct ipmi_addr *) &smi_addr, 504 &send_msg); 505 if (rv) { 506 printk(KERN_ERR PFX "Unable to send IPMI get device id info," 507 " IPMI error 0x%x\n", rv); 508 goto out_err; 509 } 510 511 if (halt_recv_msg.msg.data_len < 12) { 512 printk(KERN_ERR PFX "(chassis) IPMI get device id info too," 513 " short, was %d bytes, needed %d bytes\n", 514 halt_recv_msg.msg.data_len, 12); 515 goto out_err; 516 } 517 518 mfg_id = (halt_recv_msg.msg.data[7] 519 | (halt_recv_msg.msg.data[8] << 8) 520 | (halt_recv_msg.msg.data[9] << 16)); 521 prod_id = (halt_recv_msg.msg.data[10] 522 | (halt_recv_msg.msg.data[11] << 8)); 523 capabilities = halt_recv_msg.msg.data[6]; 524 ipmi_version = halt_recv_msg.msg.data[5]; 525 526 527 /* Scan for a poweroff method */ 528 for (i=0; i<NUM_PO_FUNCS; i++) { 529 if (poweroff_functions[i].detect(ipmi_user)) 530 goto found; 531 } 532 533 out_err: 534 printk(KERN_ERR PFX "Unable to find a poweroff function that" 535 " will work, giving up\n"); 536 ipmi_destroy_user(ipmi_user); 537 return; 538 539 found: 540 printk(KERN_INFO PFX "Found a %s style poweroff function\n", 541 poweroff_functions[i].platform_type); 542 specific_poweroff_func = poweroff_functions[i].poweroff_func; 543 old_poweroff_func = pm_power_off; 544 pm_power_off = ipmi_poweroff_function; 545 ready = 1; 546} 547 548static void ipmi_po_smi_gone(int if_num) 549{ 550 /* This can never be called, because once poweroff driver is 551 registered, the interface can't go away until the power 552 driver is unregistered. */ 553} 554 555static struct ipmi_smi_watcher smi_watcher = 556{ 557 .owner = THIS_MODULE, 558 .new_smi = ipmi_po_new_smi, 559 .smi_gone = ipmi_po_smi_gone 560}; 561 562 563#ifdef CONFIG_PROC_FS 564/* displays properties to proc */ 565static int proc_read_chassctrl(char *page, char **start, off_t off, int count, 566 int *eof, void *data) 567{ 568 return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n", 569 poweroff_control); 570} 571 572/* process property writes from proc */ 573static int proc_write_chassctrl(struct file *file, const char *buffer, 574 unsigned long count, void *data) 575{ 576 int rv = count; 577 unsigned int newval = 0; 578 579 sscanf(buffer, "%d", &newval); 580 switch (newval) { 581 case IPMI_CHASSIS_POWER_CYCLE: 582 printk(KERN_INFO PFX "power cycle is now enabled\n"); 583 poweroff_control = newval; 584 break; 585 586 case IPMI_CHASSIS_POWER_DOWN: 587 poweroff_control = IPMI_CHASSIS_POWER_DOWN; 588 break; 589 590 default: 591 rv = -EINVAL; 592 break; 593 } 594 595 return rv; 596} 597#endif /* CONFIG_PROC_FS */ 598 599/* 600 * Startup and shutdown functions. 601 */ 602static int ipmi_poweroff_init (void) 603{ 604 int rv; 605 struct proc_dir_entry *file; 606 607 printk ("Copyright (C) 2004 MontaVista Software -" 608 " IPMI Powerdown via sys_reboot.\n"); 609 610 switch (poweroff_control) { 611 case IPMI_CHASSIS_POWER_CYCLE: 612 printk(KERN_INFO PFX "Power cycle is enabled.\n"); 613 break; 614 615 case IPMI_CHASSIS_POWER_DOWN: 616 default: 617 poweroff_control = IPMI_CHASSIS_POWER_DOWN; 618 break; 619 } 620 621 rv = ipmi_smi_watcher_register(&smi_watcher); 622 if (rv) { 623 printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); 624 goto out_err; 625 } 626 627#ifdef CONFIG_PROC_FS 628 file = create_proc_entry("poweroff_control", 0, proc_ipmi_root); 629 if (!file) { 630 printk(KERN_ERR PFX "Unable to create proc power control\n"); 631 } else { 632 file->nlink = 1; 633 file->read_proc = proc_read_chassctrl; 634 file->write_proc = proc_write_chassctrl; 635 file->owner = THIS_MODULE; 636 } 637#endif 638 639 out_err: 640 return rv; 641} 642 643#ifdef MODULE 644static __exit void ipmi_poweroff_cleanup(void) 645{ 646 int rv; 647 648#ifdef CONFIG_PROC_FS 649 remove_proc_entry("poweroff_control", proc_ipmi_root); 650#endif 651 652 ipmi_smi_watcher_unregister(&smi_watcher); 653 654 if (ready) { 655 rv = ipmi_destroy_user(ipmi_user); 656 if (rv) 657 printk(KERN_ERR PFX "could not cleanup the IPMI" 658 " user: 0x%x\n", rv); 659 pm_power_off = old_poweroff_func; 660 } 661} 662module_exit(ipmi_poweroff_cleanup); 663#endif 664 665module_init(ipmi_poweroff_init); 666MODULE_LICENSE("GPL"); 667MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); 668MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot"); 669