Skip to content

Commit

Permalink
drm/i915/guc: Make GuC log sizes runtime configurable
Browse files Browse the repository at this point in the history
The GuC log buffer sizes had to be configured statically at compile
time. This can be quite troublesome when needing to get larger logs
out of a released driver. So re-organise the code to allow a boot time
module parameter override.

Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220728022028.2190627-7-John.C.Harrison@Intel.com
  • Loading branch information
John Harrison authored and John Harrison committed Aug 17, 2022
1 parent 5ece208 commit 8ad0152
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 74 deletions.
53 changes: 11 additions & 42 deletions drivers/gpu/drm/i915/gt/uc/intel_guc.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,53 +224,22 @@ static u32 guc_ctl_feature_flags(struct intel_guc *guc)

static u32 guc_ctl_log_params_flags(struct intel_guc *guc)
{
u32 offset = intel_guc_ggtt_offset(guc, guc->log.vma) >> PAGE_SHIFT;
u32 flags;

#if (((CRASH_BUFFER_SIZE) % SZ_1M) == 0)
#define LOG_UNIT SZ_1M
#define LOG_FLAG GUC_LOG_LOG_ALLOC_UNITS
#else
#define LOG_UNIT SZ_4K
#define LOG_FLAG 0
#endif

#if (((CAPTURE_BUFFER_SIZE) % SZ_1M) == 0)
#define CAPTURE_UNIT SZ_1M
#define CAPTURE_FLAG GUC_LOG_CAPTURE_ALLOC_UNITS
#else
#define CAPTURE_UNIT SZ_4K
#define CAPTURE_FLAG 0
#endif

BUILD_BUG_ON(!CRASH_BUFFER_SIZE);
BUILD_BUG_ON(!IS_ALIGNED(CRASH_BUFFER_SIZE, LOG_UNIT));
BUILD_BUG_ON(!DEBUG_BUFFER_SIZE);
BUILD_BUG_ON(!IS_ALIGNED(DEBUG_BUFFER_SIZE, LOG_UNIT));
BUILD_BUG_ON(!CAPTURE_BUFFER_SIZE);
BUILD_BUG_ON(!IS_ALIGNED(CAPTURE_BUFFER_SIZE, CAPTURE_UNIT));

BUILD_BUG_ON((CRASH_BUFFER_SIZE / LOG_UNIT - 1) >
(GUC_LOG_CRASH_MASK >> GUC_LOG_CRASH_SHIFT));
BUILD_BUG_ON((DEBUG_BUFFER_SIZE / LOG_UNIT - 1) >
(GUC_LOG_DEBUG_MASK >> GUC_LOG_DEBUG_SHIFT));
BUILD_BUG_ON((CAPTURE_BUFFER_SIZE / CAPTURE_UNIT - 1) >
(GUC_LOG_CAPTURE_MASK >> GUC_LOG_CAPTURE_SHIFT));
struct intel_guc_log *log = &guc->log;
u32 offset, flags;

GEM_BUG_ON(!log->sizes_initialised);

offset = intel_guc_ggtt_offset(guc, log->vma) >> PAGE_SHIFT;

flags = GUC_LOG_VALID |
GUC_LOG_NOTIFY_ON_HALF_FULL |
CAPTURE_FLAG |
LOG_FLAG |
((CRASH_BUFFER_SIZE / LOG_UNIT - 1) << GUC_LOG_CRASH_SHIFT) |
((DEBUG_BUFFER_SIZE / LOG_UNIT - 1) << GUC_LOG_DEBUG_SHIFT) |
((CAPTURE_BUFFER_SIZE / CAPTURE_UNIT - 1) << GUC_LOG_CAPTURE_SHIFT) |
log->sizes[GUC_LOG_SECTIONS_DEBUG].flag |
log->sizes[GUC_LOG_SECTIONS_CAPTURE].flag |
(log->sizes[GUC_LOG_SECTIONS_CRASH].count << GUC_LOG_CRASH_SHIFT) |
(log->sizes[GUC_LOG_SECTIONS_DEBUG].count << GUC_LOG_DEBUG_SHIFT) |
(log->sizes[GUC_LOG_SECTIONS_CAPTURE].count << GUC_LOG_CAPTURE_SHIFT) |
(offset << GUC_LOG_BUF_ADDR_SHIFT);

#undef LOG_UNIT
#undef LOG_FLAG
#undef CAPTURE_UNIT
#undef CAPTURE_FLAG

return flags;
}

