linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH update 0/3] HW-latency: hardware latency test 0.10
@ 2012-11-11  2:48 Luming Yu
  2012-11-11  2:48 ` [PATCH update 1/3] " Luming Yu
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Luming Yu @ 2012-11-11  2:48 UTC (permalink / raw)
  To: arnd, linux-kernel; +Cc: Luming Yu, Jon Masters, Jon Masters

Update the previous patch series to ACK all comments I've recevied so far
for the tool: e.g. 1.Acked Jon Masters in source code as many code are from
jcm, thanks very much Jon. 2. squashed all changes against new file I added into
one. 3. Make it useful on non-x86.

Please review and commit to misc tree. I will update the patch series if anyone
has anymore comments.

Thanks very much!!!
 
Luming Yu (3):
  HW-latency: hardware latency test 0.10
  x86: Delete too many "Fast TSC .." in dmesg from HW_latency cyclic
    sampling
  fs: Fix crash caused by write to dummy debugfs interface like
    HW_latency exposed

 arch/x86/kernel/tsc.c          |   2 +-
 drivers/misc/Kconfig           |   6 +
 drivers/misc/Makefile          |   1 +
 drivers/misc/hw_latency_test.c | 939 +++++++++++++++++++++++++++++++++++++++++
 fs/libfs.c                     |   2 +-
 5 files changed, 948 insertions(+), 2 deletions(-)
 create mode 100644 drivers/misc/hw_latency_test.c

-- 
1.7.12.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH update 1/3] HW-latency: hardware latency test 0.10
  2012-11-11  2:48 [PATCH update 0/3] HW-latency: hardware latency test 0.10 Luming Yu
@ 2012-11-11  2:48 ` Luming Yu
  2012-11-11  2:48 ` [PATCH update 2/3] x86: Delete too many "Fast TSC .." in dmesg from HW_latency cyclic sampling Luming Yu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Luming Yu @ 2012-11-11  2:48 UTC (permalink / raw)
  To: arnd, linux-kernel; +Cc: Luming Yu, Jon Masters, Jon Masters, Luming Yu

This patch is the first step to test some basic hardware functions like
TSC to help people understand if there is any hardware latency as well
as throughput problem exposed on bare metal or left behind by BIOS or
interfered by SMI. Currently the patch tests TSC, CPU Frequency and
RDRAND which is a new CPU instruction to get random number introduced in
new CPU like Intel Ivy Bridge in stop_machine context,which is choosen to
make sure testers fully control their system under test to rule out some
level of unwanted noise.

Signed-off-by: Jon Masters <jcm@redhat.com>
Signed-off-by: Luming Yu <luming.yu@intel.com>
---
 drivers/misc/Kconfig           |   6 +
 drivers/misc/Makefile          |   1 +
 drivers/misc/hw_latency_test.c | 939 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 946 insertions(+)
 create mode 100644 drivers/misc/hw_latency_test.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b151b7c..a00b039 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -114,6 +114,12 @@ config IBM_ASM
 	  for information on the specific driver level and support statement
 	  for your IBM server.
 
+config HW_LATENCY_TEST
+	tristate "Testing module to detect hardware lattency and throughput"
+	depends on DEBUG_FS
+	depends on RING_BUFFER
+	default m
+
 config PHANTOM
 	tristate "Sensable PHANToM (PCI)"
 	depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 2129377..c195cce 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -49,3 +49,4 @@ obj-y				+= carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)		+= mei/
+obj-$(CONFIG_HW_LATENCY_TEST)	+= hw_latency_test.o
diff --git a/drivers/misc/hw_latency_test.c b/drivers/misc/hw_latency_test.c
new file mode 100644
index 0000000..0a4d23b
--- /dev/null
+++ b/drivers/misc/hw_latency_test.c
@@ -0,0 +1,939 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ring_buffer.h>
+#include <linux/stop_machine.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/kthread.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <asm/tlbflush.h>
+
+#define BUF_SIZE_DEFAULT	262144UL
+#define BUF_FLAGS	(RB_FL_OVERWRITE)
+#define	U64STR_SIZE	22
+#define DEBUGFS_BUF_SIZE	1024
+#define DEBUGFS_NAME_SIZE	32
+
+#define	VERSION		"0.1.0"
+#define BANNER		"hardware latency test"
+#define DRVNAME		"hw_latency_test"
+
+#define DEFAULT_SAMPLE_WINDOW	1000000	
+#define	DEFAULT_SAMPLE_WIDTH	500000
+#define	DEFAULT_LAT_THRESHOLD	10
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Luming Yu <luming.yu@gmail.com>");
+MODULE_DESCRIPTION("A simple hardware latency test");
+MODULE_VERSION(VERSION);
+
+static int debug;
+static int enabled;
+static int threshold;
+
+module_param(debug, int, 0);
+module_param(enabled, int, 0);
+module_param(threshold, int, 0);
+
+static struct ring_buffer *ring_buffer;
+static DEFINE_MUTEX(ring_buffer_mutex);
+static unsigned long buf_size = 262144UL;
+static struct task_struct *kthread;
+
+#ifdef CONFIG_X86_64
+static u8 *__start = (u8 *)0xffff880000000000;
+static u8 *__end = (u8 *)0xffffc7ffffffffff;
+#else
+static u8 *__start = (u8 *)0xc0000000;
+static u8 *__end = (u8 *)0xffffffff;
+#endif
+
+struct sample {
+	unsigned int cpu;
+	u64	seqnum;
+	u64	duration;
+	struct timespec	timestamp;
+	u64	addr;
+	u8	unit; /*0: ns 1:us*/
+	unsigned long	lost;
+};
+
+static struct data {
+	struct mutex lock;
+	u64	count;
+	u64	max_sample;
+	u64	threshold;
+
+	u64	sample_window;
+	u64	sample_width;
+
+	atomic_t sample_open;
+
+	wait_queue_head_t wq;
+} data;
+
+static ktime_t	now;
+struct sample_function {
+	const char *name;
+	u8	type; /* 0=all parallel, 1=anyone, 2=all sequential*/
+	struct list_head list;
+	int (*get_sample)(void *unused);
+};
+static struct sample_function *current_sample_func = NULL;
+static LIST_HEAD(sample_function_list);
+static DEFINE_MUTEX(sample_function_mutex);
+static int sample_function_register(struct sample_function *sf);
+static struct dentry *debug_dir;
+
+static int sample_function_register(struct sample_function *sf)
+{
+	struct list_head *entry = &sample_function_list;
+	mutex_lock(&sample_function_mutex);
+	list_add(&sf->list, entry);
+	current_sample_func = sf;
+	mutex_unlock(&sample_function_mutex);
+	return 0;
+}
+
+static int __buffer_add_sample(struct sample *sample)
+{
+	return ring_buffer_write(ring_buffer,
+				sizeof(struct sample), sample);
+}
+
+static struct sample *buffer_get_sample(struct sample *sample)
+{
+	struct ring_buffer_event *e = NULL;
+	struct sample *s = NULL;
+	unsigned int cpu = 0;
+
+	if (!sample)
+		return NULL;
+	
+	mutex_lock(&ring_buffer_mutex);
+	for_each_online_cpu(cpu) {
+		e = ring_buffer_consume(ring_buffer, cpu, NULL, &sample->lost);
+		if (e)
+			break;
+	}
+	if (e) {
+		s = ring_buffer_event_data(e);
+		memcpy(sample, s, sizeof(struct sample));
+	} else
+		sample = NULL;
+	mutex_unlock(&ring_buffer_mutex);
+	return sample;
+}
+
+static int buffer_add_sample(u64 sample, u8 unit)
+{
+	int ret = 0;
+	unsigned int cpu = smp_processor_id();
+
+	if (sample > data.threshold) {
+		struct sample s;
+
+		data.count++;
+		s.cpu = cpu;
+		s.seqnum = data.count;
+		s.duration = sample;
+		s.timestamp = CURRENT_TIME;
+		s.addr = (u64) __start;
+		s.unit = unit;
+		ret = __buffer_add_sample(&s);
+
+		if (sample > data.max_sample)
+			data.max_sample = sample;
+	}
+	return ret;
+}
+
+/*
+ * For new instruction rdrand since Intel Ivy Bridge processor
+ */
+static int get_random_bytes_sample(void *unused)
+{
+	u32 *buffer;
+	ktime_t	start, t1, t2;
+	s64	diff, total = 0;
+	u64	sample = 0;
+	int	ret = 1;
+
+	buffer = kzalloc(1024, GFP_ATOMIC);
+
+	start = ktime_get();
+	do {
+
+		t1 = ktime_get();
+		get_random_bytes_arch(buffer, 1024);
+		t2 = ktime_get();
+		total = ktime_to_us(ktime_sub(t2, start));
+		diff = ktime_to_us(ktime_sub(t2, t1));
+
+		if (diff < 0) {
+			printk(KERN_ERR BANNER "time running backwards\n");
+			goto out;
+		} 
+
+		if (diff > sample)
+			sample = diff;
+
+	} while (total <= data.sample_width);
+
+	ret = buffer_add_sample(sample, 1);
+out:
+	kfree(buffer);
+	return ret;
+}
+
+#if CONFIG_X86
+/*
+ * For cpu frequency testing
+ */
+static int get_freq_sample(void *unused)
+{
+	ktime_t	start, t1, t2;
+	s64	diff, total = 0;
+	u32	sample = 0;
+	int	ret = 1;
+	unsigned int cpu_tsc_freq;
+
+	start = ktime_get();
+	do {
+		t1 = ktime_get();
+		cpu_tsc_freq = x86_platform.calibrate_tsc();
+		t2 = ktime_get();
+		total = ktime_to_us(ktime_sub(t2, start));
+		diff = abs(cpu_tsc_freq - tsc_khz);
+
+		if (diff < 0) {
+			printk(KERN_ERR BANNER "time running backwards\n");
+			goto out;
+		} 
+
+		if (diff > sample)
+			sample = diff;
+
+	} while (total <= data.sample_width);
+
+	ret = buffer_add_sample(sample, 1);
+out:
+	return ret;
+}
+#endif
+
+/*
+ * For TSC latency as well as SMI detecting 
+ */
+static int get_tsc_sample(void *unused)
+{
+	ktime_t	start, t1, t2;
+	s64	diff, total = 0;
+	u64	sample = 0;
+	int	ret = 1;
+
+	now = start = ktime_get();
+	do {
+		t1 = now;
+		now = t2 = ktime_get();
+
+		total = ktime_to_ns(ktime_sub(t2, start));
+		diff = ktime_to_ns(ktime_sub(t2, t1));
+
+		if (diff < 0) {
+			printk(KERN_ERR BANNER "time running backwards\n");
+			goto out;
+		} 
+
+		if (diff > sample)
+			sample = diff;
+
+	} while (total <= data.sample_width);
+
+	ret = buffer_add_sample(sample, 0);
+out:
+	return ret;
+}
+
+#if CONFIG_X86
+static int get_mem_sample(void *unused)
+{
+	ktime_t	start, t1, t2;
+	s64	diff, total = 0;
+	u64	sample = 0;
+	int	ret = 1;
+	u8	temp;
+
+	now = start = ktime_get();
+	do {
+		t1 = now;
+		now = t2 = ktime_get();
+
+		total = ktime_to_ns(ktime_sub(t2, start));
+		temp = *__start++;
+		diff = ktime_to_ns(ktime_sub(t2, t1));
+
+		if (diff < 0) {
+			printk(KERN_ERR BANNER "time running backwards\n");
+			goto out;
+		} 
+
+		if (diff > sample)
+			sample = diff;
+
+		if (__start == __end) {
+			__start = (u8 *)0xffff880000000000;
+			printk(KERN_INFO BANNER "one pass finished, jmp to the beginning\n");
+		}
+
+	} while (total <= data.sample_width);
+
+	ret = buffer_add_sample(sample, 0);
+out:
+	return ret;
+}
+#endif
+
+struct sample_function tsc_sample = {
+	.name		= "tsc",
+	.type		= 0,
+	.get_sample 	= get_tsc_sample,
+};
+
+struct sample_function random_bytes_sample = {
+	.name		= "random_bytes",
+	.type		= 0,
+	.get_sample 	= get_random_bytes_sample,
+};
+
+#if CONFIG_X86
+struct sample_function tsc_freq_sample = {
+	.name		= "freq",
+	.type		= 2,
+	.get_sample 	= get_freq_sample,
+};
+
+struct sample_function mem_sample = {
+	.name		= "mem",
+	.type		= 1,
+	.get_sample 	= get_mem_sample,
+};
+#endif
+
+static DECLARE_BITMAP(testing_cpu_map, NR_CPUS);
+
+static int kthread_fn(void *unused)
+{
+	int err = 0;
+	u64 interval = 0;
+	int cpu;
+	struct cpumask *testing_cpu_mask = to_cpumask(testing_cpu_map);
+	int (*get_sample)(void *unused);
+	
+	mutex_lock(&sample_function_mutex);
+	if (current_sample_func)
+		get_sample = current_sample_func->get_sample;
+	else
+		goto out;
+
+	cpumask_or(testing_cpu_mask, testing_cpu_mask, cpu_online_mask);
+	while (!kthread_should_stop()) {
+		mutex_lock(&data.lock);
+
+		switch (current_sample_func->type) {
+		case 0:
+			err = stop_machine(get_sample, unused, testing_cpu_mask);
+			break;
+		case 1:
+			err = stop_machine(get_sample, unused, NULL);
+			break;
+		case 2:
+			for_each_cpu(cpu, cpu_online_mask) {
+				cpumask_clear(testing_cpu_mask);
+				cpumask_set_cpu(cpu, testing_cpu_mask);
+				err = stop_machine(get_sample, unused, testing_cpu_mask);
+				if (err)
+					break;
+			}
+			break;
+		default:
+			mutex_unlock(&data.lock);
+			goto err_out;
+		}
+
+		if (err) {
+			mutex_unlock(&data.lock);
+			goto err_out;
+		}
+
+		wake_up(&data.wq);
+
+		interval = data.sample_window - data.sample_width;
+		do_div(interval, USEC_PER_MSEC);
+
+		mutex_unlock(&data.lock);
+		if (msleep_interruptible(interval))
+			goto out;
+	}
+	goto out;
+err_out:
+	printk(KERN_ERR BANNER "could not call stop_machine, disabling\n");
+	enabled = 0;
+out:
+	mutex_unlock(&sample_function_mutex);
+	return err;
+}
+
+static int start_kthread(void)
+{
+	kthread = kthread_run(kthread_fn, NULL, DRVNAME);
+	if (IS_ERR(kthread)) {
+		printk(KERN_ERR BANNER "could not start sampling thread\n");
+		enabled = 0;
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int stop_kthread(void)
+{
+	int ret;
+	ret = kthread_stop(kthread);
+	return ret;
+}
+
+static void __reset_stats(void)
+{
+	data.count = 0;
+	data.max_sample = 0;
+	ring_buffer_reset(ring_buffer);
+}
+
+static int init_stats(void)
+{
+	int ret = -ENOMEM;
+	
+	mutex_init(&data.lock);
+	init_waitqueue_head(&data.wq);
+	atomic_set(&data.sample_open,0);
+
+	ring_buffer = ring_buffer_alloc(buf_size, BUF_FLAGS);
+
+	if (WARN(!ring_buffer, KERN_ERR BANNER
+		"failed to allocate ring buffer!\n"))
+		goto out;
+	__reset_stats();
+	data.threshold = DEFAULT_LAT_THRESHOLD;
+	data.sample_window = DEFAULT_SAMPLE_WINDOW;
+	data.sample_width = DEFAULT_SAMPLE_WIDTH;
+	ret = 0;
+out:
+	return ret;
+}
+
+static ssize_t simple_data_read(struct file *filp, char __user *ubuf,
+				size_t cnt, loff_t *ppos, const u64 *entry)
+{
+	char buf[U64STR_SIZE];
+	u64 val = 0;
+	int len = 0;
+
+	memset(buf, 0, sizeof(buf));
+	if (!entry)
+		return -EFAULT;
+	mutex_lock(&data.lock);
+	val = *entry;
+	mutex_unlock(&data.lock);
+	len = snprintf(buf, sizeof(buf), "%llu\n", (unsigned long long)val);
+	return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
+}
+
+static ssize_t simple_data_write(struct file *filp, const char __user *ubuf,
+				size_t cnt, loff_t *ppos, u64 *entry)
+{
+	char buf[U64STR_SIZE];
+	int csize = min(cnt, sizeof(buf));
+	u64 val = 0;
+	int err = 0;
+
+	memset(buf, '\0', sizeof(buf));
+	if (copy_from_user(buf, ubuf, csize))
+		return -EFAULT;
+	buf[U64STR_SIZE-1] = '\0';
+	err = strict_strtoull(buf, 10, &val);
+	if (err)
+		return -EINVAL;
+	mutex_lock(&data.lock);
+	*entry = val;
+	mutex_unlock(&data.lock);
+	return csize;
+}
+
+#define debug_available_fopen	simple_open
+
+static ssize_t debug_available_fread(struct file *filp, char __user *ubuf,
+					size_t	cnt, loff_t *ppos)
+{
+	struct sample_function *sf;
+	ssize_t	count = 0;
+	char *buf;
+
+	buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	mutex_lock(&sample_function_mutex);
+	list_for_each_entry(sf, &sample_function_list, list) {
+		count += snprintf(buf + count,
+			max((ssize_t)(DEBUGFS_BUF_SIZE - count), (ssize_t)0),
+			"%s ", sf->name); 
+	}
+	mutex_unlock(&sample_function_mutex);
+	
+	count += snprintf(buf + count,
+				max((ssize_t )DEBUGFS_BUF_SIZE - count, (ssize_t) 0),
+				"\n");
+	count = simple_read_from_buffer(ubuf, cnt, ppos, buf, count); 
+	kfree(buf);
+	return count;
+}
+
+#define debug_available_fwrite	simple_attr_write
+
+#define debug_available_release	simple_attr_release
+
+#define debug_current_fopen	simple_open
+
+static ssize_t debug_current_fread(struct file *filp, char __user *ubuf,
+					size_t cnt, loff_t *ppos)
+{
+	ssize_t	count = 0;
+	char *buf;
+
+	buf = kzalloc(DEBUGFS_NAME_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	count += snprintf(buf + count,
+		max((ssize_t)DEBUGFS_NAME_SIZE - count, (ssize_t)0),
+			"%s ", current_sample_func->name); 
+	count += snprintf(buf + count,
+			max((ssize_t)DEBUGFS_NAME_SIZE - count, (ssize_t)0),
+			"\n");
+	count = simple_read_from_buffer(ubuf, cnt, ppos, buf, count); 
+	kfree(buf);
+
+	return count;
+}
+static ssize_t debug_current_fwrite(struct file *filp, const char __user *ubuf,
+					size_t cnt, loff_t *ppos)
+{
+	char *buf;
+	ssize_t count;
+	struct sample_function *sf;
+
+	buf = kzalloc(DEBUGFS_NAME_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	count = simple_write_to_buffer(buf, DEBUGFS_NAME_SIZE, ppos, ubuf, cnt);
+	mutex_lock(&sample_function_mutex);
+	list_for_each_entry(sf, &sample_function_list, list) {
+		if (strncmp(sf->name, buf, count-1) !=0)
+			continue;
+		current_sample_func = sf;
+		break;
+	}
+	mutex_unlock(&sample_function_mutex);
+	return (ssize_t) count;
+}
+#define debug_current_release	simple_attr_release
+
+#define debug_count_fopen	simple_open
+
+static ssize_t debug_count_fread(struct file *filp, char __user *ubuf,
+					size_t cnt, loff_t *ppos)
+{
+	return simple_data_read(filp, ubuf, cnt, ppos, &data.count);
+}
+static ssize_t debug_count_fwrite(struct file *filp, const char __user *ubuf,
+					size_t cnt,
+					loff_t *ppos)
+{
+	return simple_data_write(filp, ubuf, cnt, ppos, &data.count);
+}
+#define debug_count_release	simple_attr_release
+
+#define debug_enable_fopen	simple_open
+
+static ssize_t debug_enable_fread(struct file *filp, char __user *ubuf,
+					size_t cnt, loff_t *ppos)
+{
+	char buf[4];
+	if ((cnt < sizeof(buf)) || (*ppos))
+		return 0;
+	buf[0] = enabled ? '1' : '0';
+	buf[1] = '\n';
+	buf[2] = '\0';
+	if (copy_to_user(ubuf, buf, strlen(buf)))
+		return -EFAULT;
+	return *ppos = strlen(buf);
+}
+static ssize_t debug_enable_fwrite(struct file *filp,
+					const char __user *ubuf,
+					size_t cnt,
+					loff_t *ppos)
+{
+	char buf[4];
+	int csize = min(cnt, sizeof(buf));
+	long val = 0;
+	int err = 0;
+
+	memset(buf, '\0', sizeof(buf));
+	if (copy_from_user(buf, ubuf, csize))
+		return -EFAULT;
+	buf[sizeof(buf)-1] = '\0';
+	err = strict_strtoul(buf, 10, &val);
+	if (0 != err)
+		return -EINVAL;
+	if (val) {
+		if (enabled)
+			goto unlock;
+		enabled = 1;
+		if (start_kthread())
+			return -EFAULT;
+	} else {
+		if (!enabled)
+			goto unlock;
+		enabled = 0;
+		err = stop_kthread();
+		if (err) {
+			printk(KERN_ERR BANNER "cannot stop kthread\n");
+			return -EFAULT;
+		}
+		wake_up(&data.wq);
+	}
+unlock:
+	return csize;
+}
+#define debug_enable_release	simple_attr_release
+
+#define debug_max_fopen	simple_open
+
+static ssize_t debug_max_fread(struct file *filp, char __user *ubuf,
+				size_t cnt, loff_t *ppos)
+{
+	return simple_data_read(filp, ubuf, cnt, ppos, &data.max_sample);
+}
+static ssize_t debug_max_fwrite(struct file *filp,
+				const char __user *ubuf,
+				size_t	cnt,
+				loff_t	*ppos)
+{
+	return simple_data_write(filp, ubuf, cnt, ppos, &data.max_sample);
+}
+#define debug_max_release	simple_attr_release
+
+static int debug_sample_fopen(struct inode *inode, struct file *filp)
+{
+	if (!atomic_add_unless(&data.sample_open, 1, 1))
+		return -EBUSY;
+	else
+		return 0;
+}
+static ssize_t debug_sample_fread(struct file *filp, char __user *ubuf,
+					size_t cnt, loff_t *ppos)
+{
+	int len = 0;
+	char buf[64];
+	struct sample *sample = NULL;
+
+	if (!enabled)
+		return 0;
+	sample = kzalloc(sizeof(struct sample), GFP_KERNEL);
+	if(!sample)
+		return -ENOMEM;
+
+	while (!buffer_get_sample(sample)) {
+		DEFINE_WAIT(wait);
+		if (filp->f_flags & O_NONBLOCK) {
+			len = -EAGAIN;
+			goto out;
+		}
+		prepare_to_wait(&data.wq, &wait, TASK_INTERRUPTIBLE);
+		schedule();
+		finish_wait(&data.wq, &wait);
+		if (signal_pending(current)) {
+			len = -EINTR;
+			goto out;
+		}
+		if (!enabled) {
+			len = 0;
+			goto out;
+		}
+	}
+
+#if CONFIG_X86
+	len = snprintf(buf, sizeof(buf), "[%d]%010lu.%010lu\t%llu%2s\t[%llx]\n",
+			sample->cpu,
+			sample->timestamp.tv_sec,
+			sample->timestamp.tv_nsec,
+			sample->duration,
+			sample->unit ? "us":"ns",
+			(((u64) (current_sample_func->get_sample)
+				== (u64) get_mem_sample) ? sample->addr: 0));
+#else
+	len = snprintf(buf, sizeof(buf), "[%d]%010lu.%010lu\t%llu%2s\n",
+			sample->cpu,
+			sample->timestamp.tv_sec,
+			sample->timestamp.tv_nsec,
+			sample->duration,
+			sample->unit ? "us":"ns");
+#endif
+	if (len > cnt)
+		goto out;
+	if (copy_to_user(ubuf, buf,len))
+		len = -EFAULT;
+out:
+	kfree(sample);
+	return len;
+}
+
+#define debug_sample_fwrite	simple_attr_write
+
+static int debug_sample_release(struct inode *inode, struct file *filp)
+{
+	atomic_dec(&data.sample_open);
+	return 0;
+}
+
+#define debug_threshold_fopen	simple_open
+
+static ssize_t debug_threshold_fread(struct file *filp, char __user *ubuf,
+					size_t cnt, loff_t *ppos)
+{
+	return simple_data_read(filp, ubuf, cnt, ppos, &data.threshold);
+}
+static ssize_t debug_threshold_fwrite(struct file *filp,
+					const char __user *ubuf,
+					size_t cnt,
+					loff_t *ppos)
+{
+	int ret;
+	ret = simple_data_write(filp, ubuf, cnt, ppos, &data.threshold);
+	if (enabled)
+		wake_up_process(kthread);
+	return ret;
+}
+#define debug_threshold_release	simple_attr_release
+
+#define debug_width_fopen	simple_open
+
+static ssize_t debug_width_fread(struct file *filp, char __user *ubuf,
+				size_t cnt, loff_t *ppos)
+{
+	return simple_data_read(filp, ubuf, cnt, ppos, &data.sample_width);
+}
+static ssize_t debug_width_fwrite(struct file *filp,
+					const char __user *ubuf,
+					size_t cnt,
+					loff_t *ppos)
+{
+	char buf[U64STR_SIZE];
+	int csize = min(cnt, sizeof(buf));
+	u64 val = 0;
+	int err = 0;
+
+	memset(buf, '\0', sizeof(buf));
+	if (copy_from_user(buf, ubuf, csize))
+		return -EFAULT;
+	buf[U64STR_SIZE-1] = '\0';
+	err = strict_strtoull(buf, 10, &val);
+	if (0 != err)
+		return -EINVAL;
+	mutex_lock(&data.lock);
+	if (val < data.sample_window)
+		data.sample_width = val;
+	else {
+		mutex_unlock(&data.lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&data.lock);
+	if (enabled)
+		wake_up_process(kthread);
+
+	return csize;
+}
+#define debug_width_release	simple_attr_release
+
+#define debug_window_fopen	simple_open
+
+static ssize_t debug_window_fread(struct file *filp, char __user *ubuf,
+				size_t cnt, loff_t *ppos)
+{
+	return simple_data_read(filp, ubuf, cnt, ppos, &data.sample_window);
+}
+static ssize_t debug_window_fwrite(struct file *filp,
+					const char __user *ubuf,
+					size_t cnt,
+					loff_t *ppos)
+{
+	char buf[U64STR_SIZE];
+	int csize = min(cnt, sizeof(buf));
+	u64 val = 0;
+	int err = 0;
+
+	memset(buf, '\0', sizeof(buf));
+	if (copy_from_user(buf, ubuf, csize))
+		return -EFAULT;
+	buf[U64STR_SIZE-1] = '\0';
+	err = strict_strtoull(buf, 10, &val);
+	if (0 != err)
+		return -EINVAL;
+	mutex_lock(&data.lock);
+	if (data.sample_width < val)
+		data.sample_window = val;
+	else {
+		mutex_unlock(&data.lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&data.lock);
+	return csize;
+}
+#define debug_window_release	simple_attr_release
+
+#define DEFINE_DEBUGFS_FILE(name)				\
+	static const struct file_operations name##_fops = {	\
+		.open = debug_##name##_fopen,			\
+		.read = debug_##name##_fread,			\
+		.write = debug_##name##_fwrite,			\
+		.release = debug_##name##_release,		\
+		.owner = THIS_MODULE,				\
+	};
+
+DEFINE_DEBUGFS_FILE(available)
+DEFINE_DEBUGFS_FILE(current)
+DEFINE_DEBUGFS_FILE(count)
+DEFINE_DEBUGFS_FILE(enable)
+DEFINE_DEBUGFS_FILE(max)
+DEFINE_DEBUGFS_FILE(sample)
+DEFINE_DEBUGFS_FILE(threshold)
+DEFINE_DEBUGFS_FILE(width)
+DEFINE_DEBUGFS_FILE(window)
+
+#undef DEFINE_DEBUGFS_FILE
+
+#undef current
+#define DEFINE_ENTRY(name) {__stringify(name), &name##_fops, NULL},
+
+static struct debugfs_file_table
+{
+	const char	*file_name;
+	const struct file_operations	*fops;
+	struct dentry	*dentry;
+} file_table[] = {
+	DEFINE_ENTRY(available)
+	DEFINE_ENTRY(current)
+	DEFINE_ENTRY(sample)
+	DEFINE_ENTRY(count)
+	DEFINE_ENTRY(max)
+	DEFINE_ENTRY(window)
+	DEFINE_ENTRY(threshold)
+	DEFINE_ENTRY(enable)
+	{NULL, NULL,NULL},
+};
+#undef DEFINE_ENTRY
+
+static int init_debugfs(void)
+{
+	int ret = -ENOMEM;
+	int	i=0;
+
+	debug_dir = debugfs_create_dir(DRVNAME, NULL);
+	if (!debug_dir)
+		goto err_debug_dir;
+
+	while (file_table[i].fops) {
+		file_table[i].dentry =
+			 debugfs_create_file(file_table[i].file_name, 0444,
+						debug_dir, NULL,
+						file_table[i].fops);
+		if (!file_table[i].dentry)
+			break;
+		i++;
+	}
+	if (file_table[i].fops) {
+		i--;
+		while (i>=0 && file_table[i].fops && file_table[i].dentry) {
+			debugfs_remove(file_table[i].dentry);
+			i--;
+		}
+		debugfs_remove(debug_dir);
+	}
+	ret = 0;
+err_debug_dir:
+	return ret;
+}
+
+static void free_debugfs(void)
+{
+	int i=0;
+
+	while (file_table[i].fops && file_table[i].dentry) {
+		debugfs_remove(file_table[i].dentry);
+		i++;
+	}
+	debugfs_remove(debug_dir);
+}
+
+static int hw_test_init(void)
+{
+	int ret = -ENOMEM;
+	
+	printk(KERN_INFO BANNER "version %s\n", VERSION);
+
+	sample_function_register(&tsc_sample);
+	sample_function_register(&random_bytes_sample);
+#if CONFIG_X86
+	sample_function_register(&tsc_freq_sample);
+	sample_function_register(&mem_sample);
+#endif
+
+	ret = init_stats();
+	if (0 != ret)
+		goto out;
+	ret = init_debugfs();
+	if (0 != ret)
+		goto err_stats;
+	if (enabled)
+		ret = start_kthread();
+	goto out;
+
+err_stats:
+	ring_buffer_free(ring_buffer);
+out:
+	return ret;
+}
+
+static void hw_test_exit(void)
+{
+	int err;
+	
+	if (enabled) {
+		enabled = 0;
+		err = stop_kthread();
+		if (err)
+			printk(KERN_ERR BANNER "cannot stop kthread\n");
+	}
+	
+	free_debugfs();
+	ring_buffer_free(ring_buffer);
+}
+
+module_init(hw_test_init);
+module_exit(hw_test_exit);
-- 
1.7.12.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH update 2/3] x86: Delete too many "Fast TSC .." in dmesg from HW_latency cyclic sampling
  2012-11-11  2:48 [PATCH update 0/3] HW-latency: hardware latency test 0.10 Luming Yu
  2012-11-11  2:48 ` [PATCH update 1/3] " Luming Yu
