#include <linux/circ_buf.h>
#include <linux/ktime.h>
#include <linux/time64.h>
#include <linux/string_helpers.h>
#include <linux/timekeeping.h>
#include "i915_drv.h"
#include "intel_guc_ct.h"
#include "intel_guc_print.h"
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
enum { … };
static void ct_dead_ct_worker_func(struct work_struct *w);
#define CT_DEAD(ct, reason) …
#else
#define CT_DEAD …
#endif
static inline struct intel_guc *ct_to_guc(struct intel_guc_ct *ct)
{ … }
#define CT_ERROR(_ct, _fmt, ...) …
#ifdef CONFIG_DRM_I915_DEBUG_GUC
#define CT_DEBUG(_ct, _fmt, ...) …
#else
#define CT_DEBUG …
#endif
#define CT_PROBE_ERROR(_ct, _fmt, ...) …
#define CTB_DESC_SIZE …
#define CTB_H2G_BUFFER_SIZE …
#define CTB_G2H_BUFFER_SIZE …
#define G2H_ROOM_BUFFER_SIZE …
struct ct_request { … };
struct ct_incoming_msg { … };
enum { … };
enum { … };
long intel_guc_ct_max_queue_time_jiffies(void)
{ … }
static void ct_receive_tasklet_func(struct tasklet_struct *t);
static void ct_incoming_request_worker_func(struct work_struct *w);
void intel_guc_ct_init_early(struct intel_guc_ct *ct)
{ … }
static void guc_ct_buffer_desc_init(struct guc_ct_buffer_desc *desc)
{ … }
static void guc_ct_buffer_reset(struct intel_guc_ct_buffer *ctb)
{ … }
static void guc_ct_buffer_init(struct intel_guc_ct_buffer *ctb,
struct guc_ct_buffer_desc *desc,
u32 *cmds, u32 size_in_bytes, u32 resv_space)
{ … }
static int guc_action_control_ctb(struct intel_guc *guc, u32 control)
{ … }
static int ct_control_enable(struct intel_guc_ct *ct, bool enable)
{ … }
static int ct_register_buffer(struct intel_guc_ct *ct, bool send,
u32 desc_addr, u32 buff_addr, u32 size)
{ … }
int intel_guc_ct_init(struct intel_guc_ct *ct)
{ … }
void intel_guc_ct_fini(struct intel_guc_ct *ct)
{ … }
int intel_guc_ct_enable(struct intel_guc_ct *ct)
{ … }
void intel_guc_ct_disable(struct intel_guc_ct *ct)
{ … }
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
static void ct_track_lost_and_found(struct intel_guc_ct *ct, u32 fence, u32 action)
{
unsigned int lost = fence % ARRAY_SIZE(ct->requests.lost_and_found);
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
unsigned long entries[SZ_32];
unsigned int n;
n = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
ct->requests.lost_and_found[lost].stack = stack_depot_save(entries, n, GFP_NOWAIT);
#endif
ct->requests.lost_and_found[lost].fence = fence;
ct->requests.lost_and_found[lost].action = action;
}
#endif
static u32 ct_get_next_fence(struct intel_guc_ct *ct)
{ … }
static int ct_write(struct intel_guc_ct *ct,
const u32 *action,
u32 len ,
u32 fence, u32 flags)
{ … }
static int wait_for_ct_request_update(struct intel_guc_ct *ct, struct ct_request *req, u32 *status)
{ … }
#define GUC_CTB_TIMEOUT_MS …
static inline bool ct_deadlocked(struct intel_guc_ct *ct)
{ … }
static inline bool g2h_has_room(struct intel_guc_ct *ct, u32 g2h_len_dw)
{ … }
static inline void g2h_reserve_space(struct intel_guc_ct *ct, u32 g2h_len_dw)
{ … }
static inline void g2h_release_space(struct intel_guc_ct *ct, u32 g2h_len_dw)
{ … }
static inline bool h2g_has_room(struct intel_guc_ct *ct, u32 len_dw)
{ … }
static int has_room_nb(struct intel_guc_ct *ct, u32 h2g_dw, u32 g2h_dw)
{ … }
#define G2H_LEN_DW(f) …
static int ct_send_nb(struct intel_guc_ct *ct,
const u32 *action,
u32 len,
u32 flags)
{ … }
static int ct_send(struct intel_guc_ct *ct,
const u32 *action,
u32 len,
u32 *response_buf,
u32 response_buf_size,
u32 *status)
{ … }
int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len,
u32 *response_buf, u32 response_buf_size, u32 flags)
{ … }
static struct ct_incoming_msg *ct_alloc_msg(u32 num_dwords)
{ … }
static void ct_free_msg(struct ct_incoming_msg *msg)
{ … }
static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg)
{ … }
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
static bool ct_check_lost_and_found(struct intel_guc_ct *ct, u32 fence)
{
unsigned int n;
char *buf = NULL;
bool found = false;
lockdep_assert_held(&ct->requests.lock);
for (n = 0; n < ARRAY_SIZE(ct->requests.lost_and_found); n++) {
if (ct->requests.lost_and_found[n].fence != fence)
continue;
found = true;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
buf = kmalloc(SZ_4K, GFP_NOWAIT);
if (buf && stack_depot_snprint(ct->requests.lost_and_found[n].stack,
buf, SZ_4K, 0)) {
CT_ERROR(ct, "Fence %u was used by action %#04x sent at\n%s",
fence, ct->requests.lost_and_found[n].action, buf);
break;
}
#endif
CT_ERROR(ct, "Fence %u was used by action %#04x\n",
fence, ct->requests.lost_and_found[n].action);
break;
}
kfree(buf);
return found;
}
#else
static bool ct_check_lost_and_found(struct intel_guc_ct *ct, u32 fence)
{ … }
#endif
static int ct_handle_response(struct intel_guc_ct *ct, struct ct_incoming_msg *response)
{ … }
static int ct_process_request(struct intel_guc_ct *ct, struct ct_incoming_msg *request)
{ … }
static bool ct_process_incoming_requests(struct intel_guc_ct *ct)
{ … }
static void ct_incoming_request_worker_func(struct work_struct *w)
{ … }
static int ct_handle_event(struct intel_guc_ct *ct, struct ct_incoming_msg *request)
{ … }
static int ct_handle_hxg(struct intel_guc_ct *ct, struct ct_incoming_msg *msg)
{ … }
static void ct_handle_msg(struct intel_guc_ct *ct, struct ct_incoming_msg *msg)
{ … }
static int ct_receive(struct intel_guc_ct *ct)
{ … }
static void ct_try_receive_message(struct intel_guc_ct *ct)
{ … }
static void ct_receive_tasklet_func(struct tasklet_struct *t)
{ … }
void intel_guc_ct_event_handler(struct intel_guc_ct *ct)
{ … }
void intel_guc_ct_print_info(struct intel_guc_ct *ct,
struct drm_printer *p)
{ … }
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
static void ct_dead_ct_worker_func(struct work_struct *w)
{ … }
#endif