Expand Down
14 changes: 8 additions & 6 deletions drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
Original file line number Diff line number Diff line change
Expand Up @@ -656,16 +656,17 @@ static void check_guc_capture_size(struct intel_guc *guc)
struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
int min_size = guc_capture_output_min_size_est(guc);
int spare_size = min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER;
u32 buffer_size = intel_guc_log_section_size_capture(&guc->log);

if (min_size < 0)
drm_warn(&i915->drm, "Failed to calculate GuC error state capture buffer minimum size: %d!\n",
min_size);
else if (min_size > CAPTURE_BUFFER_SIZE)
else if (min_size > buffer_size)
drm_warn(&i915->drm, "GuC error state capture buffer is too small: %d < %d\n",
CAPTURE_BUFFER_SIZE, min_size);
else if (spare_size > CAPTURE_BUFFER_SIZE)
buffer_size, min_size);
else if (spare_size > buffer_size)
drm_notice(&i915->drm, "GuC error state capture buffer maybe too small: %d < %d (min = %d)\n",
CAPTURE_BUFFER_SIZE, spare_size, min_size);
buffer_size, spare_size, min_size);
}

/*
Expand Down Expand Up @@ -1294,15 +1295,16 @@ static void __guc_capture_process_output(struct intel_guc *guc)

log_buf_state = guc->log.buf_addr +
(sizeof(struct guc_log_buffer_state) * GUC_CAPTURE_LOG_BUFFER);
src_data = guc->log.buf_addr + intel_guc_get_log_buffer_offset(GUC_CAPTURE_LOG_BUFFER);
src_data = guc->log.buf_addr +
intel_guc_get_log_buffer_offset(&guc->log, GUC_CAPTURE_LOG_BUFFER);

/*
* Make a copy of the state structure, inside GuC log buffer
* (which is uncached mapped), on the stack to avoid reading
* from it multiple times.
*/
memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state));
buffer_size = intel_guc_get_log_buffer_size(GUC_CAPTURE_LOG_BUFFER);
buffer_size = intel_guc_get_log_buffer_size(&guc->log, GUC_CAPTURE_LOG_BUFFER);
read_offset = log_buf_state_local.read_ptr;
write_offset = log_buf_state_local.sampled_write_ptr;
full_count = log_buf_state_local.buffer_full_cnt;
Expand Down
176 changes: 166 additions & 10 deletions drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,158 @@
#include "intel_guc_capture.h"
#include "intel_guc_log.h"

#if defined(CONFIG_DRM_I915_DEBUG_GUC)
#define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_2M
#define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_16M
#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_4M
#elif defined(CONFIG_DRM_I915_DEBUG_GEM)
#define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_1M
#define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_2M
#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_4M
#else
#define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_8K
#define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_64K
#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_2M
#endif

static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log);

struct guc_log_section {
u32 max;
u32 flag;
u32 default_val;
const char *name;
};

static s32 scale_log_param(struct intel_guc_log *log, const struct guc_log_section *section,
s32 param)
{
/* -1 means default */
if (param < 0)
return section->default_val;

/* Check for 32-bit overflow */
if (param >= SZ_4K) {
drm_err(&guc_to_gt(log_to_guc(log))->i915->drm, "Size too large for GuC %s log: %dMB!",
section->name, param);
return section->default_val;
}

/* Param units are 1MB */
return param * SZ_1M;
}

