aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2011-01-07 20:46:25 -0500
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2011-01-12 19:29:35 -0500
commit37eb46be881dde4b405d3d8b48e76b4a8d62ae2c (patch)
treeaab617d44f19114ecc9ea7cf7e1d64ee35430005
parent7648363e5636bd865aeac3236eb4675f0687eb4a (diff)
Feather-Trace: register devices with sysfs
This patch implements support for Feather-Trace devices to use the sysfs file system and, consequently, udev support. This allows us to allocate major/minor numbers for Feather-Trace devices dynamically, which is desirable because our old static allocations tend to create conflicts on modern distributions and/or when there are many cores.
-rw-r--r--include/litmus/ftdev.h7
-rw-r--r--litmus/ftdev.c65
-rw-r--r--litmus/sched_task_trace.c6
-rw-r--r--litmus/trace.c7
4 files changed, 56 insertions, 29 deletions
diff --git a/include/litmus/ftdev.h b/include/litmus/ftdev.h
index 7697b4616699..efb2a5c9a9b0 100644
--- a/include/litmus/ftdev.h
+++ b/include/litmus/ftdev.h
@@ -28,10 +28,13 @@ struct ftdev_minor {
28 struct mutex lock; 28 struct mutex lock;
29 /* FIXME: filter for authorized events */ 29 /* FIXME: filter for authorized events */
30 struct ftdev_event* events; 30 struct ftdev_event* events;
31 struct device* device;
31}; 32};
32 33
33struct ftdev { 34struct ftdev {
34 struct cdev cdev; 35 struct cdev cdev;
36 struct class* class;
37 const char* name;
35 /* FIXME: don't waste memory, allocate dynamically */ 38 /* FIXME: don't waste memory, allocate dynamically */
36 struct ftdev_minor minor[MAX_FTDEV_MINORS]; 39 struct ftdev_minor minor[MAX_FTDEV_MINORS];
37 unsigned int minor_cnt; 40 unsigned int minor_cnt;
@@ -43,7 +46,7 @@ struct ftdev {
43struct ft_buffer* alloc_ft_buffer(unsigned int count, size_t size); 46struct ft_buffer* alloc_ft_buffer(unsigned int count, size_t size);
44void free_ft_buffer(struct ft_buffer* buf); 47void free_ft_buffer(struct ft_buffer* buf);
45 48
46void ftdev_init(struct ftdev* ftdev, struct module* owner); 49void ftdev_init(struct ftdev* ftdev, struct module* owner, const char* name);
47int register_ftdev(struct ftdev* ftdev, const char* name, int major); 50int register_ftdev(struct ftdev* ftdev);
48 51
49#endif 52#endif
diff --git a/litmus/ftdev.c b/litmus/ftdev.c
index 51dafaebf8a6..d68d05c6d7dc 100644
--- a/litmus/ftdev.c
+++ b/litmus/ftdev.c
@@ -4,6 +4,7 @@
4#include <linux/cdev.h> 4#include <linux/cdev.h>
5#include <asm/uaccess.h> 5#include <asm/uaccess.h>
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/device.h>
7 8
8#include <litmus/litmus.h> 9#include <litmus/litmus.h>
9#include <litmus/feather_trace.h> 10#include <litmus/feather_trace.h>
@@ -310,10 +311,11 @@ struct file_operations ftdev_fops = {
310}; 311};
311 312
312 313
313void ftdev_init(struct ftdev* ftdev, struct module* owner) 314void ftdev_init(struct ftdev* ftdev, struct module* owner, const char* name)
314{ 315{
315 int i; 316 int i, error;
316 cdev_init(&ftdev->cdev, &ftdev_fops); 317 cdev_init(&ftdev->cdev, &ftdev_fops);
318 ftdev->name = name;
317 ftdev->cdev.owner = owner; 319 ftdev->cdev.owner = owner;
318 ftdev->cdev.ops = &ftdev_fops; 320 ftdev->cdev.ops = &ftdev_fops;
319 ftdev->minor_cnt = 0; 321 ftdev->minor_cnt = 0;
@@ -326,35 +328,62 @@ void ftdev_init(struct ftdev* ftdev, struct module* owner)
326 ftdev->alloc = NULL; 328 ftdev->alloc = NULL;
327 ftdev->free = NULL; 329 ftdev->free = NULL;
328 ftdev->can_open = NULL; 330 ftdev->can_open = NULL;
331
332 ftdev->class = class_create(owner, ftdev->name);
333 if (IS_ERR(ftdev->class)) {
334 error = PTR_ERR(ftdev->class);
335 printk(KERN_WARNING "ftdev(%s): "
336 "Could not create device class.\n",
337 name);
338 }
329} 339}
330 340
331int register_ftdev(struct ftdev* ftdev, const char* name, int major) 341int register_ftdev(struct ftdev* ftdev)
332{ 342{
343 struct device **device;
333 dev_t trace_dev; 344 dev_t trace_dev;
334 int error = 0; 345 int error = 0, major, i;
335 346
336 if(major) { 347 error = alloc_chrdev_region(&trace_dev, 0, ftdev->minor_cnt,
337 trace_dev = MKDEV(major, 0); 348 ftdev->name);
338 error = register_chrdev_region(trace_dev, ftdev->minor_cnt, 349 major = MAJOR(trace_dev);
339 name);
340 } else {
341 error = alloc_chrdev_region(&trace_dev, 0, ftdev->minor_cnt,
342 name);
343 major = MAJOR(trace_dev);
344 }
345 if (error) 350 if (error)
346 { 351 {
347 printk(KERN_WARNING "ftdev(%s): " 352 printk(KERN_WARNING "ftdev(%s): "
348 "Could not register major/minor number %d/%u\n", 353 "Could not register major/minor number %d/%u\n",
349 name, major, ftdev->minor_cnt); 354 ftdev->name, major, ftdev->minor_cnt);
350 return error; 355 goto out;
351 } 356 }
352 error = cdev_add(&ftdev->cdev, trace_dev, ftdev->minor_cnt); 357 error = cdev_add(&ftdev->cdev, trace_dev, ftdev->minor_cnt);
353 if (error) { 358 if (error) {
354 printk(KERN_WARNING "ftdev(%s): " 359 printk(KERN_WARNING "ftdev(%s): "
355 "Could not add cdev for major/minor = %d/%u.\n", 360 "Could not add cdev for major/minor = %d/%u.\n",
356 name, major, ftdev->minor_cnt); 361 ftdev->name, major, ftdev->minor_cnt);
357 return error; 362 goto out;
363 }
364
365 /*
366 * create all the minor devices
367 */
368 for (i = 0; i < ftdev->minor_cnt; ++i)
369 {
370 trace_dev = MKDEV(major, i);
371 device = &(ftdev->minor[i].device);
372
373 *device = device_create(ftdev->class, NULL, trace_dev, NULL,
374 "%s%d", ftdev->name, i);
375 if (IS_ERR(*device)) {
376 error = PTR_ERR(*device);
377 printk(KERN_WARNING "ftdev(%s): "
378 "Could not create device major/minor number "
379 "%d/%d\n", ftdev->name, major, i);
380 printk(KERN_WARNING "ftdev(%s): "
381 "Will not continue creating devices. Tracing "
382 "may be in an inconsistent state.\n",
383 ftdev->name);
384 goto out;
385 }
358 } 386 }
387out:
359 return error; 388 return error;
360} 389}
diff --git a/litmus/sched_task_trace.c b/litmus/sched_task_trace.c
index e5098ddb1ec9..7ef7b2889b42 100644
--- a/litmus/sched_task_trace.c
+++ b/litmus/sched_task_trace.c
@@ -16,8 +16,6 @@
16#include <litmus/ftdev.h> 16#include <litmus/ftdev.h>
17 17
18 18
19/* set MAJOR to 0 to have it dynamically assigned */
20#define FT_TASK_TRACE_MAJOR 253
21#define NO_EVENTS (1 << CONFIG_SCHED_TASK_TRACE_SHIFT) 19#define NO_EVENTS (1 << CONFIG_SCHED_TASK_TRACE_SHIFT)
22 20
23#define now() litmus_clock() 21#define now() litmus_clock()
@@ -44,7 +42,7 @@ static int __init init_sched_task_trace(void)
44 printk("Allocated %u sched_trace_xxx() events per CPU " 42 printk("Allocated %u sched_trace_xxx() events per CPU "
45 "(buffer size: %d bytes)\n", 43 "(buffer size: %d bytes)\n",
46 NO_EVENTS, (int) sizeof(struct local_buffer)); 44 NO_EVENTS, (int) sizeof(struct local_buffer));
47 ftdev_init(&st_dev, THIS_MODULE); 45 ftdev_init(&st_dev, THIS_MODULE, "sched_trace");
48 for (i = 0; i < NR_CPUS; i++) { 46 for (i = 0; i < NR_CPUS; i++) {
49 buf = &per_cpu(st_event_buffer, i); 47 buf = &per_cpu(st_event_buffer, i);
50 ok += init_ft_buffer(&buf->ftbuf, NO_EVENTS, 48 ok += init_ft_buffer(&buf->ftbuf, NO_EVENTS,
@@ -56,7 +54,7 @@ static int __init init_sched_task_trace(void)
56 if (ok == NR_CPUS) { 54 if (ok == NR_CPUS) {
57 st_dev.minor_cnt = NR_CPUS; 55 st_dev.minor_cnt = NR_CPUS;
58 st_dev.can_open = st_dev_can_open; 56 st_dev.can_open = st_dev_can_open;
59 return register_ftdev(&st_dev, "sched_trace", FT_TASK_TRACE_MAJOR); 57 return register_ftdev(&st_dev);
60 } else { 58 } else {
61 return -EINVAL; 59 return -EINVAL;
62 } 60 }
diff --git a/litmus/trace.c b/litmus/trace.c
index b3a6b47aad6e..da650dfe7f4d 100644
--- a/litmus/trace.c
+++ b/litmus/trace.c
@@ -71,9 +71,6 @@ feather_callback void save_timestamp_cpu(unsigned long event,
71 */ 71 */
72#define NO_TIMESTAMPS (2 << 11) 72#define NO_TIMESTAMPS (2 << 11)
73 73
74/* set MAJOR to 0 to have it dynamically assigned */
75#define FT_TRACE_MAJOR 252
76
77static int alloc_timestamp_buffer(struct ftdev* ftdev, unsigned int idx) 74static int alloc_timestamp_buffer(struct ftdev* ftdev, unsigned int idx)
78{ 75{
79 unsigned int count = NO_TIMESTAMPS; 76 unsigned int count = NO_TIMESTAMPS;
@@ -94,11 +91,11 @@ static void free_timestamp_buffer(struct ftdev* ftdev, unsigned int idx)
94static int __init init_ft_overhead_trace(void) 91static int __init init_ft_overhead_trace(void)
95{ 92{
96 printk("Initializing Feather-Trace overhead tracing device.\n"); 93 printk("Initializing Feather-Trace overhead tracing device.\n");
97 ftdev_init(&overhead_dev, THIS_MODULE); 94 ftdev_init(&overhead_dev, THIS_MODULE, "ft_trace");
98 overhead_dev.minor_cnt = 1; /* only one buffer */ 95 overhead_dev.minor_cnt = 1; /* only one buffer */
99 overhead_dev.alloc = alloc_timestamp_buffer; 96 overhead_dev.alloc = alloc_timestamp_buffer;
100 overhead_dev.free = free_timestamp_buffer; 97 overhead_dev.free = free_timestamp_buffer;
101 return register_ftdev(&overhead_dev, "ft_trace", FT_TRACE_MAJOR); 98 return register_ftdev(&overhead_dev);
102} 99}
103 100
104module_init(init_ft_overhead_trace); 101module_init(init_ft_overhead_trace);