Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 71236
b: refs/heads/master
c: fcfa472
h: refs/heads/master
v: v3
  • Loading branch information
Corey Minyard authored and Linus Torvalds committed Oct 18, 2007
1 parent b7eeb4d commit c69a497
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 48 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 650dd0c7faf8126aaa261833dc9171a070deeaf3
refs/heads/master: fcfa4724116589d6a5fac92af410b6f12d41b5bb
9 changes: 9 additions & 0 deletions trunk/drivers/char/ipmi/ipmi_msghandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -2614,6 +2614,14 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
return;
}

void ipmi_poll_interface(ipmi_user_t user)
{
ipmi_smi_t intf = user->intf;

if (intf->handlers->poll)
intf->handlers->poll(intf->send_info);
}

int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
void *send_info,
struct ipmi_device_id *device_id,
Expand Down Expand Up @@ -4166,6 +4174,7 @@ EXPORT_SYMBOL(ipmi_destroy_user);
EXPORT_SYMBOL(ipmi_get_version);
EXPORT_SYMBOL(ipmi_request_settime);
EXPORT_SYMBOL(ipmi_request_supply_msgs);
EXPORT_SYMBOL(ipmi_poll_interface);
EXPORT_SYMBOL(ipmi_register_smi);
EXPORT_SYMBOL(ipmi_unregister_smi);
EXPORT_SYMBOL(ipmi_register_for_cmd);
Expand Down
6 changes: 5 additions & 1 deletion trunk/drivers/char/ipmi/ipmi_si_intf.c
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,8 @@ static void handle_transaction_done(struct smi_info *smi_info)
}

/* Called on timeouts and events. Timeouts should pass the elapsed
time, interrupts should pass in zero. */
time, interrupts should pass in zero. Must be called with
si_lock held and interrupts disabled. */
static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
int time)
{
Expand Down Expand Up @@ -892,13 +893,16 @@ static int ipmi_thread(void *data)
static void poll(void *send_info)
{
struct smi_info *smi_info = send_info;
unsigned long flags;

/*
* Make sure there is some delay in the poll loop so we can
* drive time forward and timeout things.
*/
udelay(10);
spin_lock_irqsave(&smi_info->si_lock, flags);
smi_event_handler(smi_info, 10);
spin_unlock_irqrestore(&smi_info->si_lock, flags);
}

static void request_events(void *send_info)
Expand Down
105 changes: 59 additions & 46 deletions trunk/drivers/char/ipmi/ipmi_watchdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,6 @@ static unsigned char ipmi_version_minor;
static atomic_t preop_panic_excl = ATOMIC_INIT(-1);

static int ipmi_heartbeat(void);
static void panic_halt_ipmi_heartbeat(void);


/* We use a mutex to make sure that only one thing can send a set
timeout at one time, because we only have one copy of the data.
Expand Down Expand Up @@ -440,19 +438,64 @@ static int ipmi_set_timeout(int do_heartbeat)
return rv;
}

static void dummy_smi_free(struct ipmi_smi_msg *msg)
static atomic_t panic_done_count = ATOMIC_INIT(0);

static void panic_smi_free(struct ipmi_smi_msg *msg)
{
atomic_dec(&panic_done_count);
}
static void dummy_recv_free(struct ipmi_recv_msg *msg)
static void panic_recv_free(struct ipmi_recv_msg *msg)
{
atomic_dec(&panic_done_count);
}

static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
{
.done = panic_smi_free
};
static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
{
.done = panic_recv_free
};

static void panic_halt_ipmi_heartbeat(void)
{
struct kernel_ipmi_msg msg;
struct ipmi_system_interface_addr addr;
int rv;

/* Don't reset the timer if we have the timer turned off, that
re-enables the watchdog. */
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
return;

addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
addr.channel = IPMI_BMC_CHANNEL;
addr.lun = 0;

msg.netfn = 0x06;
msg.cmd = IPMI_WDOG_RESET_TIMER;
msg.data = NULL;
msg.data_len = 0;
rv = ipmi_request_supply_msgs(watchdog_user,
(struct ipmi_addr *) &addr,
0,
&msg,
NULL,
&panic_halt_heartbeat_smi_msg,
&panic_halt_heartbeat_recv_msg,
1);
if (!rv)
atomic_add(2, &panic_done_count);
}

