]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] ia64: Periodically forward MCA or INIT records to user-level
authorKeith Owens <kaos@ocs.com.au>
Tue, 10 Feb 2004 07:37:14 +0000 (23:37 -0800)
committerDavid Mosberger <davidm@tiger.hpl.hp.com>
Tue, 10 Feb 2004 07:37:14 +0000 (23:37 -0800)
Periodically check for outstanding MCA or INIT records and pass them to
user space salinfo.

arch/ia64/kernel/salinfo.c

index f44191bc55e401df26cefc19984c7ab1438c3102..696b3ba7e761656f367195e04da54ec90119b62c 100644 (file)
@@ -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;
 }