diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace_mmiotrace.c | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c index 79be4a18ec1e..6d2edbdde939 100644 --- a/kernel/trace/trace_mmiotrace.c +++ b/kernel/trace/trace_mmiotrace.c | |||
@@ -12,6 +12,10 @@ | |||
12 | 12 | ||
13 | #include "trace.h" | 13 | #include "trace.h" |
14 | 14 | ||
15 | struct header_iter { | ||
16 | struct pci_dev *dev; | ||
17 | }; | ||
18 | |||
15 | static struct trace_array *mmio_trace_array; | 19 | static struct trace_array *mmio_trace_array; |
16 | 20 | ||
17 | static void mmio_reset_data(struct trace_array *tr) | 21 | static void mmio_reset_data(struct trace_array *tr) |
@@ -89,17 +93,57 @@ static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev) | |||
89 | return ret; | 93 | return ret; |
90 | } | 94 | } |
91 | 95 | ||
92 | /* XXX: This is not called for trace_pipe file! */ | 96 | static void destroy_header_iter(struct header_iter *hiter) |
93 | static void mmio_print_header(struct trace_iterator *iter) | 97 | { |
98 | if (!hiter) | ||
99 | return; | ||
100 | pci_dev_put(hiter->dev); | ||
101 | kfree(hiter); | ||
102 | } | ||
103 | |||
104 | static void mmio_pipe_open(struct trace_iterator *iter) | ||
94 | { | 105 | { |
106 | struct header_iter *hiter; | ||
95 | struct trace_seq *s = &iter->seq; | 107 | struct trace_seq *s = &iter->seq; |
96 | struct pci_dev *dev = NULL; | ||
97 | 108 | ||
98 | trace_seq_printf(s, "VERSION 20070824\n"); | 109 | trace_seq_printf(s, "VERSION 20070824\n"); |
99 | 110 | ||
100 | for_each_pci_dev(dev) | 111 | hiter = kzalloc(sizeof(*hiter), GFP_KERNEL); |
101 | mmio_print_pcidev(s, dev); | 112 | if (!hiter) |
102 | /* XXX: return value? What if header is very long? */ | 113 | return; |
114 | |||
115 | hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); | ||
116 | iter->private = hiter; | ||
117 | } | ||
118 | |||
119 | /* XXX: This is not called when the pipe is closed! */ | ||
120 | static void mmio_close(struct trace_iterator *iter) | ||
121 | { | ||
122 | struct header_iter *hiter = iter->private; | ||
123 | destroy_header_iter(hiter); | ||
124 | iter->private = NULL; | ||
125 | } | ||
126 | |||
127 | static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp, | ||
128 | char __user *ubuf, size_t cnt, loff_t *ppos) | ||
129 | { | ||
130 | ssize_t ret; | ||
131 | struct header_iter *hiter = iter->private; | ||
132 | struct trace_seq *s = &iter->seq; | ||
133 | |||
134 | if (!hiter) | ||
135 | return 0; | ||
136 | |||
137 | mmio_print_pcidev(s, hiter->dev); | ||
138 | hiter->dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, hiter->dev); | ||
139 | |||
140 | if (!hiter->dev) { | ||
141 | destroy_header_iter(hiter); | ||
142 | iter->private = NULL; | ||
143 | } | ||
144 | |||
145 | ret = trace_seq_to_user(s, ubuf, cnt); | ||
146 | return (ret == -EBUSY) ? 0 : ret; | ||
103 | } | 147 | } |
104 | 148 | ||
105 | static int mmio_print_rw(struct trace_iterator *iter) | 149 | static int mmio_print_rw(struct trace_iterator *iter) |
@@ -190,7 +234,9 @@ static struct tracer mmio_tracer __read_mostly = | |||
190 | .name = "mmiotrace", | 234 | .name = "mmiotrace", |
191 | .init = mmio_trace_init, | 235 | .init = mmio_trace_init, |
192 | .reset = mmio_trace_reset, | 236 | .reset = mmio_trace_reset, |
193 | .open = mmio_print_header, | 237 | .pipe_open = mmio_pipe_open, |
238 | .close = mmio_close, | ||
239 | .read = mmio_read, | ||
194 | .ctrl_update = mmio_trace_ctrl_update, | 240 | .ctrl_update = mmio_trace_ctrl_update, |
195 | .print_line = mmio_print_line, | 241 | .print_line = mmio_print_line, |
196 | }; | 242 | }; |