static struct ipmi_smi_msg panic_halt_smi_msg =
{
.done = dummy_smi_free
.done = panic_smi_free
};
static struct ipmi_recv_msg panic_halt_recv_msg =
{
.done = dummy_recv_free
.done = panic_recv_free
};

/* Special call, doesn't claim any locks. This is only to be called
Expand All @@ -464,13 +507,21 @@ static void panic_halt_ipmi_set_timeout(void)
int send_heartbeat_now;
int rv;

/* Wait for the messages to be free. */
while (atomic_read(&panic_done_count) != 0)
ipmi_poll_interface(watchdog_user);
rv = i_ipmi_set_timeout(&panic_halt_smi_msg,
&panic_halt_recv_msg,
&send_heartbeat_now);
if (!rv) {
atomic_add(2, &panic_done_count);
if (send_heartbeat_now)
panic_halt_ipmi_heartbeat();
}
} else
printk(KERN_WARNING PFX
"Unable to extend the watchdog timeout.");
while (atomic_read(&panic_done_count) != 0)
ipmi_poll_interface(watchdog_user);
}

/* We use a semaphore to make sure that only one thing can send a
Expand Down Expand Up @@ -499,15 +550,6 @@ static struct ipmi_recv_msg heartbeat_recv_msg =
.done = heartbeat_free_recv
};

static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
{
.done = dummy_smi_free
};
static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
{
.done = dummy_recv_free
};

static int ipmi_heartbeat(void)
{
struct kernel_ipmi_msg msg;
Expand Down Expand Up @@ -580,35 +622,6 @@ static int ipmi_heartbeat(void)
return rv;
}

static void panic_halt_ipmi_heartbeat(void)
{
struct kernel_ipmi_msg msg;
struct ipmi_system_interface_addr addr;


/* Don't reset the timer if we have the timer turned off, that
re-enables the watchdog. */
if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
return;

addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
addr.channel = IPMI_BMC_CHANNEL;
addr.lun = 0;

msg.netfn = 0x06;
msg.cmd = IPMI_WDOG_RESET_TIMER;
msg.data = NULL;
msg.data_len = 0;
ipmi_request_supply_msgs(watchdog_user,
(struct ipmi_addr *) &addr,
0,
&msg,
NULL,
&panic_halt_heartbeat_smi_msg,
&panic_halt_heartbeat_recv_msg,
1);
}

static struct watchdog_info ident =
{
.options = 0, /* WDIOF_SETTIMEOUT, */
Expand Down Expand Up @@ -998,7 +1011,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
/* Make sure we only do this once. */
reboot_event_handled = 1;

if (code == SYS_DOWN || code == SYS_HALT) {
if (code == SYS_POWER_OFF || code == SYS_HALT) {
/* Disable the WDT if we are shutting down. */
ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
panic_halt_ipmi_set_timeout();
Expand Down
10 changes: 10 additions & 0 deletions trunk/include/linux/ipmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,16 @@ int ipmi_request_supply_msgs(ipmi_user_t user,
struct ipmi_recv_msg *supplied_recv,
int priority);

/*
* Poll the IPMI interface for the user. This causes the IPMI code to
* do an immediate check for information from the driver and handle
* anything that is immediately pending. This will not block in any
* way. This is useful if you need to implement polling from the user
* for things like modifying the watchdog timeout when a panic occurs
* or disabling the watchdog timer on a reboot.
*/
void ipmi_poll_interface(ipmi_user_t user);

/*
* When commands come in to the SMS, the user can register to receive
* them. Only one user can be listening on a specific netfn/cmd/chan tuple
Expand Down

0 comments on commit c69a497

Please sign in to comment.