@ 2012-11-11  2:48 ` Luming Yu
  2012-11-11  2:48 ` [PATCH update 3/3] fs: Fix crash caused by write to dummy debugfs interface like HW_latency exposed Luming Yu
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Luming Yu @ 2012-11-11  2:48 UTC (permalink / raw)
  To: arnd, linux-kernel
  Cc: Luming Yu, Jon Masters, Jon Masters, H. Peter Anvin, Luming Yu

"Fast TSC calibration using PIT" should be a devel info.

Signed-off-by: Luming Yu <luming.yu@intel.com>
---
 arch/x86/kernel/tsc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index cfa5d4f..7765546 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -393,7 +393,7 @@ success:
 	 */
 	delta *= PIT_TICK_RATE;
 	do_div(delta, i*256*1000);
-	pr_info("Fast TSC calibration using PIT\n");
+	pr_devel("Fast TSC calibration using PIT\n");
 	return delta;
 }
 
-- 
1.7.12.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH update 3/3] fs: Fix crash caused by write to dummy debugfs interface like HW_latency exposed
  2012-11-11  2:48 [PATCH update 0/3] HW-latency: hardware latency test 0.10 Luming Yu
  2012-11-11  2:48 ` [PATCH update 1/3] " Luming Yu
  2012-11-11  2:48 ` [PATCH update 2/3] x86: Delete too many "Fast TSC .." in dmesg from HW_latency cyclic sampling Luming Yu
