/* * NB: kmalloc has a hard limit well below the maximum GuC log buffer size. * Also, can't use vmalloc as might be called from atomic context. So need * to break the buffer up into smaller chunks that can be allocated.
*/
snapshot->size = xe_bo_size(log->bo);
snapshot->num_chunks = DIV_ROUND_UP(snapshot->size, GUC_LOG_CHUNK_SIZE);
fail_copy: for (i = 0; i < snapshot->num_chunks; i++)
kfree(snapshot->copy[i]);
kfree(snapshot->copy);
fail_snap:
kfree(snapshot); return NULL;
}
/** * xe_guc_log_snapshot_free - free a previously captured GuC log snapshot * @snapshot: GuC log snapshot structure * * Return: pointer to a newly allocated snapshot object or null if out of memory. Caller is * responsible for calling xe_guc_log_snapshot_free when done with the snapshot.
*/ void xe_guc_log_snapshot_free(struct xe_guc_log_snapshot *snapshot)
{ int i;
if (!snapshot) return;
if (snapshot->copy) { for (i = 0; i < snapshot->num_chunks; i++)
kfree(snapshot->copy[i]);
kfree(snapshot->copy);
}
kfree(snapshot);
}
/** * xe_guc_log_snapshot_capture - create a new snapshot copy the GuC log for later dumping * @log: GuC log structure * @atomic: is the call inside an atomic section of some kind? * * Return: pointer to a newly allocated snapshot object or null if out of memory. Caller is * responsible for calling xe_guc_log_snapshot_free when done with the snapshot.
*/ struct xe_guc_log_snapshot *xe_guc_log_snapshot_capture(struct xe_guc_log *log, bool atomic)
{ struct xe_guc_log_snapshot *snapshot; struct xe_device *xe = log_to_xe(log); struct xe_guc *guc = log_to_guc(log); struct xe_gt *gt = log_to_gt(log); unsignedint fw_ref;
size_t remain; int i;
if (!log->bo) return NULL;
snapshot = xe_guc_log_snapshot_alloc(log, atomic); if (!snapshot) return NULL;
remain = snapshot->size; for (i = 0; i < snapshot->num_chunks; i++) {
size_t size = min(GUC_LOG_CHUNK_SIZE, remain);
/** * xe_guc_log_snapshot_print - dump a previously saved copy of the GuC log to some useful location * @snapshot: a snapshot of the GuC log * @p: the printer object to output to
*/ void xe_guc_log_snapshot_print(struct xe_guc_log_snapshot *snapshot, struct drm_printer *p)
{
size_t remain; int i;
if (!snapshot) {
drm_printf(p, "GuC log snapshot not allocated!\n"); return;
}
/** * xe_guc_log_print_dmesg - dump a copy of the GuC log to dmesg * @log: GuC log structure
*/ void xe_guc_log_print_dmesg(struct xe_guc_log *log)
{ struct xe_gt *gt = log_to_gt(log); staticint g_count; struct drm_printer ip = xe_gt_info_printer(gt); struct drm_printer lp = drm_line_printer(&ip, "Capture", ++g_count);
drm_printf(&lp, "Dumping GuC log for %ps...\n", __builtin_return_address(0));
xe_guc_log_print(log, &lp);
drm_printf(&lp, "Done.\n");
}
/** * xe_guc_log_print - dump a copy of the GuC log to some useful location * @log: GuC log structure * @p: the printer object to output to
*/ void xe_guc_log_print(struct xe_guc_log *log, struct drm_printer *p)
{ struct xe_guc_log_snapshot *snapshot;
/** * xe_guc_log_section_size_capture - Get capture buffer size within log sections. * @log: The log object. * * This function will return the capture buffer size within log sections. * * Return: capture buffer size.
*/
u32 xe_guc_log_section_size_capture(struct xe_guc_log *log)
{ return CAPTURE_BUFFER_SIZE;
}
/** * xe_guc_get_log_buffer_size - Get log buffer size for a type. * @log: The log object. * @type: The log buffer type * * Return: buffer size.
*/
u32 xe_guc_get_log_buffer_size(struct xe_guc_log *log, enum guc_log_buffer_type type)
{ switch (type) { case GUC_LOG_BUFFER_CRASH_DUMP: return xe_guc_log_section_size_crash(log); case GUC_LOG_BUFFER_DEBUG: return xe_guc_log_section_size_debug(log); case GUC_LOG_BUFFER_CAPTURE: return xe_guc_log_section_size_capture(log);
} return 0;
}
/** * xe_guc_get_log_buffer_offset - Get offset in log buffer for a type. * @log: The log object. * @type: The log buffer type * * This function will return the offset in the log buffer for a type. * Return: buffer offset.
*/
u32 xe_guc_get_log_buffer_offset(struct xe_guc_log *log, enum guc_log_buffer_type type)
{ enum guc_log_buffer_type i;
u32 offset = PAGE_SIZE;/* for the log_buffer_states */
for (i = GUC_LOG_BUFFER_CRASH_DUMP; i < GUC_LOG_BUFFER_TYPE_MAX; ++i) { if (i == type) break;
offset += xe_guc_get_log_buffer_size(log, i);
}
return offset;
}
/** * xe_guc_check_log_buf_overflow - Check if log buffer overflowed * @log: The log object. * @type: The log buffer type * @full_cnt: The count of buffer full * * This function will check count of buffer full against previous, mismatch * indicate overflowed. * Update the sampled_overflow counter, if the 4 bit counter overflowed, add * up 16 to correct the value. * * Return: True if overflowed.
*/ bool xe_guc_check_log_buf_overflow(struct xe_guc_log *log, enum guc_log_buffer_type type, unsignedint full_cnt)
{ unsignedint prev_full_cnt = log->stats[type].sampled_overflow; bool overflow = false;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.