Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13 644 lines 17 kB view raw
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#define IPMI_POWEROFF_VERSION "v33" 46 47/* Where to we insert our poweroff function? */ 48extern void (*pm_power_off)(void); 49 50/* Definitions for controlling power off (if the system supports it). It 51 * conveniently matches the IPMI chassis control values. */ 52#define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */ 53#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ 54 55/* the IPMI data command */ 56static int poweroff_control = IPMI_CHASSIS_POWER_DOWN; 57 58/* parameter definition to allow user to flag power cycle */ 59module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); 60MODULE_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."); 61 62/* Stuff from the get device id command. */ 63static unsigned int mfg_id; 64static unsigned int prod_id; 65static unsigned char capabilities; 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 * Standard chassis support 342 */ 343 344#define IPMI_NETFN_CHASSIS_REQUEST 0 345#define IPMI_CHASSIS_CONTROL_CMD 0x02 346 347static int ipmi_chassis_detect (ipmi_user_t user) 348{ 349 /* Chassis support, use it. */ 350 return (capabilities & 0x80); 351} 352 353static void ipmi_poweroff_chassis (ipmi_user_t user) 354{ 355 struct ipmi_system_interface_addr smi_addr; 356 struct kernel_ipmi_msg send_msg; 357 int rv; 358 unsigned char data[1]; 359 360 /* 361 * Configure IPMI address for local access 362 */ 363 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 364 smi_addr.channel = IPMI_BMC_CHANNEL; 365 smi_addr.lun = 0; 366 367 powercyclefailed: 368 printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", 369 ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle")); 370 371 /* 372 * Power down 373 */ 374 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; 375 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; 376 data[0] = poweroff_control; 377 send_msg.data = data; 378 send_msg.data_len = sizeof(data); 379 rv = ipmi_request_in_rc_mode(user, 380 (struct ipmi_addr *) &smi_addr, 381 &send_msg); 382 if (rv) { 383 switch (poweroff_control) { 384 case IPMI_CHASSIS_POWER_CYCLE: 385 /* power cycle failed, default to power down */ 386 printk(KERN_ERR PFX "Unable to send chassis power " \ 387 "cycle message, IPMI error 0x%x\n", rv); 388 poweroff_control = IPMI_CHASSIS_POWER_DOWN; 389 goto powercyclefailed; 390 391 case IPMI_CHASSIS_POWER_DOWN: 392 default: 393 printk(KERN_ERR PFX "Unable to send chassis power " \ 394 "down message, IPMI error 0x%x\n", rv); 395 break; 396 } 397 } 398 399 return; 400} 401 402 403/* Table of possible power off functions. */ 404struct poweroff_function { 405 char *platform_type; 406 int (*detect)(ipmi_user_t user); 407 void (*poweroff_func)(ipmi_user_t user); 408}; 409 410static struct poweroff_function poweroff_functions[] = { 411 { .platform_type = "ATCA", 412 .detect = ipmi_atca_detect, 413 .poweroff_func = ipmi_poweroff_atca }, 414 { .platform_type = "CPI1", 415 .detect = ipmi_cpi1_detect, 416 .poweroff_func = ipmi_poweroff_cpi1 }, 417 /* Chassis should generally be last, other things should override 418 it. */ 419 { .platform_type = "chassis", 420 .detect = ipmi_chassis_detect, 421 .poweroff_func = ipmi_poweroff_chassis }, 422}; 423#define NUM_PO_FUNCS (sizeof(poweroff_functions) \ 424 / sizeof(struct poweroff_function)) 425 426 427/* Our local state. */ 428static int ready = 0; 429static ipmi_user_t ipmi_user; 430static void (*specific_poweroff_func)(ipmi_user_t user) = NULL; 431 432/* Holds the old poweroff function so we can restore it on removal. */ 433static void (*old_poweroff_func)(void); 434 435 436/* Called on a powerdown request. */ 437static void ipmi_poweroff_function (void) 438{ 439 if (!ready) 440 return; 441 442 /* Use run-to-completion mode, since interrupts may be off. */ 443 ipmi_user_set_run_to_completion(ipmi_user, 1); 444 specific_poweroff_func(ipmi_user); 445 ipmi_user_set_run_to_completion(ipmi_user, 0); 446} 447 448/* Wait for an IPMI interface to be installed, the first one installed 449 will be grabbed by this code and used to perform the powerdown. */ 450static void ipmi_po_new_smi(int if_num) 451{ 452 struct ipmi_system_interface_addr smi_addr; 453 struct kernel_ipmi_msg send_msg; 454 int rv; 455 int i; 456 457 if (ready) 458 return; 459 460 rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, 461 &ipmi_user); 462 if (rv) { 463 printk(KERN_ERR PFX "could not create IPMI user, error %d\n", 464 rv); 465 return; 466 } 467 468 /* 469 * Do a get device ide and store some results, since this is 470 * used by several functions. 471 */ 472 smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; 473 smi_addr.channel = IPMI_BMC_CHANNEL; 474 smi_addr.lun = 0; 475 476 send_msg.netfn = IPMI_NETFN_APP_REQUEST; 477 send_msg.cmd = IPMI_GET_DEVICE_ID_CMD; 478 send_msg.data = NULL; 479 send_msg.data_len = 0; 480 rv = ipmi_request_wait_for_response(ipmi_user, 481 (struct ipmi_addr *) &smi_addr, 482 &send_msg); 483 if (rv) { 484 printk(KERN_ERR PFX "Unable to send IPMI get device id info," 485 " IPMI error 0x%x\n", rv); 486 goto out_err; 487 } 488 489 if (halt_recv_msg.msg.data_len < 12) { 490 printk(KERN_ERR PFX "(chassis) IPMI get device id info too," 491 " short, was %d bytes, needed %d bytes\n", 492 halt_recv_msg.msg.data_len, 12); 493 goto out_err; 494 } 495 496 mfg_id = (halt_recv_msg.msg.data[7] 497 | (halt_recv_msg.msg.data[8] << 8) 498 | (halt_recv_msg.msg.data[9] << 16)); 499 prod_id = (halt_recv_msg.msg.data[10] 500 | (halt_recv_msg.msg.data[11] << 8)); 501 capabilities = halt_recv_msg.msg.data[6]; 502 503 504 /* Scan for a poweroff method */ 505 for (i=0; i<NUM_PO_FUNCS; i++) { 506 if (poweroff_functions[i].detect(ipmi_user)) 507 goto found; 508 } 509 510 out_err: 511 printk(KERN_ERR PFX "Unable to find a poweroff function that" 512 " will work, giving up\n"); 513 ipmi_destroy_user(ipmi_user); 514 return; 515 516 found: 517 printk(KERN_INFO PFX "Found a %s style poweroff function\n", 518 poweroff_functions[i].platform_type); 519 specific_poweroff_func = poweroff_functions[i].poweroff_func; 520 old_poweroff_func = pm_power_off; 521 pm_power_off = ipmi_poweroff_function; 522 ready = 1; 523} 524 525static void ipmi_po_smi_gone(int if_num) 526{ 527 /* This can never be called, because once poweroff driver is 528 registered, the interface can't go away until the power 529 driver is unregistered. */ 530} 531 532static struct ipmi_smi_watcher smi_watcher = 533{ 534 .owner = THIS_MODULE, 535 .new_smi = ipmi_po_new_smi, 536 .smi_gone = ipmi_po_smi_gone 537}; 538 539 540#ifdef CONFIG_PROC_FS 541/* displays properties to proc */ 542static int proc_read_chassctrl(char *page, char **start, off_t off, int count, 543 int *eof, void *data) 544{ 545 return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n", 546 poweroff_control); 547} 548 549/* process property writes from proc */ 550static int proc_write_chassctrl(struct file *file, const char *buffer, 551 unsigned long count, void *data) 552{ 553 int rv = count; 554 unsigned int newval = 0; 555 556 sscanf(buffer, "%d", &newval); 557 switch (newval) { 558 case IPMI_CHASSIS_POWER_CYCLE: 559 printk(KERN_INFO PFX "power cycle is now enabled\n"); 560 poweroff_control = newval; 561 break; 562 563 case IPMI_CHASSIS_POWER_DOWN: 564 poweroff_control = IPMI_CHASSIS_POWER_DOWN; 565 break; 566 567 default: 568 rv = -EINVAL; 569 break; 570 } 571 572 return rv; 573} 574#endif /* CONFIG_PROC_FS */ 575 576/* 577 * Startup and shutdown functions. 578 */ 579static int ipmi_poweroff_init (void) 580{ 581 int rv; 582 struct proc_dir_entry *file; 583 584 printk ("Copyright (C) 2004 MontaVista Software -" 585 " IPMI Powerdown via sys_reboot version " 586 IPMI_POWEROFF_VERSION ".\n"); 587 588 switch (poweroff_control) { 589 case IPMI_CHASSIS_POWER_CYCLE: 590 printk(KERN_INFO PFX "Power cycle is enabled.\n"); 591 break; 592 593 case IPMI_CHASSIS_POWER_DOWN: 594 default: 595 poweroff_control = IPMI_CHASSIS_POWER_DOWN; 596 break; 597 } 598 599 rv = ipmi_smi_watcher_register(&smi_watcher); 600 if (rv) { 601 printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); 602 goto out_err; 603 } 604 605#ifdef CONFIG_PROC_FS 606 file = create_proc_entry("poweroff_control", 0, proc_ipmi_root); 607 if (!file) { 608 printk(KERN_ERR PFX "Unable to create proc power control\n"); 609 } else { 610 file->nlink = 1; 611 file->read_proc = proc_read_chassctrl; 612 file->write_proc = proc_write_chassctrl; 613 file->owner = THIS_MODULE; 614 } 615#endif 616 617 out_err: 618 return rv; 619} 620 621#ifdef MODULE 622static __exit void ipmi_poweroff_cleanup(void) 623{ 624 int rv; 625 626#ifdef CONFIG_PROC_FS 627 remove_proc_entry("poweroff_control", proc_ipmi_root); 628#endif 629 630 ipmi_smi_watcher_unregister(&smi_watcher); 631 632 if (ready) { 633 rv = ipmi_destroy_user(ipmi_user); 634 if (rv) 635 printk(KERN_ERR PFX "could not cleanup the IPMI" 636 " user: 0x%x\n", rv); 637 pm_power_off = old_poweroff_func; 638 } 639} 640module_exit(ipmi_poweroff_cleanup); 641#endif 642 643module_init(ipmi_poweroff_init); 644MODULE_LICENSE("GPL");