@ 2012-11-11  2:48 ` Luming Yu
  2012-11-11  8:23 ` [PATCH update 0/3] HW-latency: hardware latency test 0.10 Chen Gong
  2012-11-12  4:13 ` Jon Masters
  4 siblings, 0 replies; 9+ messages in thread
From: Luming Yu @ 2012-11-11  2:48 UTC (permalink / raw)
  To: arnd, linux-kernel
  Cc: Luming Yu, Jon Masters, Jon Masters, Greg Kroah-Hartman, Luming Yu

[  141.311906] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
[  141.314071] IP: [<ffffffff811f8f3c>] simple_attr_write+0x2c/0x100
[  141.316195] PGD c3bd7067 PUD cb41d067 PMD 0
[  141.318287] Oops: 0000 [#1] SMP
[  141.320338] Modules linked in: hw_latency_test lockd sunrpc iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack rfcomm bnep coretemp kvm arc4 iwldvm mac80211 snd_hda_codec_hdmi snd_hda_codec_realtek option usb_wwan snd_hda_intel snd_hda_codec btusb bluetooth snd_hwdep snd_seq snd_seq_device snd_pcm iwlwifi thinkpad_acpi cfg80211 snd_page_alloc snd_timer crc32c_intel snd e1000e tpm_tis ghash_clmulni_intel tpm tpm_bios soundcore iTCO_wdt rfkill joydev microcode i2c_i801 wmi iTCO_vendor_support mei lpc_ich mfd_core pcspkr uinput i915 usb_storage i2c_algo_bit uas drm_kms_helper sdhci_pci sdhci drm mmc_core i2c_core video
[  141.329446] CPU 2
[  141.329467] Pid: 804, comm: bash Not tainted 3.7.0-rc2+ #5 LENOVO 232045C/232045C
[  141.333922] RIP: 0010:[<ffffffff811f8f3c>]  [<ffffffff811f8f3c>] simple_attr_write+0x2c/0x100
[  141.336173] RSP: 0018:ffff8800cb6c3eb8  EFLAGS: 00010286
[  141.338377] RAX: ffffffff811f8f10 RBX: ffff8800c4549600 RCX: ffff8800cb6c3f50
[  141.340573] RDX: 0000000000000002 RSI: 00007fcbf9ef0000 RDI: ffff8800c4549600
[  141.342744] RBP: ffff8800cb6c3ef8 R08: 000000000000000a R09: 00007fcbf9edd740
[  141.344896] R10: 0000000000000001 R11: 0000000000000246 R12: 0000000000000002
[  141.347017] R13: 00007fcbf9ef0000 R14: ffff8800cb6c3f50 R15: 0000000000000000
[  141.349115] FS:  00007fcbf9edd740(0000) GS:ffff880119200000(0000) knlGS:0000000000000000
[  141.351209] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  141.353314] CR2: 0000000000000008 CR3: 00000000c696c000 CR4: 00000000001407e0
[  141.355457] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  141.357590] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[  141.359685] Process bash (pid: 804, threadinfo ffff8800cb6c2000, task ffff8800cb7ccd20)
[  141.361767] Stack:
[  141.363793]  ffff8800c4549600 00007fcbf9ef0000 ffff8800cb6c3ef8 ffff8800c4549600
[  141.365864]  0000000000000002 00007fcbf9ef0000 ffff8800cb6c3f50 0000000000000000
[  141.367905]  ffff8800cb6c3f28 ffffffff811cf27f ffff8800c4549600 00007fcbf9ef0000
[  141.369924] Call Trace:
[  141.371882]  [<ffffffff811cf27f>] vfs_write+0xaf/0x190
[  141.373827]  [<ffffffff811cf5d5>] sys_write+0x55/0xa0
[  141.375745]  [<ffffffff816f0199>] system_call_fastpath+0x16/0x1b
[  141.377661] Code: 1f 44 00 00 55 48 89 e5 48 83 ec 40 48 89 5d d8 4c 89 65 e0 4c 89 6d e8 4c 89 75 f0 4c 89 7d f8 4c 8b bf 28 01 00 00 48 89 75 c8 <49> 83 7f 08 00 0f 84 b1 00 00 00 4d 8d 67 50 31 f6 49 89 d5 4c
[  141.382206] RIP  [<ffffffff811f8f3c>] simple_attr_write+0x2c/0x100
[  141.384326]  RSP <ffff8800cb6c3eb8>
[  141.386401] CR2: 0000000000000008
[  141.388548] ---[ end trace 9c28eee46fcb7871 ]---

Signed-off-by: Luming Yu <luming.yu@intel.com>
---
 fs/libfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/libfs.c b/fs/libfs.c
index 7cc37ca..bc51574 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -819,7 +819,7 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
 	ssize_t ret;
 
 	attr = file->private_data;
-	if (!attr->set)
+	if (!attr || !attr->set)
 		return -EACCES;
 
 	ret = mutex_lock_interruptible(&attr->mutex);
-- 
1.7.12.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH update 0/3] HW-latency: hardware latency test 0.10
  2012-11-11  2:48 [PATCH update 0/3] HW-latency: hardware latency test 0.10 Luming Yu
                   ` (2 preceding siblings ...)
  2012-11-11  2:48 ` [PATCH update 3/3] fs: Fix crash caused by write to dummy debugfs interface like HW_latency exposed Luming Yu
@ 2012-11-11  8:23 ` Chen Gong
  2012-11-12  4:13 ` Jon Masters
  4 siblings, 0 replies; 9+ messages in thread
From: Chen Gong @ 2012-11-11  8:23 UTC (permalink / raw)
  To: Luming Yu; +Cc: arnd, linux-kernel, Jon Masters, Jon Masters

[-- Attachment #1: Type: text/plain, Size: 1808 bytes --]

On Sat, Nov 10, 2012 at 09:48:19PM -0500, Luming Yu wrote:
> Date:	Sat, 10 Nov 2012 21:48:19 -0500
> From: Luming Yu <luming.yu@gmail.com>
> To: arnd@arndb.de, linux-kernel@vger.kernel.org
> Cc: Luming Yu <luming.yu@gmail.com>, Jon Masters <jonathan@jonmasters.org>,
>  Jon Masters <jcm@redhat.com>
> Subject: [PATCH update 0/3] HW-latency: hardware latency test 0.10
> X-Mailer: git-send-email 1.7.12.1
> 
> Update the previous patch series to ACK all comments I've recevied so far
> for the tool: e.g. 1.Acked Jon Masters in source code as many code are from
> jcm, thanks very much Jon. 2. squashed all changes against new file I added into
> one. 3. Make it useful on non-x86.
> 
> Please review and commit to misc tree. I will update the patch series if anyone
> has anymore comments.
> 
> Thanks very much!!!
>  
> Luming Yu (3):
>   HW-latency: hardware latency test 0.10
>   x86: Delete too many "Fast TSC .." in dmesg from HW_latency cyclic
>     sampling
>   fs: Fix crash caused by write to dummy debugfs interface like
>     HW_latency exposed
> 
>  arch/x86/kernel/tsc.c          |   2 +-
>  drivers/misc/Kconfig           |   6 +
>  drivers/misc/Makefile          |   1 +
>  drivers/misc/hw_latency_test.c | 939 +++++++++++++++++++++++++++++++++++++++++
>  fs/libfs.c                     |   2 +-
>  5 files changed, 948 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/misc/hw_latency_test.c
> 
> -- 
> 1.7.12.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>
Hi, Luming

Would you please send the first patch to LKML, too?

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH update 0/3] HW-latency: hardware latency test 0.10
  2012-11-11  2:48 [PATCH update 0/3] HW-latency: hardware latency test 0.10 Luming Yu
                   ` (3 preceding siblings ...)
  2012-11-11  8:23 ` [PATCH update 0/3] HW-latency: hardware latency test 0.10 Chen Gong
@ 2012-11-12  4:13 ` Jon Masters
  2012-11-18  9:30   ` Luming Yu
  4 siblings, 1 reply; 9+ messages in thread
From: Jon Masters @ 2012-11-12  4:13 UTC (permalink / raw)
  To: Luming Yu; +Cc: arnd, linux-kernel, Jon Masters

On 11/10/2012 09:48 PM, Luming Yu wrote:

> Update the previous patch series to ACK all comments I've recevied so far
> for the tool: e.g. 1.Acked Jon Masters in source code as many code are from
> jcm, thanks very much Jon. 2. squashed all changes against new file I added into
> one. 3. Make it useful on non-x86.

Thanks for taking this and doing the heavy lifting to get it upstream! I
wrote the original SMI detector really for RT debug purposes as we had
OEM systems that would generate large latencies and it was easier to
prove the point with nice graphs showing where the BIOS was injecting
unwanted SMIs. Glad to see the work being done to make it more generic
in nature. Maybe I'll come back with some ARM patches ;)

Actually this exercise was very informative because it has helped shape
my input on ARMv8 designs. I'm very keen to get away from a world in
which world+dog feature is implemented inside an SMI-like context. It
should be done via a dedicated management processor (on-chip) instead.

Jon.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH update 0/3] HW-latency: hardware latency test 0.10
  2012-11-12  4:13 ` Jon Masters
