mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-13 16:16:42 +07:00
ipmi: Start the timer and thread on internal msgs
The timer and thread were not being started for internal messages, so in interrupt mode if something hung the timer would never go off and clean things up. Factor out the internal message sending and start the timer for those messages, too. Signed-off-by: Corey Minyard <cminyard@mvista.com> Tested-by: Gouji, Masayuki <gouji.masayuki@jp.fujitsu.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
8005c49d9a
commit
0cfec916e8
@ -412,18 +412,42 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void start_check_enables(struct smi_info *smi_info)
|
||||
static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
|
||||
{
|
||||
smi_info->last_timeout_jiffies = jiffies;
|
||||
mod_timer(&smi_info->si_timer, new_val);
|
||||
smi_info->timer_running = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a new message and (re)start the timer and thread.
|
||||
*/
|
||||
static void start_new_msg(struct smi_info *smi_info, unsigned char *msg,
|
||||
unsigned int size)
|
||||
{
|
||||
smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
|
||||
|
||||
if (smi_info->thread)
|
||||
wake_up_process(smi_info->thread);
|
||||
|
||||
smi_info->handlers->start_transaction(smi_info->si_sm, msg, size);
|
||||
}
|
||||
|
||||
static void start_check_enables(struct smi_info *smi_info, bool start_timer)
|
||||
{
|
||||
unsigned char msg[2];
|
||||
|
||||
msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
|
||||
msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
|
||||
|
||||
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
|
||||
if (start_timer)
|
||||
start_new_msg(smi_info, msg, 2);
|
||||
else
|
||||
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
|
||||
smi_info->si_state = SI_CHECKING_ENABLES;
|
||||
}
|
||||
|
||||
static void start_clear_flags(struct smi_info *smi_info)
|
||||
static void start_clear_flags(struct smi_info *smi_info, bool start_timer)
|
||||
{
|
||||
unsigned char msg[3];
|
||||
|
||||
@ -432,7 +456,10 @@ static void start_clear_flags(struct smi_info *smi_info)
|
||||
msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
|
||||
msg[2] = WDT_PRE_TIMEOUT_INT;
|
||||
|
||||
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
|
||||
if (start_timer)
|
||||
start_new_msg(smi_info, msg, 3);
|
||||
else
|
||||
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
|
||||
smi_info->si_state = SI_CLEARING_FLAGS;
|
||||
}
|
||||
|
||||
@ -442,10 +469,8 @@ static void start_getting_msg_queue(struct smi_info *smi_info)
|
||||
smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD;
|
||||
smi_info->curr_msg->data_size = 2;
|
||||
|
||||
smi_info->handlers->start_transaction(
|
||||
smi_info->si_sm,
|
||||
smi_info->curr_msg->data,
|
||||
smi_info->curr_msg->data_size);
|
||||
start_new_msg(smi_info, smi_info->curr_msg->data,
|
||||
smi_info->curr_msg->data_size);
|
||||
smi_info->si_state = SI_GETTING_MESSAGES;
|
||||
}
|
||||
|
||||
@ -455,20 +480,11 @@ static void start_getting_events(struct smi_info *smi_info)
|
||||
smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
|
||||
smi_info->curr_msg->data_size = 2;
|
||||
|
||||
smi_info->handlers->start_transaction(
|
||||
smi_info->si_sm,
|
||||
smi_info->curr_msg->data,
|
||||
smi_info->curr_msg->data_size);
|
||||
start_new_msg(smi_info, smi_info->curr_msg->data,
|
||||
smi_info->curr_msg->data_size);
|
||||
smi_info->si_state = SI_GETTING_EVENTS;
|
||||
}
|
||||
|
||||
static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
|
||||
{
|
||||
smi_info->last_timeout_jiffies = jiffies;
|
||||
mod_timer(&smi_info->si_timer, new_val);
|
||||
smi_info->timer_running = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we have a situtaion where we run out of memory and cannot
|
||||
* allocate messages, we just leave them in the BMC and run the system
|
||||
@ -478,11 +494,11 @@ static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
|
||||
* Note that we cannot just use disable_irq(), since the interrupt may
|
||||
* be shared.
|
||||
*/
|
||||
static inline bool disable_si_irq(struct smi_info *smi_info)
|
||||
static inline bool disable_si_irq(struct smi_info *smi_info, bool start_timer)
|
||||
{
|
||||
if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
|
||||
smi_info->interrupt_disabled = true;
|
||||
start_check_enables(smi_info);
|
||||
start_check_enables(smi_info, start_timer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -492,7 +508,7 @@ static inline bool enable_si_irq(struct smi_info *smi_info)
|
||||
{
|
||||
if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
|
||||
smi_info->interrupt_disabled = false;
|
||||
start_check_enables(smi_info);
|
||||
start_check_enables(smi_info, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -510,7 +526,7 @@ static struct ipmi_smi_msg *alloc_msg_handle_irq(struct smi_info *smi_info)
|
||||
|
||||
msg = ipmi_alloc_smi_msg();
|
||||
if (!msg) {
|
||||
if (!disable_si_irq(smi_info))
|
||||
if (!disable_si_irq(smi_info, true))
|
||||
smi_info->si_state = SI_NORMAL;
|
||||
} else if (enable_si_irq(smi_info)) {
|
||||
ipmi_free_smi_msg(msg);
|
||||
@ -526,7 +542,7 @@ static void handle_flags(struct smi_info *smi_info)
|
||||
/* Watchdog pre-timeout */
|
||||
smi_inc_stat(smi_info, watchdog_pretimeouts);
|
||||
|
||||
start_clear_flags(smi_info);
|
||||
start_clear_flags(smi_info, true);
|
||||
smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
|
||||
if (smi_info->intf)
|
||||
ipmi_smi_watchdog_pretimeout(smi_info->intf);
|
||||
@ -879,8 +895,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
|
||||
msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
|
||||
msg[1] = IPMI_GET_MSG_FLAGS_CMD;
|
||||
|
||||
smi_info->handlers->start_transaction(
|
||||
smi_info->si_sm, msg, 2);
|
||||
start_new_msg(smi_info, msg, 2);
|
||||
smi_info->si_state = SI_GETTING_FLAGS;
|
||||
goto restart;
|
||||
}
|
||||
@ -910,7 +925,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
|
||||
* disable and messages disabled.
|
||||
*/
|
||||
if (smi_info->supports_event_msg_buff || smi_info->irq) {
|
||||
start_check_enables(smi_info);
|
||||
start_check_enables(smi_info, true);
|
||||
} else {
|
||||
smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
|
||||
if (!smi_info->curr_msg)
|
||||
@ -3613,7 +3628,7 @@ static int try_smi_init(struct smi_info *new_smi)
|
||||
* Start clearing the flags before we enable interrupts or the
|
||||
* timer to avoid racing with the timer.
|
||||
*/
|
||||
start_clear_flags(new_smi);
|
||||
start_clear_flags(new_smi, false);
|
||||
|
||||
/*
|
||||
* IRQ is defined to be set when non-zero. req_events will
|
||||
@ -3908,7 +3923,7 @@ static void cleanup_one_si(struct smi_info *to_clean)
|
||||
poll(to_clean);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
}
|
||||
disable_si_irq(to_clean);
|
||||
disable_si_irq(to_clean, false);
|
||||
while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
|
||||
poll(to_clean);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
|
Loading…
Reference in New Issue
Block a user