114 lines
2.5 KiB
C
114 lines
2.5 KiB
C
|
// SPDX-License-Identifier: MIT
|
||
|
/*
|
||
|
* Copyright © 2022 Intel Corporation
|
||
|
*/
|
||
|
|
||
|
#include "xe_bb.h"
|
||
|
|
||
|
#include "instructions/xe_mi_commands.h"
|
||
|
#include "xe_assert.h"
|
||
|
#include "xe_device.h"
|
||
|
#include "xe_exec_queue_types.h"
|
||
|
#include "xe_gt.h"
|
||
|
#include "xe_hw_fence.h"
|
||
|
#include "xe_sa.h"
|
||
|
#include "xe_sched_job.h"
|
||
|
#include "xe_vm_types.h"
|
||
|
|
||
|
static int bb_prefetch(struct xe_gt *gt)
|
||
|
{
|
||
|
struct xe_device *xe = gt_to_xe(gt);
|
||
|
|
||
|
if (GRAPHICS_VERx100(xe) >= 1250 && !xe_gt_is_media_type(gt))
|
||
|
/*
|
||
|
* RCS and CCS require 1K, although other engines would be
|
||
|
* okay with 512.
|
||
|
*/
|
||
|
return SZ_1K;
|
||
|
else
|
||
|
return SZ_512;
|
||
|
}
|
||
|
|
||
|
struct xe_bb *xe_bb_new(struct xe_gt *gt, u32 dwords, bool usm)
|
||
|
{
|
||
|
struct xe_tile *tile = gt_to_tile(gt);
|
||
|
struct xe_bb *bb = kmalloc(sizeof(*bb), GFP_KERNEL);
|
||
|
int err;
|
||
|
|
||
|
if (!bb)
|
||
|
return ERR_PTR(-ENOMEM);
|
||
|
|
||
|
/*
|
||
|
* We need to allocate space for the requested number of dwords,
|
||
|
* one additional MI_BATCH_BUFFER_END dword, and additional buffer
|
||
|
* space to accomodate the platform-specific hardware prefetch
|
||
|
* requirements.
|
||
|
*/
|
||
|
bb->bo = xe_sa_bo_new(!usm ? tile->mem.kernel_bb_pool : gt->usm.bb_pool,
|
||
|
4 * (dwords + 1) + bb_prefetch(gt));
|
||
|
if (IS_ERR(bb->bo)) {
|
||
|
err = PTR_ERR(bb->bo);
|
||
|
goto err;
|
||
|
}
|
||
|
|
||
|
bb->cs = xe_sa_bo_cpu_addr(bb->bo);
|
||
|
bb->len = 0;
|
||
|
|
||
|
return bb;
|
||
|
err:
|
||
|
kfree(bb);
|
||
|
return ERR_PTR(err);
|
||
|
}
|
||
|
|
||
|
static struct xe_sched_job *
|
||
|
__xe_bb_create_job(struct xe_exec_queue *q, struct xe_bb *bb, u64 *addr)
|
||
|
{
|
||
|
u32 size = drm_suballoc_size(bb->bo);
|
||
|
|
||
|
if (bb->len == 0 || bb->cs[bb->len - 1] != MI_BATCH_BUFFER_END)
|
||
|
bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
|
||
|
|
||
|
xe_gt_assert(q->gt, bb->len * 4 + bb_prefetch(q->gt) <= size);
|
||
|
|
||
|
xe_sa_bo_flush_write(bb->bo);
|
||
|
|
||
|
return xe_sched_job_create(q, addr);
|
||
|
}
|
||
|
|
||
|
struct xe_sched_job *xe_bb_create_migration_job(struct xe_exec_queue *q,
|
||
|
struct xe_bb *bb,
|
||
|
u64 batch_base_ofs,
|
||
|
u32 second_idx)
|
||
|
{
|
||
|
u64 addr[2] = {
|
||
|
batch_base_ofs + drm_suballoc_soffset(bb->bo),
|
||
|
batch_base_ofs + drm_suballoc_soffset(bb->bo) +
|
||
|
4 * second_idx,
|
||
|
};
|
||
|
|
||
|
xe_gt_assert(q->gt, second_idx <= bb->len);
|
||
|
xe_gt_assert(q->gt, xe_sched_job_is_migration(q));
|
||
|
xe_gt_assert(q->gt, q->width == 1);
|
||
|
|
||
|
return __xe_bb_create_job(q, bb, addr);
|
||
|
}
|
||
|
|
||
|
struct xe_sched_job *xe_bb_create_job(struct xe_exec_queue *q,
|
||
|
struct xe_bb *bb)
|
||
|
{
|
||
|
u64 addr = xe_sa_bo_gpu_addr(bb->bo);
|
||
|
|
||
|
xe_gt_assert(q->gt, !xe_sched_job_is_migration(q));
|
||
|
xe_gt_assert(q->gt, q->width == 1);
|
||
|
return __xe_bb_create_job(q, bb, &addr);
|
||
|
}
|
||
|
|
||
|
void xe_bb_free(struct xe_bb *bb, struct dma_fence *fence)
|
||
|
{
|
||
|
if (!bb)
|
||
|
return;
|
||
|
|
||
|
xe_sa_bo_free(bb->bo, fence);
|
||
|
kfree(bb);
|
||
|
}
|