@ 2012-11-18  9:30   ` Luming Yu
  2012-11-19  7:30     ` Jon Masters
  0 siblings, 1 reply; 9+ messages in thread
From: Luming Yu @ 2012-11-18  9:30 UTC (permalink / raw)
  To: arnd, Jon Masters; +Cc: linux-kernel, Jon Masters, H. Peter Anvin

On Mon, Nov 12, 2012 at 12:13 PM, Jon Masters <jcm@redhat.com> wrote:
> On 11/10/2012 09:48 PM, Luming Yu wrote:
>
>> Update the previous patch series to ACK all comments I've recevied so far
>> for the tool: e.g. 1.Acked Jon Masters in source code as many code are from
>> jcm, thanks very much Jon. 2. squashed all changes against new file I added into
>> one. 3. Make it useful on non-x86.
>
> Thanks for taking this and doing the heavy lifting to get it upstream! I
> wrote the original SMI detector really for RT debug purposes as we had
> OEM systems that would generate large latencies and it was easier to
> prove the point with nice graphs showing where the BIOS was injecting
> unwanted SMIs. Glad to see the work being done to make it more generic
> in nature. Maybe I'll come back with some ARM patches ;)
>
> Actually this exercise was very informative because it has helped shape
> my input on ARMv8 designs. I'm very keen to get away from a world in
> which world+dog feature is implemented inside an SMI-like context. It
> should be done via a dedicated management processor (on-chip) instead.
>
> Jon.
>

