// SPDX-License-Identifier: MIT
/*
* Copyright © 2022 Intel Corporation
*/
#include "xe_guc_ct.h"
#include <linux/bitfield.h>
#include <linux/circ_buf.h>
#include <linux/delay.h>
#include <drm/drm_managed.h>
#include "abi/guc_actions_abi.h"
#include "abi/guc_klvs_abi.h"
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_gt.h"
#include "xe_gt_pagefault.h"
#include "xe_gt_tlb_invalidation.h"
#include "xe_guc.h"
#include "xe_guc_submit.h"
#include "xe_map.h"
#include "xe_pm.h"
#include "xe_trace.h"
/* Used when a CT send wants to block and / or receive data */
struct g2h_fence {
u32 *response_buffer;
u32 seqno;
u16 response_len;
u16 error;
u16 hint;
u16 reason;
bool retry;
bool fail;
bool done;
};
static void g2h_fence_init(struct g2h_fence *g2h_fence, u32 *response_buffer)
{
g2h_fence->response_buffer = response_buffer;
g2h_fence->response_len = 0;
g2h_fence->fail = false;
g2h_fence->retry = false;
g2h_fence->done = false;
g2h_fence->seqno = ~0x0;
}
static bool g2h_fence_needs_alloc(struct g2h_fence *g2h_fence)
{
return g2h_fence->seqno == ~0x0;
}
static struct xe_guc *
ct_to_guc(struct xe_guc_ct *ct)
{
return container_of(ct, struct xe_guc, ct);
}
static struct xe_gt *
ct_to_gt(struct xe_guc_ct *ct)
{
return container_of(ct, struct xe_gt, uc.guc.ct);
}
static struct xe_device *
ct_to_xe(struct xe_guc_ct *ct)
{
return gt_to_xe(ct_to_gt(ct));
}
/**
* DOC: GuC CTB Blob
*
* We allocate single blob to hold both CTB descriptors and buffers:
*
* +--------+-----------------------------------------------+------+
* | offset | contents | size |
* +========+===============================================+======+
* | 0x0000 | H2G CTB Descriptor (send) | |
* +--------+-----------------------------------------------+ 4K |
* | 0x0800 | G2H CTB Descriptor (g2h) | |
* +--------+-----------------------------------------------+------+
* | 0x1000 | H2G CT Buffer (send) | n*4K |
* | | | |
* +--------+-----------------------------------------------+------+
* | 0x1000 | G2H CT Buffer (g2h) | m*4K |
* | + n*4K | | |
* +--------+-----------------------------------------------+------+
*
* Size of each ``CT Buffer`` must be multiple of 4K.
* We don't expect too many messages in flight at any time, unless we are
* using the GuC submission. In that case each request requires a minimum
* 2 dwords which gives us a maximum 256 queue'd requests. Hopefully this
* enough space to avoid backpressure on the driver. We increase the size
* of the receive buffer (relative to the send) to ensure a G2H response
* CTB has a landing spot.
*/
#define CTB_DESC_SIZE ALIGN(sizeof(struct guc_ct_buffer_desc), SZ_2K)
#define CTB_H2G_BUFFER_SIZE (SZ_4K)
#define CTB_G2H_BUFFER_SIZE (4 * CTB_H2G_BUFFER_SIZE)
#define G2H_ROOM_BUFFER_SIZE (CTB_G2H_BUFFER_SIZE / 4)
static size_t guc_ct_size(void)
{
return 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE +
CTB_G2H_BUFFER_SIZE;
}
static void guc_ct_fini(struct drm_device *drm, void *arg)
{
struct xe_guc_ct *ct = arg;
xa_destroy(&ct->fence_lookup);
}
static