blob: 4129405d17c0fcbf2e29e7f14abfba6d6f077347 [file] [log] [blame]
Tomeu Vizoso9edbf1f2016-10-06 17:21:06 +02001/*
2 * Copyright © 2008 Intel Corporation
3 * Copyright © 2016 Collabora Ltd
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * Based on code from the i915 driver.
25 * Original author: Damien Lespiau <damien.lespiau@intel.com>
26 *
27 */
28
29#include <linux/circ_buf.h>
30#include <linux/ctype.h>
31#include <linux/debugfs.h>
32#include <drm/drmP.h>
33
34/**
35 * DOC: CRC ABI
36 *
37 * DRM device drivers can provide to userspace CRC information of each frame as
38 * it reached a given hardware component (a "source").
39 *
40 * Userspace can control generation of CRCs in a given CRTC by writing to the
41 * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC.
42 * Accepted values are source names (which are driver-specific) and the "auto"
43 * keyword, which will let the driver select a default source of frame CRCs
44 * for this CRTC.
45 *
46 * Once frame CRC generation is enabled, userspace can capture them by reading
47 * the dri/0/crtc-N/crc/data file. Each line in that file contains the frame
48 * number in the first field and then a number of unsigned integer fields
49 * containing the CRC data. Fields are separated by a single space and the number
50 * of CRC fields is source-specific.
51 *
52 * Note that though in some cases the CRC is computed in a specified way and on
53 * the frame contents as supplied by userspace (eDP 1.3), in general the CRC
54 * computation is performed in an unspecified way and on frame contents that have
55 * been already processed in also an unspecified way and thus userspace cannot
56 * rely on being able to generate matching CRC values for the frame contents that
57 * it submits. In this general case, the maximum userspace can do is to compare
58 * the reported CRCs of frames that should have the same contents.
59 */
60
61static int crc_control_show(struct seq_file *m, void *data)
62{
63 struct drm_crtc *crtc = m->private;
64
65 seq_printf(m, "%s\n", crtc->crc.source);
66
67 return 0;
68}
69
70static int crc_control_open(struct inode *inode, struct file *file)
71{
72 struct drm_crtc *crtc = inode->i_private;
73
74 return single_open(file, crc_control_show, crtc);
75}
76
77static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
78 size_t len, loff_t *offp)
79{
80 struct seq_file *m = file->private_data;
81 struct drm_crtc *crtc = m->private;
82 struct drm_crtc_crc *crc = &crtc->crc;
83 char *source;
84
85 if (len == 0)
86 return 0;
87
88 if (len > PAGE_SIZE - 1) {
89 DRM_DEBUG_KMS("Expected < %lu bytes into crtc crc control\n",
90 PAGE_SIZE);
91 return -E2BIG;
92 }
93
94 source = memdup_user_nul(ubuf, len);
95 if (IS_ERR(source))
96 return PTR_ERR(source);
97
98 if (source[len] == '\n')
99 source[len] = '\0';
100
101 spin_lock_irq(&crc->lock);
102
103 if (crc->opened) {
104 spin_unlock_irq(&crc->lock);
105 kfree(source);
106 return -EBUSY;
107 }
108
109 kfree(crc->source);
110 crc->source = source;
111
112 spin_unlock_irq(&crc->lock);
113
114 *offp += len;
115 return len;
116}
117
118const struct file_operations drm_crtc_crc_control_fops = {
119 .owner = THIS_MODULE,
120 .open = crc_control_open,
121 .read = seq_read,
122 .llseek = seq_lseek,
123 .release = single_release,
124 .write = crc_control_write
125};
126
127static int crtc_crc_open(struct inode *inode, struct file *filep)
128{
129 struct drm_crtc *crtc = inode->i_private;
130 struct drm_crtc_crc *crc = &crtc->crc;
131 struct drm_crtc_crc_entry *entries = NULL;
132 size_t values_cnt;
133 int ret;
134
135 if (crc->opened)
136 return -EBUSY;
137
138 ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt);
139 if (ret)
140 return ret;
141
142 if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) {
143 ret = -EINVAL;
144 goto err_disable;
145 }
146
147 if (WARN_ON(values_cnt == 0)) {
148 ret = -EINVAL;
149 goto err_disable;
150 }
151
152 entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL);
153 if (!entries) {
154 ret = -ENOMEM;
155 goto err_disable;
156 }
157
158 spin_lock_irq(&crc->lock);
159 crc->entries = entries;
160 crc->values_cnt = values_cnt;
161 crc->opened = true;
162 spin_unlock_irq(&crc->lock);
163
164 return 0;
165
166err_disable:
167 crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
168 return ret;
169}
170
171static int crtc_crc_release(struct inode *inode, struct file *filep)
172{
173 struct drm_crtc *crtc = filep->f_inode->i_private;
174 struct drm_crtc_crc *crc = &crtc->crc;
175 size_t values_cnt;
176
177 spin_lock_irq(&crc->lock);
178 kfree(crc->entries);
179 crc->entries = NULL;
180 crc->head = 0;
181 crc->tail = 0;
182 crc->values_cnt = 0;
183 crc->opened = false;
184 spin_unlock_irq(&crc->lock);
185
186 crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
187
188 return 0;
189}
190
191static int crtc_crc_data_count(struct drm_crtc_crc *crc)
192{
193 assert_spin_locked(&crc->lock);
194 return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR);
195}
196
197/*
198 * 1 frame field of 10 chars plus a number of CRC fields of 10 chars each, space
199 * separated, with a newline at the end and null-terminated.
200 */
201#define LINE_LEN(values_cnt) (10 + 11 * values_cnt + 1 + 1)
202#define MAX_LINE_LEN (LINE_LEN(DRM_MAX_CRC_NR))
203
204static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf,
205 size_t count, loff_t *pos)
206{
207 struct drm_crtc *crtc = filep->f_inode->i_private;
208 struct drm_crtc_crc *crc = &crtc->crc;
209 struct drm_crtc_crc_entry *entry;
210 char buf[MAX_LINE_LEN];
211 int ret, i;
212
213 spin_lock_irq(&crc->lock);
214
215 if (!crc->source) {
216 spin_unlock_irq(&crc->lock);
217 return 0;
218 }
219
220 /* Nothing to read? */
221 while (crtc_crc_data_count(crc) == 0) {
222 if (filep->f_flags & O_NONBLOCK) {
223 spin_unlock_irq(&crc->lock);
224 return -EAGAIN;
225 }
226
227 ret = wait_event_interruptible_lock_irq(crc->wq,
228 crtc_crc_data_count(crc),
229 crc->lock);
230 if (ret) {
231 spin_unlock_irq(&crc->lock);
232 return ret;
233 }
234 }
235
236 /* We know we have an entry to be read */
237 entry = &crc->entries[crc->tail];
238
239 if (count < LINE_LEN(crc->values_cnt)) {
240 spin_unlock_irq(&crc->lock);
241 return -EINVAL;
242 }
243
244 BUILD_BUG_ON_NOT_POWER_OF_2(DRM_CRC_ENTRIES_NR);
245 crc->tail = (crc->tail + 1) & (DRM_CRC_ENTRIES_NR - 1);
246
247 spin_unlock_irq(&crc->lock);
248
249 if (entry->has_frame_counter)
250 sprintf(buf, "0x%08x", entry->frame);
251 else
252 sprintf(buf, "XXXXXXXXXX");
253
254 for (i = 0; i < crc->values_cnt; i++)
255 sprintf(buf + 10 + i * 11, " 0x%08x", entry->crcs[i]);
256 sprintf(buf + 10 + crc->values_cnt * 11, "\n");
257
258 if (copy_to_user(user_buf, buf, LINE_LEN(crc->values_cnt)))
259 return -EFAULT;
260
261 return LINE_LEN(crc->values_cnt);
262}
263
264const struct file_operations drm_crtc_crc_data_fops = {
265 .owner = THIS_MODULE,
266 .open = crtc_crc_open,
267 .read = crtc_crc_read,
268 .release = crtc_crc_release,
269};
270
271/**
272 * drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs
273 * @crtc: CRTC to whom the frames will belong
274 *
275 * Adds files to debugfs directory that allows userspace to control the
276 * generation of frame CRCs and to read them.
277 *
278 * Returns:
279 * Zero on success, error code on failure.
280 */
281int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
282{
283 struct dentry *crc_ent, *ent;
284
285 if (!crtc->funcs->set_crc_source)
286 return 0;
287
288 crc_ent = debugfs_create_dir("crc", crtc->debugfs_entry);
289 if (!crc_ent)
290 return -ENOMEM;
291
292 ent = debugfs_create_file("control", S_IRUGO, crc_ent, crtc,
293 &drm_crtc_crc_control_fops);
294 if (!ent)
295 goto error;
296
297 ent = debugfs_create_file("data", S_IRUGO, crc_ent, crtc,
298 &drm_crtc_crc_data_fops);
299 if (!ent)
300 goto error;
301
302 return 0;
303
304error:
305 debugfs_remove_recursive(crc_ent);
306
307 return -ENOMEM;
308}
309
310/**
311 * drm_crtc_add_crc_entry - Add entry with CRC information for a frame
312 * @crtc: CRTC to which the frame belongs
313 * @has_frame: whether this entry has a frame number to go with
314 * @frame: number of the frame these CRCs are about
315 * @crcs: array of CRC values, with length matching #drm_crtc_crc.values_cnt
316 *
317 * For each frame, the driver polls the source of CRCs for new data and calls
318 * this function to add them to the buffer from where userspace reads.
319 */
320int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
321 uint32_t frame, uint32_t *crcs)
322{
323 struct drm_crtc_crc *crc = &crtc->crc;
324 struct drm_crtc_crc_entry *entry;
325 int head, tail;
326
327 assert_spin_locked(&crc->lock);
328
329 /* Caller may not have noticed yet that userspace has stopped reading */
330 if (!crc->opened)
331 return -EINVAL;
332
333 head = crc->head;
334 tail = crc->tail;
335
336 if (CIRC_SPACE(head, tail, DRM_CRC_ENTRIES_NR) < 1) {
337 DRM_ERROR("Overflow of CRC buffer, userspace reads too slow.\n");
338 return -ENOBUFS;
339 }
340
341 entry = &crc->entries[head];
342 entry->frame = frame;
343 entry->has_frame_counter = has_frame;
344 memcpy(&entry->crcs, crcs, sizeof(*crcs) * crc->values_cnt);
345
346 head = (head + 1) & (DRM_CRC_ENTRIES_NR - 1);
347 crc->head = head;
348
349 return 0;
350}
351EXPORT_SYMBOL_GPL(drm_crtc_add_crc_entry);