thanks Jon,

ping Arnd,  would you take this into your tree?

The value is when the feature finally done, we can finally have a
reliable tool  to count on for automatically sorting out hardware
problems and differences that really matter to designing your software
stack on bare metal, which means a lot to many of us dedicated to
hardware development/enabling as a software engineer, especially when
you have two similar platforms and need to rule out hardware latency
that could be the root cause.. in many case, people would have to dig
into various specs and lost...

I'd be glad to do anything to push this tool into upstream.  Please
let me know your thoughts. Thanks !!!! /l

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH update 0/3] HW-latency: hardware latency test 0.10
  2012-11-18  9:30   ` Luming Yu
@ 2012-11-19  7:30     ` Jon Masters
  2012-11-27  2:43       ` Luming Yu
  0 siblings, 1 reply; 9+ messages in thread
From: Jon Masters @ 2012-11-19  7:30 UTC (permalink / raw)
  To: Luming Yu; +Cc: arnd, linux-kernel, Jon Masters, H. Peter Anvin

On 11/18/2012 04:30 AM, Luming Yu wrote:

> I'd be glad to do anything to push this tool into upstream.  Please
> let me know your thoughts. Thanks !!!! /l

I'm also happy to help test. I'll take a look over the TG holiday at
your latest version.

Jon.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH update 0/3] HW-latency: hardware latency test 0.10
  2012-11-19  7:30     ` Jon Masters
