Commit a5d5fc46 authored by Keith Owens's avatar Keith Owens Committed by David Mosberger

[PATCH] ia64: Periodically forward MCA or INIT records to user-level

Periodically check for outstanding MCA or INIT records and pass them to
user space salinfo.
parent 8510017e
......@@ -16,6 +16,9 @@
* Cache the record across multi-block reads from user space.
* Support > 64 cpus.
* Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module.
*
* Jan 28 2004 kaos@sgi.com
* Periodically check for outstanding MCA or INIT records.
*/
#include <linux/types.h>
......@@ -23,6 +26,7 @@
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/timer.h>
#include <linux/vmalloc.h>
#include <asm/semaphore.h>
......@@ -179,6 +183,8 @@ shift1_data_saved (struct salinfo_data *data, int shift)
/* This routine is invoked in interrupt context. Note: mca.c enables
* interrupts before calling this code for CMC/CPE. MCA and INIT events are
* not irq safe, do not call any routines that use spinlocks, they may deadlock.
* MCA and INIT records are recorded, a timer event will look for any
* outstanding events and wake up the user space code.
*
* The buffer passed from mca.c points to the output from ia64_log_get. This is
* a persistent buffer but its contents can change between the interrupt and
......@@ -224,6 +230,35 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
}
}
/* Check for outstanding MCA/INIT records every 5 minutes (arbitrary) */
#define SALINFO_TIMER_DELAY (5*60*HZ)
static struct timer_list salinfo_timer;
static void
salinfo_timeout_check(struct salinfo_data *data)
{
int i;
if (!data->open)
return;
for (i = 0; i < NR_CPUS; ++i) {
if (test_bit(i, &data->cpu_event)) {
/* double up() is not a problem, user space will see no
* records for the additional "events".
*/
up(&data->sem);
}
}
}
static void
salinfo_timeout (unsigned long arg)
{
salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT);
salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
add_timer(&salinfo_timer);
}
static int
salinfo_event_open(struct inode *inode, struct file *file)
{
......@@ -563,6 +598,11 @@ salinfo_init(void)
*sdir++ = salinfo_dir;
init_timer(&salinfo_timer);
salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
salinfo_timer.function = &salinfo_timeout;
add_timer(&salinfo_timer);
return 0;
}
......
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