diff options
author | Pawel Moll | 2011-09-30 05:47:12 -0500 |
---|---|---|
committer | Pawel Moll | 2011-09-30 05:47:12 -0500 |
commit | 1d5b785dbabac2dfc45103e7c2d787952c93488c (patch) | |
tree | e03426ecb18855bb05af48a811e619cc26eb2f3b /driver/gator_events_block.c | |
parent | 7c366b2d106bd14742cc3446f874e520d473703d (diff) | |
download | arm-ds5-gator-1d5b785dbabac2dfc45103e7c2d787952c93488c.tar.gz arm-ds5-gator-1d5b785dbabac2dfc45103e7c2d787952c93488c.tar.xz arm-ds5-gator-1d5b785dbabac2dfc45103e7c2d787952c93488c.zip |
gator: Move driver sources to a separate directory
... in prepration for daemon sources.
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Diffstat (limited to 'driver/gator_events_block.c')
-rw-r--r-- | driver/gator_events_block.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c new file mode 100644 index 0000000..cbfed86 --- /dev/null +++ b/driver/gator_events_block.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /** | ||
2 | * Copyright (C) ARM Limited 2010-2011. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include "gator.h" | ||
11 | #include <trace/events/block.h> | ||
12 | |||
13 | #define BLOCK_RQ_WR 0 | ||
14 | #define BLOCK_RQ_RD 1 | ||
15 | |||
16 | #define BLOCK_TOTAL (BLOCK_RQ_RD+1) | ||
17 | |||
18 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) | ||
19 | #define EVENTWRITE REQ_RW | ||
20 | #else | ||
21 | #define EVENTWRITE REQ_WRITE | ||
22 | #endif | ||
23 | |||
24 | static ulong block_rq_wr_enabled; | ||
25 | static ulong block_rq_rd_enabled; | ||
26 | static ulong block_rq_wr_key; | ||
27 | static ulong block_rq_rd_key; | ||
28 | static DEFINE_PER_CPU(int[BLOCK_TOTAL], blockCnt); | ||
29 | static DEFINE_PER_CPU(int[BLOCK_TOTAL * 2], blockGet); | ||
30 | static DEFINE_PER_CPU(bool, new_data_avail); | ||
31 | |||
32 | GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq)) | ||
33 | { | ||
34 | unsigned long flags; | ||
35 | int write, size; | ||
36 | int cpu = smp_processor_id(); | ||
37 | |||
38 | if (!rq) | ||
39 | return; | ||
40 | |||
41 | write = rq->cmd_flags & EVENTWRITE; | ||
42 | size = rq->resid_len; | ||
43 | |||
44 | if (!size) | ||
45 | return; | ||
46 | |||
47 | // disable interrupts to synchronize with gator_events_block_read() | ||
48 | // spinlocks not needed since percpu buffers are used | ||
49 | local_irq_save(flags); | ||
50 | if (write) | ||
51 | per_cpu(blockCnt, cpu)[BLOCK_RQ_WR] += size; | ||
52 | else | ||
53 | per_cpu(blockCnt, cpu)[BLOCK_RQ_RD] += size; | ||
54 | local_irq_restore(flags); | ||
55 | |||
56 | per_cpu(new_data_avail, cpu) = true; | ||
57 | } | ||
58 | |||
59 | static int gator_events_block_create_files(struct super_block *sb, struct dentry *root) | ||
60 | { | ||
61 | struct dentry *dir; | ||
62 | |||
63 | /* block_complete_wr */ | ||
64 | dir = gatorfs_mkdir(sb, root, "Linux_block_rq_wr"); | ||
65 | if (!dir) { | ||
66 | return -1; | ||
67 | } | ||
68 | gatorfs_create_ulong(sb, dir, "enabled", &block_rq_wr_enabled); | ||
69 | gatorfs_create_ro_ulong(sb, dir, "key", &block_rq_wr_key); | ||
70 | |||
71 | /* block_complete_rd */ | ||
72 | dir = gatorfs_mkdir(sb, root, "Linux_block_rq_rd"); | ||
73 | if (!dir) { | ||
74 | return -1; | ||
75 | } | ||
76 | gatorfs_create_ulong(sb, dir, "enabled", &block_rq_rd_enabled); | ||
77 | gatorfs_create_ro_ulong(sb, dir, "key", &block_rq_rd_key); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int gator_events_block_start(void) | ||
83 | { | ||
84 | int cpu; | ||
85 | |||
86 | for_each_present_cpu(cpu) | ||
87 | per_cpu(new_data_avail, cpu) = true; | ||
88 | |||
89 | // register tracepoints | ||
90 | if (block_rq_wr_enabled || block_rq_rd_enabled) | ||
91 | if (GATOR_REGISTER_TRACE(block_rq_complete)) | ||
92 | goto fail_block_rq_exit; | ||
93 | pr_debug("gator: registered block event tracepoints\n"); | ||
94 | |||
95 | return 0; | ||
96 | |||
97 | // unregister tracepoints on error | ||
98 | fail_block_rq_exit: | ||
99 | pr_err("gator: block event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); | ||
100 | |||
101 | return -1; | ||
102 | } | ||
103 | |||
104 | static void gator_events_block_stop(void) | ||
105 | { | ||
106 | if (block_rq_wr_enabled || block_rq_rd_enabled) | ||
107 | GATOR_UNREGISTER_TRACE(block_rq_complete); | ||
108 | pr_debug("gator: unregistered block event tracepoints\n"); | ||
109 | |||
110 | block_rq_wr_enabled = 0; | ||
111 | block_rq_rd_enabled = 0; | ||
112 | } | ||
113 | |||
114 | static int gator_events_block_read(int **buffer) | ||
115 | { | ||
116 | unsigned long flags; | ||
117 | int len, value, cpu, data = 0; | ||
118 | cpu = smp_processor_id(); | ||
119 | |||
120 | if (per_cpu(new_data_avail, cpu) == false) | ||
121 | return 0; | ||
122 | |||
123 | per_cpu(new_data_avail, cpu) = false; | ||
124 | |||
125 | len = 0; | ||
126 | if (block_rq_wr_enabled) { | ||
127 | local_irq_save(flags); | ||
128 | value = per_cpu(blockCnt, cpu)[BLOCK_RQ_WR]; | ||
129 | per_cpu(blockCnt, cpu)[BLOCK_RQ_WR] = 0; | ||
130 | local_irq_restore(flags); | ||
131 | per_cpu(blockGet, cpu)[len++] = block_rq_wr_key; | ||
132 | per_cpu(blockGet, cpu)[len++] = value; | ||
133 | data += value; | ||
134 | } | ||
135 | if (block_rq_rd_enabled) { | ||
136 | local_irq_save(flags); | ||
137 | value = per_cpu(blockCnt, cpu)[BLOCK_RQ_RD]; | ||
138 | per_cpu(blockCnt, cpu)[BLOCK_RQ_RD] = 0; | ||
139 | local_irq_restore(flags); | ||
140 | per_cpu(blockGet, cpu)[len++] = block_rq_rd_key; | ||
141 | per_cpu(blockGet, cpu)[len++] = value; | ||
142 | data += value; | ||
143 | } | ||
144 | |||
145 | if (data != 0) | ||
146 | per_cpu(new_data_avail, cpu) = true; | ||
147 | |||
148 | if (buffer) | ||
149 | *buffer = per_cpu(blockGet, cpu); | ||
150 | |||
151 | return len; | ||
152 | } | ||
153 | |||
154 | static struct gator_interface gator_events_block_interface = { | ||
155 | .create_files = gator_events_block_create_files, | ||
156 | .start = gator_events_block_start, | ||
157 | .stop = gator_events_block_stop, | ||
158 | .read = gator_events_block_read, | ||
159 | }; | ||
160 | |||
161 | int gator_events_block_init(void) | ||
162 | { | ||
163 | block_rq_wr_enabled = 0; | ||
164 | block_rq_rd_enabled = 0; | ||
165 | |||
166 | block_rq_wr_key = gator_events_get_key(); | ||
167 | block_rq_rd_key = gator_events_get_key(); | ||
168 | |||
169 | return gator_events_install(&gator_events_block_interface); | ||
170 | } | ||
171 | gator_events_init(gator_events_block_init); | ||