static void _guc_log_init_sizes(struct intel_guc_log *log)
{
struct intel_guc *guc = log_to_guc(log);
struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
static const struct guc_log_section sections[GUC_LOG_SECTIONS_LIMIT] = {
{
GUC_LOG_CRASH_MASK >> GUC_LOG_CRASH_SHIFT,
GUC_LOG_LOG_ALLOC_UNITS,
GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE,
"crash dump"
},
{
GUC_LOG_DEBUG_MASK >> GUC_LOG_DEBUG_SHIFT,
GUC_LOG_LOG_ALLOC_UNITS,
GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE,
"debug",
},
{
GUC_LOG_CAPTURE_MASK >> GUC_LOG_CAPTURE_SHIFT,
GUC_LOG_CAPTURE_ALLOC_UNITS,
GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE,
"capture",
}
};
s32 params[GUC_LOG_SECTIONS_LIMIT] = {
i915->params.guc_log_size_crash,
i915->params.guc_log_size_debug,
i915->params.guc_log_size_capture,
};
int i;

for (i = 0; i < GUC_LOG_SECTIONS_LIMIT; i++)
log->sizes[i].bytes = scale_log_param(log, sections + i, params[i]);

/* If debug size > 1MB then bump default crash size to keep the same units */
if (log->sizes[GUC_LOG_SECTIONS_DEBUG].bytes >= SZ_1M &&
(i915->params.guc_log_size_crash == -1) &&
GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE < SZ_1M)
log->sizes[GUC_LOG_SECTIONS_CRASH].bytes = SZ_1M;

/* Prepare the GuC API structure fields: */
for (i = 0; i < GUC_LOG_SECTIONS_LIMIT; i++) {
/* Convert to correct units */
if ((log->sizes[i].bytes % SZ_1M) == 0) {
log->sizes[i].units = SZ_1M;
log->sizes[i].flag = sections[i].flag;
} else {
log->sizes[i].units = SZ_4K;
log->sizes[i].flag = 0;
}

if (!IS_ALIGNED(log->sizes[i].bytes, log->sizes[i].units))
drm_err(&i915->drm, "Mis-aligned GuC log %s size: 0x%X vs 0x%X!",
sections[i].name, log->sizes[i].bytes, log->sizes[i].units);
log->sizes[i].count = log->sizes[i].bytes / log->sizes[i].units;

if (!log->sizes[i].count) {
drm_err(&i915->drm, "Zero GuC log %s size!", sections[i].name);
} else {
/* Size is +1 unit */
log->sizes[i].count--;
}

/* Clip to field size */
if (log->sizes[i].count > sections[i].max) {
drm_err(&i915->drm, "GuC log %s size too large: %d vs %d!",
sections[i].name, log->sizes[i].count + 1, sections[i].max + 1);
log->sizes[i].count = sections[i].max;
}
}

if (log->sizes[GUC_LOG_SECTIONS_CRASH].units != log->sizes[GUC_LOG_SECTIONS_DEBUG].units) {
drm_err(&i915->drm, "Unit mis-match for GuC log crash and debug sections: %d vs %d!",
log->sizes[GUC_LOG_SECTIONS_CRASH].units,
log->sizes[GUC_LOG_SECTIONS_DEBUG].units);
log->sizes[GUC_LOG_SECTIONS_CRASH].units = log->sizes[GUC_LOG_SECTIONS_DEBUG].units;
log->sizes[GUC_LOG_SECTIONS_CRASH].count = 0;
}

log->sizes_initialised = true;
}

static void guc_log_init_sizes(struct intel_guc_log *log)
{
if (log->sizes_initialised)
return;

_guc_log_init_sizes(log);
}

static u32 intel_guc_log_section_size_crash(struct intel_guc_log *log)
{
guc_log_init_sizes(log);

return log->sizes[GUC_LOG_SECTIONS_CRASH].bytes;
}

static u32 intel_guc_log_section_size_debug(struct intel_guc_log *log)
{
guc_log_init_sizes(log);

return log->sizes[GUC_LOG_SECTIONS_DEBUG].bytes;
}

