aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ipmi/ipmi_watchdog.c
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2007-10-18 06:07:09 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-18 17:37:32 -0400
commitfcfa4724116589d6a5fac92af410b6f12d41b5bb (patch)
treee709e6e51e8475836f56478a4645bbeeb8daf134 /drivers/char/ipmi/ipmi_watchdog.c
parent650dd0c7faf8126aaa261833dc9171a070deeaf3 (diff)
IPMI: add polled interface
Currently the IPMI watchdog timer sets the watchdog timeout on a panic, but it doesn't actually poll the interface to make sure the message goes out. Add an interface for polling the IPMI driver, and add code to the IPMI watchdog timer to poll the interface when the timer is set from a panic. Signed-off-by: Corey Minyard <cminyard@mvista.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_watchdog.c')
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c105
1 files changed, 59 insertions, 46 deletions
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 806106b8c980..19a8683bd25d 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -314,8 +314,6 @@ static unsigned char ipmi_version_minor;
314static atomic_t preop_panic_excl = ATOMIC_INIT(-1); 314static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
315 315
316static int ipmi_heartbeat(void); 316static int ipmi_heartbeat(void);
317static void panic_halt_ipmi_heartbeat(void);
318
319 317
320/* We use a mutex to make sure that only one thing can send a set 318/* We use a mutex to make sure that only one thing can send a set
321 timeout at one time, because we only have one copy of the data. 319 timeout at one time, because we only have one copy of the data.
@@ -440,19 +438,64 @@ out:
440 return rv; 438 return rv;
441} 439}
442 440
443static void dummy_smi_free(struct ipmi_smi_msg *msg) 441static atomic_t panic_done_count = ATOMIC_INIT(0);
442
443static void panic_smi_free(struct ipmi_smi_msg *msg)
444{ 444{
445 atomic_dec(&panic_done_count);
445} 446}
446static void dummy_recv_free(struct ipmi_recv_msg *msg) 447static void panic_recv_free(struct ipmi_recv_msg *msg)
448{
449 atomic_dec(&panic_done_count);
450}
451
452static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
453{
454 .done = panic_smi_free
455};
456static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
447{ 457{
458 .done = panic_recv_free
459};
460
461static void panic_halt_ipmi_heartbeat(void)
462{
463 struct kernel_ipmi_msg msg;
464 struct ipmi_system_interface_addr addr;
465 int rv;
466
467 /* Don't reset the timer if we have the timer turned off, that
468 re-enables the watchdog. */
469 if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
470 return;
471
472 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
473 addr.channel = IPMI_BMC_CHANNEL;
474 addr.lun = 0;
475
476 msg.netfn = 0x06;
477 msg.cmd = IPMI_WDOG_RESET_TIMER;
478 msg.data = NULL;
479 msg.data_len = 0;
480 rv = ipmi_request_supply_msgs(watchdog_user,
481 (struct ipmi_addr *) &addr,
482 0,
483 &msg,
484 NULL,
485 &panic_halt_heartbeat_smi_msg,
486 &panic_halt_heartbeat_recv_msg,
487 1);
488 if (!rv)
489 atomic_add(2, &panic_done_count);
448} 490}
491
449static struct ipmi_smi_msg panic_halt_smi_msg = 492static struct ipmi_smi_msg panic_halt_smi_msg =
450{ 493{
451 .done = dummy_smi_free 494 .done = panic_smi_free
452}; 495};
453static struct ipmi_recv_msg panic_halt_recv_msg = 496static struct ipmi_recv_msg panic_halt_recv_msg =
454{ 497{
455 .done = dummy_recv_free 498 .done = panic_recv_free
456}; 499};
457 500
458/* Special call, doesn't claim any locks. This is only to be called 501/* Special call, doesn't claim any locks. This is only to be called
@@ -464,13 +507,21 @@ static void panic_halt_ipmi_set_timeout(void)
464 int send_heartbeat_now; 507 int send_heartbeat_now;
465 int rv; 508 int rv;
466 509
510 /* Wait for the messages to be free. */
511 while (atomic_read(&panic_done_count) != 0)
512 ipmi_poll_interface(watchdog_user);
467 rv = i_ipmi_set_timeout(&panic_halt_smi_msg, 513 rv = i_ipmi_set_timeout(&panic_halt_smi_msg,
468 &panic_halt_recv_msg, 514 &panic_halt_recv_msg,
469 &send_heartbeat_now); 515 &send_heartbeat_now);
470 if (!rv) { 516 if (!rv) {
517 atomic_add(2, &panic_done_count);
471 if (send_heartbeat_now) 518 if (send_heartbeat_now)
472 panic_halt_ipmi_heartbeat(); 519 panic_halt_ipmi_heartbeat();
473 } 520 } else
521 printk(KERN_WARNING PFX
522 "Unable to extend the watchdog timeout.");
523 while (atomic_read(&panic_done_count) != 0)
524 ipmi_poll_interface(watchdog_user);
474} 525}
475 526
476/* We use a semaphore to make sure that only one thing can send a 527/* We use a semaphore to make sure that only one thing can send a
@@ -499,15 +550,6 @@ static struct ipmi_recv_msg heartbeat_recv_msg =
499 .done = heartbeat_free_recv 550 .done = heartbeat_free_recv
500}; 551};
501 552
502static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
503{
504 .done = dummy_smi_free
505};
506static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
507{
508 .done = dummy_recv_free
509};
510
511static int ipmi_heartbeat(void) 553static int ipmi_heartbeat(void)
512{ 554{
513 struct kernel_ipmi_msg msg; 555 struct kernel_ipmi_msg msg;
@@ -580,35 +622,6 @@ static int ipmi_heartbeat(void)
580 return rv; 622 return rv;
581} 623}
582 624
583static void panic_halt_ipmi_heartbeat(void)
584{
585 struct kernel_ipmi_msg msg;
586 struct ipmi_system_interface_addr addr;
587
588
589 /* Don't reset the timer if we have the timer turned off, that
590 re-enables the watchdog. */
591 if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
592 return;
593
594 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
595 addr.channel = IPMI_BMC_CHANNEL;
596 addr.lun = 0;
597
598 msg.netfn = 0x06;
599 msg.cmd = IPMI_WDOG_RESET_TIMER;
600 msg.data = NULL;
601 msg.data_len = 0;
602 ipmi_request_supply_msgs(watchdog_user,
603 (struct ipmi_addr *) &addr,
604 0,
605 &msg,
606 NULL,
607 &panic_halt_heartbeat_smi_msg,
608 &panic_halt_heartbeat_recv_msg,
609 1);
610}
611
612static struct watchdog_info ident = 625static struct watchdog_info ident =
613{ 626{
614 .options = 0, /* WDIOF_SETTIMEOUT, */ 627 .options = 0, /* WDIOF_SETTIMEOUT, */
@@ -998,7 +1011,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
998 /* Make sure we only do this once. */ 1011 /* Make sure we only do this once. */
999 reboot_event_handled = 1; 1012 reboot_event_handled = 1;
1000 1013
1001 if (code == SYS_DOWN || code == SYS_HALT) { 1014 if (code == SYS_POWER_OFF || code == SYS_HALT) {
1002 /* Disable the WDT if we are shutting down. */ 1015 /* Disable the WDT if we are shutting down. */
1003 ipmi_watchdog_state = WDOG_TIMEOUT_NONE; 1016 ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
1004 panic_halt_ipmi_set_timeout(); 1017 panic_halt_ipmi_set_timeout();