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