summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/xe/xe_guc_ct.c
diff options
context:
space:
mode:
authorRodrigo Vivi <rodrigo.vivi@intel.com>2023-05-16 17:54:08 +0300
committerRodrigo Vivi <rodrigo.vivi@intel.com>2023-12-20 02:33:52 +0300
commita7ca8157ec7b59b597ba47cb98eaa82cb0b1d4af (patch)
treec788657d06ebb36f1b1e1d8796763f6fb59dc710 /drivers/gpu/drm/xe/xe_guc_ct.c
parent656d29506ca89b4af1d2380ff4cab15f40ae9e19 (diff)
downloadlinux-a7ca8157ec7b59b597ba47cb98eaa82cb0b1d4af.tar.xz
drm/xe: Extract non mapped regions out of GuC CTB into its own struct.
No functional change here. The goal is to have a clear split between the mapped portions of the CTB and the static information, so we can easily capture snapshots that will be used for later read out with the devcoredump infrastructure. Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Diffstat (limited to 'drivers/gpu/drm/xe/xe_guc_ct.c')
-rw-r--r--drivers/gpu/drm/xe/xe_guc_ct.c155
1 files changed, 81 insertions, 74 deletions
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
index 9055ff133a7c..e16e5fe37ed4 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.c
+++ b/drivers/gpu/drm/xe/xe_guc_ct.c
@@ -172,13 +172,14 @@ int xe_guc_ct_init(struct xe_guc_ct *ct)
static void guc_ct_ctb_h2g_init(struct xe_device *xe, struct guc_ctb *h2g,
struct iosys_map *map)
{
- h2g->size = CTB_H2G_BUFFER_SIZE / sizeof(u32);
- h2g->resv_space = 0;
- h2g->tail = 0;
- h2g->head = 0;
- h2g->space = CIRC_SPACE(h2g->tail, h2g->head, h2g->size) -
- h2g->resv_space;
- h2g->broken = false;
+ h2g->info.size = CTB_H2G_BUFFER_SIZE / sizeof(u32);
+ h2g->info.resv_space = 0;
+ h2g->info.tail = 0;
+ h2g->info.head = 0;
+ h2g->info.space = CIRC_SPACE(h2g->info.tail, h2g->info.head,
+ h2g->info.size) -
+ h2g->info.resv_space;
+ h2g->info.broken = false;
h2g->desc = *map;
xe_map_memset(xe, &h2g->desc, 0, 0, sizeof(struct guc_ct_buffer_desc));
@@ -189,13 +190,14 @@ static void guc_ct_ctb_h2g_init(struct xe_device *xe, struct guc_ctb *h2g,
static void guc_ct_ctb_g2h_init(struct xe_device *xe, struct guc_ctb *g2h,
struct iosys_map *map)
{
- g2h->size = CTB_G2H_BUFFER_SIZE / sizeof(u32);
- g2h->resv_space = G2H_ROOM_BUFFER_SIZE / sizeof(u32);
- g2h->head = 0;
- g2h->tail = 0;
- g2h->space = CIRC_SPACE(g2h->tail, g2h->head, g2h->size) -
- g2h->resv_space;
- g2h->broken = false;
+ g2h->info.size = CTB_G2H_BUFFER_SIZE / sizeof(u32);
+ g2h->info.resv_space = G2H_ROOM_BUFFER_SIZE / sizeof(u32);
+ g2h->info.head = 0;
+ g2h->info.tail = 0;
+ g2h->info.space = CIRC_SPACE(g2h->info.tail, g2h->info.head,
+ g2h->info.size) -
+ g2h->info.resv_space;
+ g2h->info.broken = false;
g2h->desc = IOSYS_MAP_INIT_OFFSET(map, CTB_DESC_SIZE);
xe_map_memset(xe, &g2h->desc, 0, 0, sizeof(struct guc_ct_buffer_desc));
@@ -212,7 +214,7 @@ static int guc_ct_ctb_h2g_register(struct xe_guc_ct *ct)
desc_addr = xe_bo_ggtt_addr(ct->bo);
ctb_addr = xe_bo_ggtt_addr(ct->bo) + CTB_DESC_SIZE * 2;
- size = ct->ctbs.h2g.size * sizeof(u32);
+ size = ct->ctbs.h2g.info.size * sizeof(u32);
err = xe_guc_self_cfg64(guc,
GUC_KLV_SELF_CFG_H2G_CTB_DESCRIPTOR_ADDR_KEY,
@@ -240,7 +242,7 @@ static int guc_ct_ctb_g2h_register(struct xe_guc_ct *ct)
desc_addr = xe_bo_ggtt_addr(ct->bo) + CTB_DESC_SIZE;
ctb_addr = xe_bo_ggtt_addr(ct->bo) + CTB_DESC_SIZE * 2 +
CTB_H2G_BUFFER_SIZE;
- size = ct->ctbs.g2h.size * sizeof(u32);
+ size = ct->ctbs.g2h.info.size * sizeof(u32);
err = xe_guc_self_cfg64(guc,
GUC_KLV_SELF_CFG_G2H_CTB_DESCRIPTOR_ADDR_KEY,
@@ -329,11 +331,12 @@ static bool h2g_has_room(struct xe_guc_ct *ct, u32 cmd_len)
lockdep_assert_held(&ct->lock);
- if (cmd_len > h2g->space) {
- h2g->head = desc_read(ct_to_xe(ct), h2g, head);
- h2g->space = CIRC_SPACE(h2g->tail, h2g->head, h2g->size) -
- h2g->resv_space;
- if (cmd_len > h2g->space)
+ if (cmd_len > h2g->info.space) {
+ h2g->info.head = desc_read(ct_to_xe(ct), h2g, head);
+ h2g->info.space = CIRC_SPACE(h2g->info.tail, h2g->info.head,
+ h2g->info.size) -
+ h2g->info.resv_space;
+ if (cmd_len > h2g->info.space)
return false;
}
@@ -344,7 +347,7 @@ static bool g2h_has_room(struct xe_guc_ct *ct, u32 g2h_len)
{
lockdep_assert_held(&ct->lock);
- return ct->ctbs.g2h.space > g2h_len;
+ return ct->ctbs.g2h.info.space > g2h_len;
}
static int has_room(struct xe_guc_ct *ct, u32 cmd_len, u32 g2h_len)
@@ -360,16 +363,16 @@ static int has_room(struct xe_guc_ct *ct, u32 cmd_len, u32 g2h_len)
static void h2g_reserve_space(struct xe_guc_ct *ct, u32 cmd_len)
{
lockdep_assert_held(&ct->lock);
- ct->ctbs.h2g.space -= cmd_len;
+ ct->ctbs.h2g.info.space -= cmd_len;
}
static void g2h_reserve_space(struct xe_guc_ct *ct, u32 g2h_len, u32 num_g2h)
{
- XE_BUG_ON(g2h_len > ct->ctbs.g2h.space);
+ XE_BUG_ON(g2h_len > ct->ctbs.g2h.info.space);
if (g2h_len) {
spin_lock_irq(&ct->fast_lock);
- ct->ctbs.g2h.space -= g2h_len;
+ ct->ctbs.g2h.info.space -= g2h_len;
ct->g2h_outstanding += num_g2h;
spin_unlock_irq(&ct->fast_lock);
}
@@ -378,10 +381,10 @@ static void g2h_reserve_space(struct xe_guc_ct *ct, u32 g2h_len, u32 num_g2h)
static void __g2h_release_space(struct xe_guc_ct *ct, u32 g2h_len)
{
lockdep_assert_held(&ct->fast_lock);
- XE_WARN_ON(ct->ctbs.g2h.space + g2h_len >
- ct->ctbs.g2h.size - ct->ctbs.g2h.resv_space);
+ XE_WARN_ON(ct->ctbs.g2h.info.space + g2h_len >
+ ct->ctbs.g2h.info.size - ct->ctbs.g2h.info.resv_space);
- ct->ctbs.g2h.space += g2h_len;
+ ct->ctbs.g2h.info.space += g2h_len;
--ct->g2h_outstanding;
}
@@ -400,20 +403,21 @@ static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len,
u32 cmd[GUC_CTB_MSG_MAX_LEN / sizeof(u32)];
u32 cmd_len = len + GUC_CTB_HDR_LEN;
u32 cmd_idx = 0, i;
- u32 tail = h2g->tail;
+ u32 tail = h2g->info.tail;
struct iosys_map map = IOSYS_MAP_INIT_OFFSET(&h2g->cmds,
tail * sizeof(u32));
lockdep_assert_held(&ct->lock);
XE_BUG_ON(len * sizeof(u32) > GUC_CTB_MSG_MAX_LEN);
- XE_BUG_ON(tail > h2g->size);
+ XE_BUG_ON(tail > h2g->info.size);
/* Command will wrap, zero fill (NOPs), return and check credits again */
- if (tail + cmd_len > h2g->size) {
- xe_map_memset(xe, &map, 0, 0, (h2g->size - tail) * sizeof(u32));
- h2g_reserve_space(ct, (h2g->size - tail));
- h2g->tail = 0;
- desc_write(xe, h2g, tail, h2g->tail);
+ if (tail + cmd_len > h2g->info.size) {
+ xe_map_memset(xe, &map, 0, 0,
+ (h2g->info.size - tail) * sizeof(u32));
+ h2g_reserve_space(ct, (h2g->info.size - tail));
+ h2g->info.tail = 0;
+ desc_write(xe, h2g, tail, h2g->info.tail);
return -EAGAIN;
}
@@ -445,11 +449,11 @@ static int h2g_write(struct xe_guc_ct *ct, const u32 *action, u32 len,
xe_device_wmb(ct_to_xe(ct));
/* Update local copies */
- h2g->tail = (tail + cmd_len) % h2g->size;
+ h2g->info.tail = (tail + cmd_len) % h2g->info.size;
h2g_reserve_space(ct, cmd_len);
/* Update descriptor */
- desc_write(xe, h2g, tail, h2g->tail);
+ desc_write(xe, h2g, tail, h2g->info.tail);
return 0;
}
@@ -466,7 +470,7 @@ static int __guc_ct_send_locked(struct xe_guc_ct *ct, const u32 *action,
XE_BUG_ON(!g2h_len && num_g2h);
lockdep_assert_held(&ct->lock);
- if (unlikely(ct->ctbs.h2g.broken)) {
+ if (unlikely(ct->ctbs.h2g.info.broken)) {
ret = -EPIPE;
goto out;
}
@@ -554,8 +558,9 @@ try_again:
if (sleep_period_ms == 1024)
goto broken;
- trace_xe_guc_ct_h2g_flow_control(h2g->head, h2g->tail,
- h2g->size, h2g->space,
+ trace_xe_guc_ct_h2g_flow_control(h2g->info.head, h2g->info.tail,
+ h2g->info.size,
+ h2g->info.space,
len + GUC_CTB_HDR_LEN);
msleep(sleep_period_ms);
sleep_period_ms <<= 1;
@@ -565,15 +570,16 @@ try_again:
struct xe_device *xe = ct_to_xe(ct);
struct guc_ctb *g2h = &ct->ctbs.g2h;
- trace_xe_guc_ct_g2h_flow_control(g2h->head,
+ trace_xe_guc_ct_g2h_flow_control(g2h->info.head,
desc_read(xe, g2h, tail),
- g2h->size, g2h->space,
+ g2h->info.size,
+ g2h->info.space,
g2h_fence ?
GUC_CTB_HXG_MSG_MAX_LEN :
g2h_len);
#define g2h_avail(ct) \
- (desc_read(ct_to_xe(ct), (&ct->ctbs.g2h), tail) != ct->ctbs.g2h.head)
+ (desc_read(ct_to_xe(ct), (&ct->ctbs.g2h), tail) != ct->ctbs.g2h.info.head)
if (!wait_event_timeout(ct->wq, !ct->g2h_outstanding ||
g2h_avail(ct), HZ))
goto broken;
@@ -590,7 +596,7 @@ try_again:
broken:
drm_err(drm, "No forward process on H2G, reset required");
xe_guc_ct_print(ct, &p);
- ct->ctbs.h2g.broken = true;
+ ct->ctbs.h2g.info.broken = true;
return -EDEADLK;
}
@@ -656,7 +662,7 @@ static bool retry_failure(struct xe_guc_ct *ct, int ret)
return false;
#define ct_alive(ct) \
- (ct->enabled && !ct->ctbs.h2g.broken && !ct->ctbs.g2h.broken)
+ (ct->enabled && !ct->ctbs.h2g.info.broken && !ct->ctbs.g2h.info.broken)
if (!wait_event_interruptible_timeout(ct->wq, ct_alive(ct), HZ * 5))
return false;
#undef ct_alive
@@ -821,7 +827,7 @@ static int parse_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
drm_err(&xe->drm,
"G2H channel broken on read, origin=%d, reset required\n",
origin);
- ct->ctbs.g2h.broken = true;
+ ct->ctbs.g2h.info.broken = true;
return -EPROTO;
}
@@ -840,7 +846,7 @@ static int parse_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
drm_err(&xe->drm,
"G2H channel broken on read, type=%d, reset required\n",
type);
- ct->ctbs.g2h.broken = true;
+ ct->ctbs.g2h.info.broken = true;
ret = -EOPNOTSUPP;
}
@@ -919,36 +925,37 @@ static int g2h_read(struct xe_guc_ct *ct, u32 *msg, bool fast_path)
if (!ct->enabled)
return -ENODEV;
- if (g2h->broken)
+ if (g2h->info.broken)
return -EPIPE;
/* Calculate DW available to read */
tail = desc_read(xe, g2h, tail);
- avail = tail - g2h->head;
+ avail = tail - g2h->info.head;
if (unlikely(avail == 0))
return 0;
if (avail < 0)
- avail += g2h->size;
+ avail += g2h->info.size;
/* Read header */
- xe_map_memcpy_from(xe, msg, &g2h->cmds, sizeof(u32) * g2h->head, sizeof(u32));
+ xe_map_memcpy_from(xe, msg, &g2h->cmds, sizeof(u32) * g2h->info.head,
+ sizeof(u32));
len = FIELD_GET(GUC_CTB_MSG_0_NUM_DWORDS, msg[0]) + GUC_CTB_MSG_MIN_LEN;
if (len > avail) {
drm_err(&xe->drm,
"G2H channel broken on read, avail=%d, len=%d, reset required\n",
avail, len);
- g2h->broken = true;
+ g2h->info.broken = true;
return -EPROTO;
}
- head = (g2h->head + 1) % g2h->size;
+ head = (g2h->info.head + 1) % g2h->info.size;
avail = len - 1;
/* Read G2H message */
- if (avail + head > g2h->size) {
- u32 avail_til_wrap = g2h->size - head;
+ if (avail + head > g2h->info.size) {
+ u32 avail_til_wrap = g2h->info.size - head;
xe_map_memcpy_from(xe, msg + 1,
&g2h->cmds, sizeof(u32) * head,
@@ -983,8 +990,8 @@ static int g2h_read(struct xe_guc_ct *ct, u32 *msg, bool fast_path)
}
/* Update local / descriptor header */
- g2h->head = (head + avail) % g2h->size;
- desc_write(xe, g2h, head, g2h->head);
+ g2h->info.head = (head + avail) % g2h->info.size;
+ desc_write(xe, g2h, head, g2h->info.head);
return len;
}
@@ -1093,12 +1100,12 @@ static void guc_ct_ctb_print(struct xe_device *xe, struct guc_ctb *ctb,
{
u32 head, tail;
- drm_printf(p, "\tsize: %d\n", ctb->size);
- drm_printf(p, "\tresv_space: %d\n", ctb->resv_space);
- drm_printf(p, "\thead: %d\n", ctb->head);
- drm_printf(p, "\ttail: %d\n", ctb->tail);
- drm_printf(p, "\tspace: %d\n", ctb->space);
- drm_printf(p, "\tbroken: %d\n", ctb->broken);
+ drm_printf(p, "\tsize: %d\n", ctb->info.size);
+ drm_printf(p, "\tresv_space: %d\n", ctb->info.resv_space);
+ drm_printf(p, "\thead: %d\n", ctb->info.head);
+ drm_printf(p, "\ttail: %d\n", ctb->info.tail);
+ drm_printf(p, "\tspace: %d\n", ctb->info.space);
+ drm_printf(p, "\tbroken: %d\n", ctb->info.broken);
head = desc_read(xe, ctb, head);
tail = desc_read(xe, ctb, tail);
@@ -1114,7 +1121,7 @@ static void guc_ct_ctb_print(struct xe_device *xe, struct guc_ctb *ctb,
drm_printf(p, "\tcmd[%d]: 0x%08x\n", head,
xe_map_rd(xe, &map, 0, u32));
++head;
- if (head == ctb->size) {
+ if (head == ctb->info.size) {
head = 0;
map = ctb->cmds;
} else {
@@ -1168,12 +1175,12 @@ void xe_guc_ct_selftest(struct xe_guc_ct *ct, struct drm_printer *p)
if (!ret) {
xe_guc_ct_irq_handler(ct);
msleep(200);
- if (g2h->space !=
- CIRC_SPACE(0, 0, g2h->size) - g2h->resv_space) {
+ if (g2h->info.space !=
+ CIRC_SPACE(0, 0, g2h->info.size) - g2h->info.resv_space) {
drm_printf(p, "Mismatch on space %d, %d\n",
- g2h->space,
- CIRC_SPACE(0, 0, g2h->size) -
- g2h->resv_space);
+ g2h->info.space,
+ CIRC_SPACE(0, 0, g2h->info.size) -
+ g2h->info.resv_space);
ret = -EIO;
}
if (ct->g2h_outstanding) {
@@ -1185,12 +1192,12 @@ void xe_guc_ct_selftest(struct xe_guc_ct *ct, struct drm_printer *p)
/* Check failure path for blocking CTs too */
xe_guc_ct_send_block(ct, bad_action, ARRAY_SIZE(bad_action));
- if (g2h->space !=
- CIRC_SPACE(0, 0, g2h->size) - g2h->resv_space) {
+ if (g2h->info.space !=
+ CIRC_SPACE(0, 0, g2h->info.size) - g2h->info.resv_space) {
drm_printf(p, "Mismatch on space %d, %d\n",
- g2h->space,
- CIRC_SPACE(0, 0, g2h->size) -
- g2h->resv_space);
+ g2h->info.space,
+ CIRC_SPACE(0, 0, g2h->info.size) -
+ g2h->info.resv_space);
ret = -EIO;
}
if (ct->g2h_outstanding) {