u32 intel_guc_log_section_size_capture(struct intel_guc_log *log)
{
guc_log_init_sizes(log);

return log->sizes[GUC_LOG_SECTIONS_CAPTURE].bytes;
}

static u32 intel_guc_log_size(struct intel_guc_log *log)
{
/*
Expand All @@ -38,7 +188,10 @@ static u32 intel_guc_log_size(struct intel_guc_log *log)
* | Capture logs |
* +===============================+ + CAPTURE_SIZE
*/
return PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE + CAPTURE_BUFFER_SIZE;
return PAGE_SIZE +
intel_guc_log_section_size_crash(log) +
intel_guc_log_section_size_debug(log) +
intel_guc_log_section_size_capture(log);
}

/**
Expand Down Expand Up @@ -165,7 +318,8 @@ static void guc_move_to_next_buf(struct intel_guc_log *log)
smp_wmb();

/* All data has been written, so now move the offset of sub buffer. */
relay_reserve(log->relay.channel, log->vma->obj->base.size - CAPTURE_BUFFER_SIZE);
relay_reserve(log->relay.channel, log->vma->obj->base.size -
intel_guc_log_section_size_capture(log));

/* Switch to the next sub buffer */
relay_flush(log->relay.channel);
Expand Down Expand Up @@ -210,31 +364,33 @@ bool intel_guc_check_log_buf_overflow(struct intel_guc_log *log,
return overflow;
}

unsigned int intel_guc_get_log_buffer_size(enum guc_log_buffer_type type)
unsigned int intel_guc_get_log_buffer_size(struct intel_guc_log *log,
enum guc_log_buffer_type type)
{
switch (type) {
case GUC_DEBUG_LOG_BUFFER:
return DEBUG_BUFFER_SIZE;
return intel_guc_log_section_size_debug(log);
case GUC_CRASH_DUMP_LOG_BUFFER:
return CRASH_BUFFER_SIZE;
return intel_guc_log_section_size_crash(log);
case GUC_CAPTURE_LOG_BUFFER:
return CAPTURE_BUFFER_SIZE;
return intel_guc_log_section_size_capture(log);
default:
MISSING_CASE(type);
}

return 0;
}

size_t intel_guc_get_log_buffer_offset(enum guc_log_buffer_type type)
size_t intel_guc_get_log_buffer_offset(struct intel_guc_log *log,
enum guc_log_buffer_type type)
{
enum guc_log_buffer_type i;
size_t offset = PAGE_SIZE;/* for the log_buffer_states */

for (i = GUC_DEBUG_LOG_BUFFER; i < GUC_MAX_LOG_BUFFER; ++i) {
if (i == type)
break;
offset += intel_guc_get_log_buffer_size(i);
offset += intel_guc_get_log_buffer_size(log, i);
}

return offset;
Expand Down Expand Up @@ -285,7 +441,7 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log)
*/
memcpy(&log_buf_state_local, log_buf_state,
sizeof(struct guc_log_buffer_state));
buffer_size = intel_guc_get_log_buffer_size(type);
buffer_size = intel_guc_get_log_buffer_size(log, type);
read_offset = log_buf_state_local.read_ptr;
write_offset = log_buf_state_local.sampled_write_ptr;
full_cnt = log_buf_state_local.buffer_full_cnt;
Expand Down Expand Up @@ -400,7 +556,7 @@ static int guc_log_relay_create(struct intel_guc_log *log)
* Keep the size of sub buffers same as shared log buffer
* but GuC log-events excludes the error-state-capture logs
*/
subbuf_size = log->vma->size - CAPTURE_BUFFER_SIZE;
subbuf_size = log->vma->size - intel_guc_log_section_size_capture(log);

/*
* Store up to 8 snapshots, which is large enough to buffer sufficient
Expand Down
Loading

0 comments on commit 8ad0152

Please sign in to comment.