r4765 - developers/werner/wlan-spi/patches-tracking
werner at docs.openmoko.org
werner at docs.openmoko.org
Fri Nov 7 04:50:29 CET 2008
Author: werner
Date: 2008-11-07 04:50:29 +0100 (Fri, 07 Nov 2008)
New Revision: 4765
Added:
developers/werner/wlan-spi/patches-tracking/find-irq-blockers.patch
Log:
WIP.
Added: developers/werner/wlan-spi/patches-tracking/find-irq-blockers.patch
===================================================================
--- developers/werner/wlan-spi/patches-tracking/find-irq-blockers.patch (rev 0)
+++ developers/werner/wlan-spi/patches-tracking/find-irq-blockers.patch 2008-11-07 03:50:29 UTC (rev 4765)
@@ -0,0 +1,257 @@
+Quick and dirty interrupt blocking time detector.
+
+Index: ktrack/arch/arm/include/asm/irqflags.h
+===================================================================
+--- ktrack.orig/arch/arm/include/asm/irqflags.h 2008-11-05 23:28:34.000000000 -0200
++++ ktrack/arch/arm/include/asm/irqflags.h 2008-11-05 23:53:25.000000000 -0200
+@@ -5,6 +5,12 @@
+
+ #include <asm/ptrace.h>
+
++
++void iblock_start(void);
++void iblock_end(void);
++void iblock_end_maybe(unsigned long flags);
++
++
+ /*
+ * CPU interrupt mask handling.
+ */
+@@ -31,6 +37,7 @@
+ #define raw_local_irq_save(x) \
+ ({ \
+ unsigned long temp; \
++ iblock_start(); \
+ (void) (&temp == &x); \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ local_irq_save\n" \
+@@ -47,6 +54,7 @@
+ #define raw_local_irq_enable() \
+ ({ \
+ unsigned long temp; \
++ iblock_start(); \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ local_irq_enable\n" \
+ " bic %0, %0, #128\n" \
+@@ -62,6 +70,7 @@
+ #define raw_local_irq_disable() \
+ ({ \
+ unsigned long temp; \
++ iblock_start(); \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ local_irq_disable\n" \
+ " orr %0, %0, #128\n" \
+@@ -117,11 +126,12 @@
+ * restore saved IRQ & FIQ state
+ */
+ #define raw_local_irq_restore(x) \
++ ({ iblock_end_maybe(x); \
+ __asm__ __volatile__( \
+ "msr cpsr_c, %0 @ local_irq_restore\n" \
+ : \
+ : "r" (x) \
+- : "memory", "cc")
++ : "memory", "cc"); })
+
+ #define raw_irqs_disabled_flags(flags) \
+ ({ \
+Index: ktrack/arch/arm/kernel/Makefile
+===================================================================
+--- ktrack.orig/arch/arm/kernel/Makefile 2008-11-05 23:50:06.000000000 -0200
++++ ktrack/arch/arm/kernel/Makefile 2008-11-07 01:47:47.000000000 -0200
+@@ -44,5 +44,6 @@
+
+ head-y := head$(MMUEXT).o
+ obj-$(CONFIG_DEBUG_LL) += debug.o
++obj-y += iblock.o
+
+ extra-y := $(head-y) init_task.o vmlinux.lds
+Index: ktrack/arch/arm/plat-s3c/time.c
+===================================================================
+--- ktrack.orig/arch/arm/plat-s3c/time.c 2008-11-06 00:07:12.000000000 -0200
++++ ktrack/arch/arm/plat-s3c/time.c 2008-11-06 00:07:18.000000000 -0200
+@@ -96,7 +96,7 @@
+ * IRQs are disabled before entering here from do_gettimeofday()
+ */
+
+-static unsigned long s3c2410_gettimeoffset (void)
++unsigned long s3c2410_gettimeoffset (void)
+ {
+ unsigned long tdone;
+ unsigned long tval;
+Index: ktrack/arch/arm/plat-s3c24xx/time.c
+===================================================================
+--- ktrack.orig/arch/arm/plat-s3c24xx/time.c 2008-11-06 00:03:12.000000000 -0200
++++ ktrack/arch/arm/plat-s3c24xx/time.c 2008-11-06 00:03:16.000000000 -0200
+@@ -99,7 +99,7 @@
+
+ #define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
+
+-static unsigned long s3c2410_gettimeoffset (void)
++unsigned long s3c2410_gettimeoffset (void)
+ {
+ unsigned long tdone;
+ unsigned long irqpend;
+Index: ktrack/arch/arm/kernel/iblock.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ ktrack/arch/arm/kernel/iblock.c 2008-11-07 01:46:40.000000000 -0200
+@@ -0,0 +1,158 @@
++/*
++ *
++ * /sys/kernel/iblock/
++ * All times are in microseconds (us).
++ *
++ * - limit
++ * Interrupt blocking time reporting limit, in microseconds.
++ * 0 disables reporting. Auto-resets to zero after reporting.
++ *
++ * - max
++ * Maximum blocking time recorded. Reset to zero by writing anything.
++ *
++ * - test
++ * Force a delay with interrupts disabled.
++ *
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/sysfs.h>
++#include <linux/kobject.h>
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <asm/irqflags.h>
++
++
++unsigned long s3c2410_gettimeoffset(void);
++
++
++static unsigned long iblock_t0;
++static int iblock_limit;
++static int iblock_max;
++
++
++void iblock_start(void)
++{
++ unsigned long flags;
++
++ raw_local_save_flags(flags);
++ if (raw_irqs_disabled_flags(flags))
++ return;
++ iblock_t0 = s3c2410_gettimeoffset();
++}
++
++
++void iblock_end(void)
++{
++ unsigned long flags;
++ unsigned long t, us;
++
++ raw_local_save_flags(flags);
++ if (!raw_irqs_disabled_flags(flags))
++ return;
++ if (!iblock_t0)
++ return;
++ t = s3c2410_gettimeoffset();
++ us = t-iblock_t0;
++ if (us > 40000000)
++ return;
++ if (us > iblock_max)
++ iblock_max = us;
++ if (!iblock_limit)
++ return;
++ if (us < iblock_limit)
++ return;
++ iblock_limit = 0;
++ printk(KERN_ERR "interrupts were disabled for %lu us !\n", us);
++ WARN_ON(1);
++}
++
++
++void iblock_end_maybe(unsigned long flags)
++{
++ if (raw_irqs_disabled_flags(flags))
++ return;
++ iblock_end();
++}
++
++
++static ssize_t limit_read(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return sprintf(buf, "%u us\n", iblock_limit);
++}
++
++
++static ssize_t limit_write(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ unsigned long tmp;
++ char *end;
++
++ tmp = simple_strtoul(buf, &end, 0);
++ if (end == buf)
++ return -EINVAL;
++ iblock_limit = tmp;
++ return count;
++}
++
++
++static ssize_t max_read(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ return sprintf(buf, "%u us\n", iblock_max);
++}
++
++
++static ssize_t max_write(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ iblock_max = 0;
++ return count;
++}
++
++
++static ssize_t test_write(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ unsigned long tmp, flags;
++ char *end;
++
++ tmp = simple_strtoul(buf, &end, 0);
++ if (end == buf)
++ return -EINVAL;
++ local_irq_save(flags);
++ udelay(tmp);
++ local_irq_restore(flags);
++ return count;
++}
++
++
++static DEVICE_ATTR(limit, 0644, limit_read, limit_write);
++static DEVICE_ATTR(max, 0644, max_read, max_write);
++static DEVICE_ATTR(test, 0200, NULL, test_write);
++
++
++static struct attribute *sysfs_entries[] = {
++ &dev_attr_limit.attr,
++ &dev_attr_max.attr,
++ &dev_attr_test.attr,
++ NULL
++};
++
++
++static struct attribute_group attr_group = {
++ .name = "iblock",
++ .attrs = sysfs_entries,
++};
++
++
++static int __devinit iblock_init(void)
++{
++ return sysfs_create_group(kernel_kobj, &attr_group);
++}
++
++
++module_init(iblock_init);
More information about the commitlog
mailing list