Branch data Line data Source code
1 : : // SPDX-License-Identifier: MIT
2 : : /*
3 : : * Copyright © 2014-2019 Intel Corporation
4 : : */
5 : :
6 : : #include <linux/debugfs.h>
7 : :
8 : : #include "gt/intel_gt.h"
9 : : #include "i915_drv.h"
10 : : #include "i915_memcpy.h"
11 : : #include "intel_guc_log.h"
12 : :
13 : : static void guc_log_capture_logs(struct intel_guc_log *log);
14 : :
15 : : /**
16 : : * DOC: GuC firmware log
17 : : *
18 : : * Firmware log is enabled by setting i915.guc_log_level to the positive level.
19 : : * Log data is printed out via reading debugfs i915_guc_log_dump. Reading from
20 : : * i915_guc_load_status will print out firmware loading status and scratch
21 : : * registers value.
22 : : */
23 : :
24 : 0 : static int guc_action_flush_log_complete(struct intel_guc *guc)
25 : : {
26 : 0 : u32 action[] = {
27 : : INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE
28 : : };
29 : :
30 : 0 : return intel_guc_send(guc, action, ARRAY_SIZE(action));
31 : : }
32 : :
33 : 0 : static int guc_action_flush_log(struct intel_guc *guc)
34 : : {
35 : 0 : u32 action[] = {
36 : : INTEL_GUC_ACTION_FORCE_LOG_BUFFER_FLUSH,
37 : : 0
38 : : };
39 : :
40 : 0 : return intel_guc_send(guc, action, ARRAY_SIZE(action));
41 : : }
42 : :
43 : 0 : static int guc_action_control_log(struct intel_guc *guc, bool enable,
44 : : bool default_logging, u32 verbosity)
45 : : {
46 : 0 : u32 action[] = {
47 : : INTEL_GUC_ACTION_UK_LOG_ENABLE_LOGGING,
48 [ # # ]: 0 : (enable ? GUC_LOG_CONTROL_LOGGING_ENABLED : 0) |
49 : 0 : (verbosity << GUC_LOG_CONTROL_VERBOSITY_SHIFT) |
50 [ # # ]: 0 : (default_logging ? GUC_LOG_CONTROL_DEFAULT_LOGGING : 0)
51 : : };
52 : :
53 : 0 : GEM_BUG_ON(verbosity > GUC_LOG_VERBOSITY_MAX);
54 : :
55 : 0 : return intel_guc_send(guc, action, ARRAY_SIZE(action));
56 : : }
57 : :
58 : 0 : static inline struct intel_guc *log_to_guc(struct intel_guc_log *log)
59 : : {
60 : 0 : return container_of(log, struct intel_guc, log);
61 : : }
62 : :
63 : 0 : static void guc_log_enable_flush_events(struct intel_guc_log *log)
64 : : {
65 : 0 : intel_guc_enable_msg(log_to_guc(log),
66 : : INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
67 : : INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED);
68 : : }
69 : :
70 : 0 : static void guc_log_disable_flush_events(struct intel_guc_log *log)
71 : : {
72 : 0 : intel_guc_disable_msg(log_to_guc(log),
73 : : INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
74 : : INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED);
75 : : }
76 : :
77 : : /*
78 : : * Sub buffer switch callback. Called whenever relay has to switch to a new
79 : : * sub buffer, relay stays on the same sub buffer if 0 is returned.
80 : : */
81 : 0 : static int subbuf_start_callback(struct rchan_buf *buf,
82 : : void *subbuf,
83 : : void *prev_subbuf,
84 : : size_t prev_padding)
85 : : {
86 : : /*
87 : : * Use no-overwrite mode by default, where relay will stop accepting
88 : : * new data if there are no empty sub buffers left.
89 : : * There is no strict synchronization enforced by relay between Consumer
90 : : * and Producer. In overwrite mode, there is a possibility of getting
91 : : * inconsistent/garbled data, the producer could be writing on to the
92 : : * same sub buffer from which Consumer is reading. This can't be avoided
93 : : * unless Consumer is fast enough and can always run in tandem with
94 : : * Producer.
95 : : */
96 [ # # ]: 0 : if (relay_buf_full(buf))
97 : 0 : return 0;
98 : :
99 : : return 1;
100 : : }
101 : :
102 : : /*
103 : : * file_create() callback. Creates relay file in debugfs.
104 : : */
105 : 0 : static struct dentry *create_buf_file_callback(const char *filename,
106 : : struct dentry *parent,
107 : : umode_t mode,
108 : : struct rchan_buf *buf,
109 : : int *is_global)
110 : : {
111 : 0 : struct dentry *buf_file;
112 : :
113 : : /*
114 : : * This to enable the use of a single buffer for the relay channel and
115 : : * correspondingly have a single file exposed to User, through which
116 : : * it can collect the logs in order without any post-processing.
117 : : * Need to set 'is_global' even if parent is NULL for early logging.
118 : : */
119 : 0 : *is_global = 1;
120 : :
121 [ # # ]: 0 : if (!parent)
122 : : return NULL;
123 : :
124 : 0 : buf_file = debugfs_create_file(filename, mode,
125 : : parent, buf, &relay_file_operations);
126 [ # # ]: 0 : if (IS_ERR(buf_file))
127 : 0 : return NULL;
128 : :
129 : : return buf_file;
130 : : }
131 : :
132 : : /*
133 : : * file_remove() default callback. Removes relay file in debugfs.
134 : : */
135 : 0 : static int remove_buf_file_callback(struct dentry *dentry)
136 : : {
137 : 0 : debugfs_remove(dentry);
138 : 0 : return 0;
139 : : }
140 : :
141 : : /* relay channel callbacks */
142 : : static struct rchan_callbacks relay_callbacks = {
143 : : .subbuf_start = subbuf_start_callback,
144 : : .create_buf_file = create_buf_file_callback,
145 : : .remove_buf_file = remove_buf_file_callback,
146 : : };
147 : :
148 : : static void guc_move_to_next_buf(struct intel_guc_log *log)
149 : : {
150 : : /*
151 : : * Make sure the updates made in the sub buffer are visible when
152 : : * Consumer sees the following update to offset inside the sub buffer.
153 : : */
154 : : smp_wmb();
155 : :
156 : : /* All data has been written, so now move the offset of sub buffer. */
157 : : relay_reserve(log->relay.channel, log->vma->obj->base.size);
158 : :
159 : : /* Switch to the next sub buffer */
160 : : relay_flush(log->relay.channel);
161 : : }
162 : :
163 : 0 : static void *guc_get_write_buffer(struct intel_guc_log *log)
164 : : {
165 : : /*
166 : : * Just get the base address of a new sub buffer and copy data into it
167 : : * ourselves. NULL will be returned in no-overwrite mode, if all sub
168 : : * buffers are full. Could have used the relay_write() to indirectly
169 : : * copy the data, but that would have been bit convoluted, as we need to
170 : : * write to only certain locations inside a sub buffer which cannot be
171 : : * done without using relay_reserve() along with relay_write(). So its
172 : : * better to use relay_reserve() alone.
173 : : */
174 : 0 : return relay_reserve(log->relay.channel, 0);
175 : : }
176 : :
177 : 0 : static bool guc_check_log_buf_overflow(struct intel_guc_log *log,
178 : : enum guc_log_buffer_type type,
179 : : unsigned int full_cnt)
180 : : {
181 : 0 : unsigned int prev_full_cnt = log->stats[type].sampled_overflow;
182 : 0 : bool overflow = false;
183 : :
184 [ # # ]: 0 : if (full_cnt != prev_full_cnt) {
185 : 0 : overflow = true;
186 : :
187 : 0 : log->stats[type].overflow = full_cnt;
188 : 0 : log->stats[type].sampled_overflow += full_cnt - prev_full_cnt;
189 : :
190 [ # # ]: 0 : if (full_cnt < prev_full_cnt) {
191 : : /* buffer_full_cnt is a 4 bit counter */
192 : 0 : log->stats[type].sampled_overflow += 16;
193 : : }
194 : :
195 [ # # ]: 0 : dev_notice_ratelimited(guc_to_gt(log_to_guc(log))->i915->drm.dev,
196 : : "GuC log buffer overflow\n");
197 : : }
198 : :
199 : 0 : return overflow;
200 : : }
201 : :
202 : 0 : static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type)
203 : : {
204 [ # # # ]: 0 : switch (type) {
205 : : case GUC_ISR_LOG_BUFFER:
206 : : return ISR_BUFFER_SIZE;
207 : : case GUC_DPC_LOG_BUFFER:
208 : : return DPC_BUFFER_SIZE;
209 : 0 : case GUC_CRASH_DUMP_LOG_BUFFER:
210 : 0 : return CRASH_BUFFER_SIZE;
211 : : default:
212 : 0 : MISSING_CASE(type);
213 : : }
214 : :
215 : 0 : return 0;
216 : : }
217 : :
218 : 0 : static void guc_read_update_log_buffer(struct intel_guc_log *log)
219 : : {
220 : 0 : unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt;
221 : 0 : struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state;
222 : 0 : struct guc_log_buffer_state log_buf_state_local;
223 : 0 : enum guc_log_buffer_type type;
224 : 0 : void *src_data, *dst_data;
225 : 0 : bool new_overflow;
226 : :
227 : 0 : mutex_lock(&log->relay.lock);
228 : :
229 [ # # ]: 0 : if (WARN_ON(!intel_guc_log_relay_created(log)))
230 : 0 : goto out_unlock;
231 : :
232 : : /* Get the pointer to shared GuC log buffer */
233 : 0 : log_buf_state = src_data = log->relay.buf_addr;
234 : :
235 : : /* Get the pointer to local buffer to store the logs */
236 : 0 : log_buf_snapshot_state = dst_data = guc_get_write_buffer(log);
237 : :
238 [ # # ]: 0 : if (unlikely(!log_buf_snapshot_state)) {
239 : : /*
240 : : * Used rate limited to avoid deluge of messages, logs might be
241 : : * getting consumed by User at a slow rate.
242 : : */
243 [ # # ]: 0 : DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n");
244 : 0 : log->relay.full_count++;
245 : :
246 : 0 : goto out_unlock;
247 : : }
248 : :
249 : : /* Actual logs are present from the 2nd page */
250 : 0 : src_data += PAGE_SIZE;
251 : 0 : dst_data += PAGE_SIZE;
252 : :
253 [ # # ]: 0 : for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
254 : : /*
255 : : * Make a copy of the state structure, inside GuC log buffer
256 : : * (which is uncached mapped), on the stack to avoid reading
257 : : * from it multiple times.
258 : : */
259 : 0 : memcpy(&log_buf_state_local, log_buf_state,
260 : : sizeof(struct guc_log_buffer_state));
261 : 0 : buffer_size = guc_get_log_buffer_size(type);
262 : 0 : read_offset = log_buf_state_local.read_ptr;
263 : 0 : write_offset = log_buf_state_local.sampled_write_ptr;
264 : 0 : full_cnt = log_buf_state_local.buffer_full_cnt;
265 : :
266 : : /* Bookkeeping stuff */
267 : 0 : log->stats[type].flush += log_buf_state_local.flush_to_file;
268 : 0 : new_overflow = guc_check_log_buf_overflow(log, type, full_cnt);
269 : :
270 : : /* Update the state of shared log buffer */
271 : 0 : log_buf_state->read_ptr = write_offset;
272 : 0 : log_buf_state->flush_to_file = 0;
273 : 0 : log_buf_state++;
274 : :
275 : : /* First copy the state structure in snapshot buffer */
276 : 0 : memcpy(log_buf_snapshot_state, &log_buf_state_local,
277 : : sizeof(struct guc_log_buffer_state));
278 : :
279 : : /*
280 : : * The write pointer could have been updated by GuC firmware,
281 : : * after sending the flush interrupt to Host, for consistency
282 : : * set write pointer value to same value of sampled_write_ptr
283 : : * in the snapshot buffer.
284 : : */
285 : 0 : log_buf_snapshot_state->write_ptr = write_offset;
286 : 0 : log_buf_snapshot_state++;
287 : :
288 : : /* Now copy the actual logs. */
289 [ # # ]: 0 : if (unlikely(new_overflow)) {
290 : : /* copy the whole buffer in case of overflow */
291 : : read_offset = 0;
292 : : write_offset = buffer_size;
293 [ # # ]: 0 : } else if (unlikely((read_offset > buffer_size) ||
294 : : (write_offset > buffer_size))) {
295 : 0 : DRM_ERROR("invalid log buffer state\n");
296 : : /* copy whole buffer as offsets are unreliable */
297 : 0 : read_offset = 0;
298 : 0 : write_offset = buffer_size;
299 : : }
300 : :
301 : : /* Just copy the newly written data */
302 [ # # ]: 0 : if (read_offset > write_offset) {
303 : 0 : i915_memcpy_from_wc(dst_data, src_data, write_offset);
304 : 0 : bytes_to_copy = buffer_size - read_offset;
305 : : } else {
306 : 0 : bytes_to_copy = write_offset - read_offset;
307 : : }
308 : 0 : i915_memcpy_from_wc(dst_data + read_offset,
309 : 0 : src_data + read_offset, bytes_to_copy);
310 : :
311 : 0 : src_data += buffer_size;
312 : 0 : dst_data += buffer_size;
313 : : }
314 : :
315 : 0 : guc_move_to_next_buf(log);
316 : :
317 : 0 : out_unlock:
318 : 0 : mutex_unlock(&log->relay.lock);
319 : 0 : }
320 : :
321 : 0 : static void capture_logs_work(struct work_struct *work)
322 : : {
323 : 0 : struct intel_guc_log *log =
324 : 0 : container_of(work, struct intel_guc_log, relay.flush_work);
325 : :
326 : 0 : guc_log_capture_logs(log);
327 : 0 : }
328 : :
329 : 0 : static int guc_log_map(struct intel_guc_log *log)
330 : : {
331 : 0 : void *vaddr;
332 : :
333 : 0 : lockdep_assert_held(&log->relay.lock);
334 : :
335 : 0 : if (!log->vma)
336 : : return -ENODEV;
337 : :
338 : : /*
339 : : * Create a WC (Uncached for read) vmalloc mapping of log
340 : : * buffer pages, so that we can directly get the data
341 : : * (up-to-date) from memory.
342 : : */
343 : 0 : vaddr = i915_gem_object_pin_map(log->vma->obj, I915_MAP_WC);
344 [ # # ]: 0 : if (IS_ERR(vaddr))
345 [ # # ]: 0 : return PTR_ERR(vaddr);
346 : :
347 : 0 : log->relay.buf_addr = vaddr;
348 : :
349 : 0 : return 0;
350 : : }
351 : :
352 : 0 : static void guc_log_unmap(struct intel_guc_log *log)
353 : : {
354 : 0 : lockdep_assert_held(&log->relay.lock);
355 : :
356 : 0 : i915_gem_object_unpin_map(log->vma->obj);
357 : 0 : log->relay.buf_addr = NULL;
358 : : }
359 : :
360 : 0 : void intel_guc_log_init_early(struct intel_guc_log *log)
361 : : {
362 : 0 : mutex_init(&log->relay.lock);
363 : 0 : INIT_WORK(&log->relay.flush_work, capture_logs_work);
364 : 0 : log->relay.started = false;
365 : 0 : }
366 : :
367 : 0 : static int guc_log_relay_create(struct intel_guc_log *log)
368 : : {
369 : 0 : struct intel_guc *guc = log_to_guc(log);
370 : 0 : struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
371 : 0 : struct rchan *guc_log_relay_chan;
372 : 0 : size_t n_subbufs, subbuf_size;
373 : 0 : int ret;
374 : :
375 : 0 : lockdep_assert_held(&log->relay.lock);
376 : 0 : GEM_BUG_ON(!log->vma);
377 : :
378 : : /* Keep the size of sub buffers same as shared log buffer */
379 : 0 : subbuf_size = log->vma->size;
380 : :
381 : : /*
382 : : * Store up to 8 snapshots, which is large enough to buffer sufficient
383 : : * boot time logs and provides enough leeway to User, in terms of
384 : : * latency, for consuming the logs from relay. Also doesn't take
385 : : * up too much memory.
386 : : */
387 : 0 : n_subbufs = 8;
388 : :
389 : 0 : guc_log_relay_chan = relay_open("guc_log",
390 : 0 : dev_priv->drm.primary->debugfs_root,
391 : : subbuf_size, n_subbufs,
392 : : &relay_callbacks, dev_priv);
393 [ # # ]: 0 : if (!guc_log_relay_chan) {
394 : 0 : DRM_ERROR("Couldn't create relay chan for GuC logging\n");
395 : :
396 : 0 : ret = -ENOMEM;
397 : 0 : return ret;
398 : : }
399 : :
400 : 0 : GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size);
401 : 0 : log->relay.channel = guc_log_relay_chan;
402 : :
403 : 0 : return 0;
404 : : }
405 : :
406 : 0 : static void guc_log_relay_destroy(struct intel_guc_log *log)
407 : : {
408 : 0 : lockdep_assert_held(&log->relay.lock);
409 : :
410 : 0 : relay_close(log->relay.channel);
411 : 0 : log->relay.channel = NULL;
412 : 0 : }
413 : :
414 : 0 : static void guc_log_capture_logs(struct intel_guc_log *log)
415 : : {
416 : 0 : struct intel_guc *guc = log_to_guc(log);
417 : 0 : struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
418 : 0 : intel_wakeref_t wakeref;
419 : :
420 : 0 : guc_read_update_log_buffer(log);
421 : :
422 : : /*
423 : : * Generally device is expected to be active only at this
424 : : * time, so get/put should be really quick.
425 : : */
426 [ # # ]: 0 : with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
427 : 0 : guc_action_flush_log_complete(guc);
428 : 0 : }
429 : :
430 : : static u32 __get_default_log_level(struct intel_guc_log *log)
431 : : {
432 : : /* A negative value means "use platform/config default" */
433 : : if (i915_modparams.guc_log_level < 0) {
434 : : return (IS_ENABLED(CONFIG_DRM_I915_DEBUG) ||
435 : : IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) ?
436 : : GUC_LOG_LEVEL_MAX : GUC_LOG_LEVEL_NON_VERBOSE;
437 : : }
438 : :
439 : : if (i915_modparams.guc_log_level > GUC_LOG_LEVEL_MAX) {
440 : : DRM_WARN("Incompatible option detected: %s=%d, %s!\n",
441 : : "guc_log_level", i915_modparams.guc_log_level,
442 : : "verbosity too high");
443 : : return (IS_ENABLED(CONFIG_DRM_I915_DEBUG) ||
444 : : IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) ?
445 : : GUC_LOG_LEVEL_MAX : GUC_LOG_LEVEL_DISABLED;
446 : : }
447 : :
448 : : GEM_BUG_ON(i915_modparams.guc_log_level < GUC_LOG_LEVEL_DISABLED);
449 : : GEM_BUG_ON(i915_modparams.guc_log_level > GUC_LOG_LEVEL_MAX);
450 : : return i915_modparams.guc_log_level;
451 : : }
452 : :
453 : 0 : int intel_guc_log_create(struct intel_guc_log *log)
454 : : {
455 : 0 : struct intel_guc *guc = log_to_guc(log);
456 : 0 : struct i915_vma *vma;
457 : 0 : u32 guc_log_size;
458 : 0 : int ret;
459 : :
460 : 0 : GEM_BUG_ON(log->vma);
461 : :
462 : : /*
463 : : * GuC Log buffer Layout
464 : : *
465 : : * +===============================+ 00B
466 : : * | Crash dump state header |
467 : : * +-------------------------------+ 32B
468 : : * | DPC state header |
469 : : * +-------------------------------+ 64B
470 : : * | ISR state header |
471 : : * +-------------------------------+ 96B
472 : : * | |
473 : : * +===============================+ PAGE_SIZE (4KB)
474 : : * | Crash Dump logs |
475 : : * +===============================+ + CRASH_SIZE
476 : : * | DPC logs |
477 : : * +===============================+ + DPC_SIZE
478 : : * | ISR logs |
479 : : * +===============================+ + ISR_SIZE
480 : : */
481 : 0 : guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DPC_BUFFER_SIZE +
482 : : ISR_BUFFER_SIZE;
483 : :
484 : 0 : vma = intel_guc_allocate_vma(guc, guc_log_size);
485 [ # # ]: 0 : if (IS_ERR(vma)) {
486 : 0 : ret = PTR_ERR(vma);
487 : 0 : goto err;
488 : : }
489 : :
490 : 0 : log->vma = vma;
491 : :
492 : 0 : log->level = __get_default_log_level(log);
493 [ # # ]: 0 : DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n",
494 : : log->level, enableddisabled(log->level),
495 : : yesno(GUC_LOG_LEVEL_IS_VERBOSE(log->level)),
496 : : GUC_LOG_LEVEL_TO_VERBOSITY(log->level));
497 : :
498 : 0 : return 0;
499 : :
500 : : err:
501 : 0 : DRM_ERROR("Failed to allocate GuC log buffer. %d\n", ret);
502 : 0 : return ret;
503 : : }
504 : :
505 : 0 : void intel_guc_log_destroy(struct intel_guc_log *log)
506 : : {
507 : 0 : i915_vma_unpin_and_release(&log->vma, 0);
508 : 0 : }
509 : :
510 : 0 : int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
511 : : {
512 : 0 : struct intel_guc *guc = log_to_guc(log);
513 [ # # ]: 0 : struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915;
514 : 0 : intel_wakeref_t wakeref;
515 : 0 : int ret = 0;
516 : :
517 : 0 : BUILD_BUG_ON(GUC_LOG_VERBOSITY_MIN != 0);
518 : 0 : GEM_BUG_ON(!log->vma);
519 : :
520 : : /*
521 : : * GuC is recognizing log levels starting from 0 to max, we're using 0
522 : : * as indication that logging should be disabled.
523 : : */
524 [ # # ]: 0 : if (level < GUC_LOG_LEVEL_DISABLED || level > GUC_LOG_LEVEL_MAX)
525 : : return -EINVAL;
526 : :
527 : 0 : mutex_lock(&dev_priv->drm.struct_mutex);
528 : :
529 [ # # ]: 0 : if (log->level == level)
530 : 0 : goto out_unlock;
531 : :
532 [ # # ]: 0 : with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
533 : 0 : ret = guc_action_control_log(guc,
534 : : GUC_LOG_LEVEL_IS_VERBOSE(level),
535 : : GUC_LOG_LEVEL_IS_ENABLED(level),
536 : 0 : GUC_LOG_LEVEL_TO_VERBOSITY(level));
537 [ # # ]: 0 : if (ret) {
538 : 0 : DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret);
539 : 0 : goto out_unlock;
540 : : }
541 : :
542 : 0 : log->level = level;
543 : :
544 : 0 : out_unlock:
545 : 0 : mutex_unlock(&dev_priv->drm.struct_mutex);
546 : :
547 : 0 : return ret;
548 : : }
549 : :
550 : 0 : bool intel_guc_log_relay_created(const struct intel_guc_log *log)
551 : : {
552 [ # # ]: 0 : return log->relay.buf_addr;
553 : : }
554 : :
555 : 0 : int intel_guc_log_relay_open(struct intel_guc_log *log)
556 : : {
557 : 0 : int ret;
558 : :
559 [ # # ]: 0 : if (!log->vma)
560 : : return -ENODEV;
561 : :
562 : 0 : mutex_lock(&log->relay.lock);
563 : :
564 [ # # ]: 0 : if (intel_guc_log_relay_created(log)) {
565 : 0 : ret = -EEXIST;
566 : 0 : goto out_unlock;
567 : : }
568 : :
569 : : /*
570 : : * We require SSE 4.1 for fast reads from the GuC log buffer and
571 : : * it should be present on the chipsets supporting GuC based
572 : : * submisssions.
573 : : */
574 [ # # ]: 0 : if (!i915_has_memcpy_from_wc()) {
575 : 0 : ret = -ENXIO;
576 : 0 : goto out_unlock;
577 : : }
578 : :
579 : 0 : ret = guc_log_relay_create(log);
580 [ # # ]: 0 : if (ret)
581 : 0 : goto out_unlock;
582 : :
583 [ # # ]: 0 : ret = guc_log_map(log);
584 [ # # ]: 0 : if (ret)
585 : 0 : goto out_relay;
586 : :
587 : 0 : mutex_unlock(&log->relay.lock);
588 : :
589 : 0 : return 0;
590 : :
591 : : out_relay:
592 : 0 : guc_log_relay_destroy(log);
593 : 0 : out_unlock:
594 : 0 : mutex_unlock(&log->relay.lock);
595 : :
596 : 0 : return ret;
597 : : }
598 : :
599 : 0 : int intel_guc_log_relay_start(struct intel_guc_log *log)
600 : : {
601 [ # # ]: 0 : if (log->relay.started)
602 : : return -EEXIST;
603 : :
604 : 0 : guc_log_enable_flush_events(log);
605 : :
606 : : /*
607 : : * When GuC is logging without us relaying to userspace, we're ignoring
608 : : * the flush notification. This means that we need to unconditionally
609 : : * flush on relay enabling, since GuC only notifies us once.
610 : : */
611 : 0 : queue_work(system_highpri_wq, &log->relay.flush_work);
612 : :
613 : 0 : log->relay.started = true;
614 : :
615 : 0 : return 0;
616 : : }
617 : :
618 : 0 : void intel_guc_log_relay_flush(struct intel_guc_log *log)
619 : : {
620 : 0 : struct intel_guc *guc = log_to_guc(log);
621 : 0 : intel_wakeref_t wakeref;
622 : :
623 [ # # ]: 0 : if (!log->relay.started)
624 : : return;
625 : :
626 : : /*
627 : : * Before initiating the forceful flush, wait for any pending/ongoing
628 : : * flush to complete otherwise forceful flush may not actually happen.
629 : : */
630 : 0 : flush_work(&log->relay.flush_work);
631 : :
632 [ # # ]: 0 : with_intel_runtime_pm(guc_to_gt(guc)->uncore->rpm, wakeref)
633 : 0 : guc_action_flush_log(guc);
634 : :
635 : : /* GuC would have updated log buffer by now, so capture it */
636 : 0 : guc_log_capture_logs(log);
637 : : }
638 : :
639 : : /*
640 : : * Stops the relay log. Called from intel_guc_log_relay_close(), so no
641 : : * possibility of race with start/flush since relay_write cannot race
642 : : * relay_close.
643 : : */
644 : 0 : static void guc_log_relay_stop(struct intel_guc_log *log)
645 : : {
646 : 0 : struct intel_guc *guc = log_to_guc(log);
647 [ # # ]: 0 : struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
648 : :
649 [ # # ]: 0 : if (!log->relay.started)
650 : : return;
651 : :
652 : 0 : guc_log_disable_flush_events(log);
653 : 0 : intel_synchronize_irq(i915);
654 : :
655 : 0 : flush_work(&log->relay.flush_work);
656 : :
657 : 0 : log->relay.started = false;
658 : : }
659 : :
660 : 0 : void intel_guc_log_relay_close(struct intel_guc_log *log)
661 : : {
662 : 0 : guc_log_relay_stop(log);
663 : :
664 : 0 : mutex_lock(&log->relay.lock);
665 : 0 : GEM_BUG_ON(!intel_guc_log_relay_created(log));
666 : 0 : guc_log_unmap(log);
667 : 0 : guc_log_relay_destroy(log);
668 : 0 : mutex_unlock(&log->relay.lock);
669 : 0 : }
670 : :
671 : 0 : void intel_guc_log_handle_flush_event(struct intel_guc_log *log)
672 : : {
673 : 0 : queue_work(system_highpri_wq, &log->relay.flush_work);
674 : 0 : }
|