aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Kenna <cjk@cs.unc.edu>2011-01-07 20:46:25 -0500
committerChristopher Kenna <cjk@cs.unc.edu>2011-01-10 22:43:50 -0500
commit7b3808d96ac3778a7516b1eb9a02d7c3f85ccac0 (patch)
treee341045612d839bdef2fcde724de9a0c2a56415c
parent64ff1a907dca75efb5883b44378365f635c030ce (diff)
Preliminary udev support
This patch implements support for FeatherTrace devices to use the sysfs file system and, consequently, udev support. It also changed the FeatherTrace headers and API a bit. There is still more to do, including: - Verify that calling device_create() is the right thing to do (I think it is). - Testing! I noticed some failed FeatherTrace writes, but it was on a system with high utilization and in qemu, so it might be benign. - Remove created devices on system shutdown or module unregister. FeaterTrace never did this; probably not a huge issue if we don't. - Determine if we want to try and use a "root device" to group LITMUS^RT devices together. See the __root_device_register() function in drivers/base/core.c - Update documentation.
-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);