@ 2012-11-27  2:43       ` Luming Yu
  0 siblings, 0 replies; 9+ messages in thread
From: Luming Yu @ 2012-11-27  2:43 UTC (permalink / raw)
  To: Jon Masters, H. Peter Anvin; +Cc: arnd, linux-kernel, Jon Masters

On Mon, Nov 19, 2012 at 3:30 PM, Jon Masters <jcm@redhat.com> wrote:
> On 11/18/2012 04:30 AM, Luming Yu wrote:
>
>> I'd be glad to do anything to push this tool into upstream.  Please
>> let me know your thoughts. Thanks !!!! /l
>
> I'm also happy to help test. I'll take a look over the TG holiday at
> your latest version.
>

if we can make the tool upstream,  probably we can ask more people to test.
But not sure if arand is interested in this work anymore although he
gave the work
detailed review back to July , thanks Arand...
To push the patch upstream, l'd like to ping you again.

But if other maintainers also interested in the feature, I'd be very
glad to work with them.

Hello Peter,  would you like to take this tool to upstream?

Regards /l

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-11-27  2:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-11  2:48 [PATCH update 0/3] HW-latency: hardware latency test 0.10 Luming Yu
2012-11-11  2:48 ` [PATCH update 1/3] " Luming Yu
2012-11-11  2:48 ` [PATCH update 2/3] x86: Delete too many "Fast TSC .." in dmesg from HW_latency cyclic sampling Luming Yu
2012-11-11  2:48 ` [PATCH update 3/3] fs: Fix crash caused by write to dummy debugfs interface like HW_latency exposed Luming Yu
2012-11-11  8:23 ` [PATCH update 0/3] HW-latency: hardware latency test 0.10 Chen Gong
2012-11-12  4:13 ` Jon Masters
2012-11-18  9:30   ` Luming Yu
2012-11-19  7:30     ` Jon Masters
2012-11-27  2:43       ` Luming Yu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).