patch-2.4.26 linux-2.4.26/arch/ia64/kernel/salinfo.c
Next file: linux-2.4.26/arch/ia64/kernel/signal.c
Previous file: linux-2.4.26/arch/ia64/kernel/ptrace.c
Back to the patch index
Back to the overall index
- Lines: 126
- Date:
2004-04-14 06:05:26.000000000 -0700
- Orig file:
linux-2.4.25/arch/ia64/kernel/salinfo.c
- Orig date:
2004-02-18 05:36:30.000000000 -0800
diff -urN linux-2.4.25/arch/ia64/kernel/salinfo.c linux-2.4.26/arch/ia64/kernel/salinfo.c
@@ -16,6 +16,13 @@
* 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.
+ *
+ * Feb 21 2004 kaos@sgi.com
+ * Copy record contents rather than relying on the mca.c buffers, to cope with
+ * interrupts arriving in mca.c faster than salinfo.c can process them.
*/
#include <linux/types.h>
@@ -23,6 +30,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>
@@ -83,6 +91,7 @@
u64 size;
u64 id;
int cpu;
+ int kmalloced :1; /* buffer was kmalloc'ed */
};
/* State transitions. Actions are :-
@@ -178,6 +187,8 @@
static void
shift1_data_saved (struct salinfo_data *data, int shift)
{
+ if (data->data_saved[shift].kmalloced)
+ kfree(data->data_saved[shift].buffer);
memcpy(data->data_saved+shift, data->data_saved+shift+1,
(ARRAY_SIZE(data->data_saved) - (shift+1)) * sizeof(data->data_saved[0]));
memset(data->data_saved + ARRAY_SIZE(data->data_saved) - 1, 0,
@@ -187,6 +198,8 @@
/* 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
@@ -194,12 +207,12 @@
* changes.
*/
void
-salinfo_log_wakeup(int type, u8 *buffer, u64 size)
+salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
{
struct salinfo_data *data = salinfo_data + type;
struct salinfo_data_saved *data_saved;
unsigned long flags = 0;
- int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT;
+ int i;
int saved_size = ARRAY_SIZE(data->data_saved);
BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
@@ -221,7 +234,13 @@
data_saved->cpu = smp_processor_id();
data_saved->id = ((sal_log_record_header_t *)buffer)->id;
data_saved->size = size;
- data_saved->buffer = buffer;
+ if (irqsafe && (data_saved->buffer = kmalloc(size, GFP_ATOMIC))) {
+ memcpy(data_saved->buffer, buffer, size);
+ data_saved->kmalloced = 1;
+ } else {
+ data_saved->buffer = buffer;
+ data_saved->kmalloced = 0;
+ }
}
if (irqsafe)
spin_unlock_irqrestore(&data_saved_lock, flags);
@@ -232,6 +251,35 @@
}
}
+/* 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)
{
@@ -571,6 +619,11 @@
*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;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)