Commit a1466ec5 authored by Corey Minyard's avatar Corey Minyard

ipmi: Fix SSIF flag requests

Commit 89986496 ("ipmi: Turn off all activity on an idle ipmi
interface") modified the IPMI code to only request events when the
driver had somethine waiting for events.  The SSIF code, however,
was using the event fetch request to also fetch the flags.

Add a timer and the proper handling for the upper layer telling
whether flags fetches are required.
Reported-by: default avatarKamlakant Patel <Kamlakant.Patel@cavium.com>
Signed-off-by: default avatarCorey Minyard <cminyard@mvista.com>
Tested-by: default avatarKamlakant Patel <kamlakant.patel@cavium.com>
parent 401e7e88
......@@ -90,6 +90,12 @@
#define SSIF_MSG_JIFFIES ((SSIF_MSG_USEC * 1000) / TICK_NSEC)
#define SSIF_MSG_PART_JIFFIES ((SSIF_MSG_PART_USEC * 1000) / TICK_NSEC)
/*
* Timeout for the watch, only used for get flag timer.
*/
#define SSIF_WATCH_TIMEOUT_MSEC 100
#define SSIF_WATCH_TIMEOUT_JIFFIES msecs_to_jiffies(SSIF_WATCH_TIMEOUT_MSEC)
enum ssif_intf_state {
SSIF_NORMAL,
SSIF_GETTING_FLAGS,
......@@ -270,6 +276,9 @@ struct ssif_info {
struct timer_list retry_timer;
int retries_left;
bool need_watch; /* Need to look for flags? */
struct timer_list watch_timer; /* Flag fetch timer. */
/* Info from SSIF cmd */
unsigned char max_xmit_msg_size;
unsigned char max_recv_msg_size;
......@@ -560,6 +569,26 @@ static void retry_timeout(struct timer_list *t)
start_get(ssif_info);
}
static void watch_timeout(struct timer_list *t)
{
struct ssif_info *ssif_info = from_timer(ssif_info, t, watch_timer);
unsigned long oflags, *flags;
if (ssif_info->stopping)
return;
flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
if (ssif_info->need_watch) {
mod_timer(&ssif_info->watch_timer,
jiffies + SSIF_WATCH_TIMEOUT_JIFFIES);
if (SSIF_IDLE(ssif_info)) {
start_flag_fetch(ssif_info, flags); /* Releases lock */
return;
}
ssif_info->req_flags = true;
}
ipmi_ssif_unlock_cond(ssif_info, flags);
}
static void ssif_alert(struct i2c_client *client, enum i2c_alert_protocol type,
unsigned int data)
......@@ -1073,8 +1102,7 @@ static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
}
/*
* Instead of having our own timer to periodically check the message
* flags, we let the message handler drive us.
* Upper layer wants us to request events.
*/
static void request_events(void *send_info)
{
......@@ -1085,18 +1113,27 @@ static void request_events(void *send_info)
return;
flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
/*
* Request flags first, not events, because the lower layer
* doesn't have a way to send an attention. But make sure
* event checking still happens.
*/
ssif_info->req_events = true;
if (SSIF_IDLE(ssif_info))
start_flag_fetch(ssif_info, flags);
else {
ssif_info->req_flags = true;
ipmi_ssif_unlock_cond(ssif_info, flags);
ipmi_ssif_unlock_cond(ssif_info, flags);
}
/*
* Upper layer is changing the flag saying whether we need to request
* flags periodically or not.
*/
static void ssif_set_need_watch(void *send_info, bool enable)
{
struct ssif_info *ssif_info = (struct ssif_info *) send_info;
unsigned long oflags, *flags;
flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
if (enable != ssif_info->need_watch) {
ssif_info->need_watch = enable;
if (ssif_info->need_watch)
mod_timer(&ssif_info->watch_timer,
jiffies + SSIF_WATCH_TIMEOUT_JIFFIES);
}
ipmi_ssif_unlock_cond(ssif_info, flags);
}
static int ssif_start_processing(void *send_info,
......@@ -1223,6 +1260,7 @@ static void shutdown_ssif(void *send_info)
schedule_timeout(1);
ssif_info->stopping = true;
del_timer_sync(&ssif_info->watch_timer);
del_timer_sync(&ssif_info->retry_timer);
if (ssif_info->thread) {
complete(&ssif_info->wake_thread);
......@@ -1708,6 +1746,7 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
spin_lock_init(&ssif_info->lock);
ssif_info->ssif_state = SSIF_NORMAL;
timer_setup(&ssif_info->retry_timer, retry_timeout, 0);
timer_setup(&ssif_info->watch_timer, watch_timeout, 0);
for (i = 0; i < SSIF_NUM_STATS; i++)
atomic_set(&ssif_info->stats[i], 0);
......@@ -1721,6 +1760,7 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
ssif_info->handlers.get_smi_info = get_smi_info;
ssif_info->handlers.sender = sender;
ssif_info->handlers.request_events = request_events;
ssif_info->handlers.set_need_watch = ssif_set_need_watch;
{
unsigned int thread_num;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment