mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 03:10:12 +00:00
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie: "A varied bunch of fixes, the radeon pull is probably a bit larger than I'd like, but it contains 2 weeks of stuff, and the Fiji fixes are a bit large, but they are Fiji specific. Otherwise: - mgag200: One cursor regression oops fix. - vc4: A few small fixes and cleanups. - core: Atomic fixes and Atomic helper fixes - i915: Revert for the backlight regression along with a bunch of fixes" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (58 commits) drm/atomic-helper: Check encoder/crtc constraints Revert "drm/i915: skip modeset if compatible for everyone." drm/mgag200: fix kernel hang in cursor code. drm/amdgpu: reserve/unreserve objects out of map/unmap operations drm/amdgpu: move bo_reserve out of amdgpu_vm_clear_bo drm/amdgpu: add lock for interval tree in vm drm/amdgpu: keep the owner for VMIDs drm/amdgpu: move VM manager clean into the VM code again drm/amdgpu: cleanup VM coding style drm/amdgpu: remove unused VM manager field drm/amdgpu: cleanup scheduler command submission drm/amdgpu: fix typo in firmware name drm/i915: Consider SPLL as another shared pll, v2. drm/i915: Fix gpu frequency change tracing drm/vc4: Make sure that planes aren't scaled. drm/vc4: Fix some failure to track __iomem decorations on pointers. drm/vc4: checking for NULL instead of IS_ERR drm/vc4: fix itnull.cocci warnings drm/vc4: fix platform_no_drv_owner.cocci warnings drm/vc4: vc4_plane_duplicate_state() can be static ...
This commit is contained in:
commit
c69bde78f0
40 changed files with 955 additions and 538 deletions
|
@ -389,7 +389,6 @@ struct amdgpu_clock {
|
|||
* Fences.
|
||||
*/
|
||||
struct amdgpu_fence_driver {
|
||||
struct amdgpu_ring *ring;
|
||||
uint64_t gpu_addr;
|
||||
volatile uint32_t *cpu_addr;
|
||||
/* sync_seq is protected by ring emission lock */
|
||||
|
@ -398,7 +397,7 @@ struct amdgpu_fence_driver {
|
|||
bool initialized;
|
||||
struct amdgpu_irq_src *irq_src;
|
||||
unsigned irq_type;
|
||||
struct delayed_work lockup_work;
|
||||
struct timer_list fallback_timer;
|
||||
wait_queue_head_t fence_queue;
|
||||
};
|
||||
|
||||
|
@ -917,8 +916,8 @@ struct amdgpu_ring {
|
|||
#define AMDGPU_VM_FAULT_STOP_ALWAYS 2
|
||||
|
||||
struct amdgpu_vm_pt {
|
||||
struct amdgpu_bo *bo;
|
||||
uint64_t addr;
|
||||
struct amdgpu_bo *bo;
|
||||
uint64_t addr;
|
||||
};
|
||||
|
||||
struct amdgpu_vm_id {
|
||||
|
@ -926,8 +925,6 @@ struct amdgpu_vm_id {
|
|||
uint64_t pd_gpu_addr;
|
||||
/* last flushed PD/PT update */
|
||||
struct fence *flushed_updates;
|
||||
/* last use of vmid */
|
||||
struct fence *last_id_use;
|
||||
};
|
||||
|
||||
struct amdgpu_vm {
|
||||
|
@ -957,24 +954,70 @@ struct amdgpu_vm {
|
|||
|
||||
/* for id and flush management per ring */
|
||||
struct amdgpu_vm_id ids[AMDGPU_MAX_RINGS];
|
||||
/* for interval tree */
|
||||
spinlock_t it_lock;
|
||||
};
|
||||
|
||||
struct amdgpu_vm_manager {
|
||||
struct fence *active[AMDGPU_NUM_VM];
|
||||
uint32_t max_pfn;
|
||||
struct {
|
||||
struct fence *active;
|
||||
atomic_long_t owner;
|
||||
} ids[AMDGPU_NUM_VM];
|
||||
|
||||
uint32_t max_pfn;
|
||||
/* number of VMIDs */
|
||||
unsigned nvm;
|
||||
unsigned nvm;
|
||||
/* vram base address for page table entry */
|
||||
u64 vram_base_offset;
|
||||
u64 vram_base_offset;
|
||||
/* is vm enabled? */
|
||||
bool enabled;
|
||||
/* for hw to save the PD addr on suspend/resume */
|
||||
uint32_t saved_table_addr[AMDGPU_NUM_VM];
|
||||
bool enabled;
|
||||
/* vm pte handling */
|
||||
const struct amdgpu_vm_pte_funcs *vm_pte_funcs;
|
||||
struct amdgpu_ring *vm_pte_funcs_ring;
|
||||
};
|
||||
|
||||
void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
|
||||
void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
|
||||
struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm,
|
||||
struct list_head *head);
|
||||
int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
||||
struct amdgpu_sync *sync);
|
||||
void amdgpu_vm_flush(struct amdgpu_ring *ring,
|
||||
struct amdgpu_vm *vm,
|
||||
struct fence *updates);
|
||||
void amdgpu_vm_fence(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm,
|
||||
struct fence *fence);
|
||||
uint64_t amdgpu_vm_map_gart(struct amdgpu_device *adev, uint64_t addr);
|
||||
int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm);
|
||||
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm);
|
||||
int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
struct amdgpu_sync *sync);
|
||||
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
struct ttm_mem_reg *mem);
|
||||
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo *bo);
|
||||
struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
|
||||
struct amdgpu_bo *bo);
|
||||
struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm,
|
||||
struct amdgpu_bo *bo);
|
||||
int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
uint64_t addr, uint64_t offset,
|
||||
uint64_t size, uint32_t flags);
|
||||
int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
uint64_t addr);
|
||||
void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va);
|
||||
int amdgpu_vm_free_job(struct amdgpu_job *job);
|
||||
|
||||
/*
|
||||
* context related structures
|
||||
*/
|
||||
|
@ -1211,6 +1254,7 @@ struct amdgpu_cs_parser {
|
|||
/* relocations */
|
||||
struct amdgpu_bo_list_entry *vm_bos;
|
||||
struct list_head validated;
|
||||
struct fence *fence;
|
||||
|
||||
struct amdgpu_ib *ibs;
|
||||
uint32_t num_ibs;
|
||||
|
@ -1226,7 +1270,7 @@ struct amdgpu_job {
|
|||
struct amdgpu_device *adev;
|
||||
struct amdgpu_ib *ibs;
|
||||
uint32_t num_ibs;
|
||||
struct mutex job_lock;
|
||||
void *owner;
|
||||
struct amdgpu_user_fence uf;
|
||||
int (*free_job)(struct amdgpu_job *job);
|
||||
};
|
||||
|
@ -2257,11 +2301,6 @@ void amdgpu_pci_config_reset(struct amdgpu_device *adev);
|
|||
bool amdgpu_card_posted(struct amdgpu_device *adev);
|
||||
void amdgpu_update_display_priority(struct amdgpu_device *adev);
|
||||
bool amdgpu_boot_test_post_card(struct amdgpu_device *adev);
|
||||
struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
|
||||
struct drm_file *filp,
|
||||
struct amdgpu_ctx *ctx,
|
||||
struct amdgpu_ib *ibs,
|
||||
uint32_t num_ibs);
|
||||
|
||||
int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data);
|
||||
int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
|
||||
|
@ -2318,49 +2357,6 @@ int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
|
|||
long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/*
|
||||
* vm
|
||||
*/
|
||||
int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
|
||||
void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
|
||||
struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm,
|
||||
struct list_head *head);
|
||||
int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
||||
struct amdgpu_sync *sync);
|
||||
void amdgpu_vm_flush(struct amdgpu_ring *ring,
|
||||
struct amdgpu_vm *vm,
|
||||
struct fence *updates);
|
||||
void amdgpu_vm_fence(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm,
|
||||
struct amdgpu_fence *fence);
|
||||
uint64_t amdgpu_vm_map_gart(struct amdgpu_device *adev, uint64_t addr);
|
||||
int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm);
|
||||
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm);
|
||||
int amdgpu_vm_clear_invalids(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm, struct amdgpu_sync *sync);
|
||||
int amdgpu_vm_bo_update(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
struct ttm_mem_reg *mem);
|
||||
void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo *bo);
|
||||
struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
|
||||
struct amdgpu_bo *bo);
|
||||
struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm,
|
||||
struct amdgpu_bo *bo);
|
||||
int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
uint64_t addr, uint64_t offset,
|
||||
uint64_t size, uint32_t flags);
|
||||
int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
uint64_t addr);
|
||||
void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va);
|
||||
int amdgpu_vm_free_job(struct amdgpu_job *job);
|
||||
/*
|
||||
* functions used by amdgpu_encoder.c
|
||||
*/
|
||||
|
|
|
@ -127,30 +127,6 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct amdgpu_cs_parser *amdgpu_cs_parser_create(struct amdgpu_device *adev,
|
||||
struct drm_file *filp,
|
||||
struct amdgpu_ctx *ctx,
|
||||
struct amdgpu_ib *ibs,
|
||||
uint32_t num_ibs)
|
||||
{
|
||||
struct amdgpu_cs_parser *parser;
|
||||
int i;
|
||||
|
||||
parser = kzalloc(sizeof(struct amdgpu_cs_parser), GFP_KERNEL);
|
||||
if (!parser)
|
||||
return NULL;
|
||||
|
||||
parser->adev = adev;
|
||||
parser->filp = filp;
|
||||
parser->ctx = ctx;
|
||||
parser->ibs = ibs;
|
||||
parser->num_ibs = num_ibs;
|
||||
for (i = 0; i < num_ibs; i++)
|
||||
ibs[i].ctx = ctx;
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
|
||||
{
|
||||
union drm_amdgpu_cs *cs = data;
|
||||
|
@ -463,8 +439,18 @@ static int cmp_size_smaller_first(void *priv, struct list_head *a,
|
|||
return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages;
|
||||
}
|
||||
|
||||
static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int error, bool backoff)
|
||||
/**
|
||||
* cs_parser_fini() - clean parser states
|
||||
* @parser: parser structure holding parsing context.
|
||||
* @error: error number
|
||||
*
|
||||
* If error is set than unvalidate buffer, otherwise just free memory
|
||||
* used by parsing context.
|
||||
**/
|
||||
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (!error) {
|
||||
/* Sort the buffer list from the smallest to largest buffer,
|
||||
* which affects the order of buffers in the LRU list.
|
||||
|
@ -479,17 +465,14 @@ static void amdgpu_cs_parser_fini_early(struct amdgpu_cs_parser *parser, int err
|
|||
list_sort(NULL, &parser->validated, cmp_size_smaller_first);
|
||||
|
||||
ttm_eu_fence_buffer_objects(&parser->ticket,
|
||||
&parser->validated,
|
||||
&parser->ibs[parser->num_ibs-1].fence->base);
|
||||
&parser->validated,
|
||||
parser->fence);
|
||||
} else if (backoff) {
|
||||
ttm_eu_backoff_reservation(&parser->ticket,
|
||||
&parser->validated);
|
||||
}
|
||||
}
|
||||
fence_put(parser->fence);
|
||||
|
||||
static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
|
||||
{
|
||||
unsigned i;
|
||||
if (parser->ctx)
|
||||
amdgpu_ctx_put(parser->ctx);
|
||||
if (parser->bo_list)
|
||||
|
@ -499,31 +482,12 @@ static void amdgpu_cs_parser_fini_late(struct amdgpu_cs_parser *parser)
|
|||
for (i = 0; i < parser->nchunks; i++)
|
||||
drm_free_large(parser->chunks[i].kdata);
|
||||
kfree(parser->chunks);
|
||||
if (!amdgpu_enable_scheduler)
|
||||
{
|
||||
if (parser->ibs)
|
||||
for (i = 0; i < parser->num_ibs; i++)
|
||||
amdgpu_ib_free(parser->adev, &parser->ibs[i]);
|
||||
kfree(parser->ibs);
|
||||
if (parser->uf.bo)
|
||||
drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
|
||||
}
|
||||
|
||||
kfree(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* cs_parser_fini() - clean parser states
|
||||
* @parser: parser structure holding parsing context.
|
||||
* @error: error number
|
||||
*
|
||||
* If error is set than unvalidate buffer, otherwise just free memory
|
||||
* used by parsing context.
|
||||
**/
|
||||
static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bool backoff)
|
||||
{
|
||||
amdgpu_cs_parser_fini_early(parser, error, backoff);
|
||||
amdgpu_cs_parser_fini_late(parser);
|
||||
if (parser->ibs)
|
||||
for (i = 0; i < parser->num_ibs; i++)
|
||||
amdgpu_ib_free(parser->adev, &parser->ibs[i]);
|
||||
kfree(parser->ibs);
|
||||
if (parser->uf.bo)
|
||||
drm_gem_object_unreference_unlocked(&parser->uf.bo->gem_base);
|
||||
}
|
||||
|
||||
static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
|
||||
|
@ -610,15 +574,9 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
r = amdgpu_bo_vm_update_pte(parser, vm);
|
||||
if (r) {
|
||||
goto out;
|
||||
}
|
||||
amdgpu_cs_sync_rings(parser);
|
||||
if (!amdgpu_enable_scheduler)
|
||||
r = amdgpu_ib_schedule(adev, parser->num_ibs, parser->ibs,
|
||||
parser->filp);
|
||||
if (!r)
|
||||
amdgpu_cs_sync_rings(parser);
|
||||
|
||||
out:
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -828,36 +786,36 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|||
union drm_amdgpu_cs *cs = data;
|
||||
struct amdgpu_fpriv *fpriv = filp->driver_priv;
|
||||
struct amdgpu_vm *vm = &fpriv->vm;
|
||||
struct amdgpu_cs_parser *parser;
|
||||
struct amdgpu_cs_parser parser = {};
|
||||
bool reserved_buffers = false;
|
||||
int i, r;
|
||||
|
||||
if (!adev->accel_working)
|
||||
return -EBUSY;
|
||||
|
||||
parser = amdgpu_cs_parser_create(adev, filp, NULL, NULL, 0);
|
||||
if (!parser)
|
||||
return -ENOMEM;
|
||||
r = amdgpu_cs_parser_init(parser, data);
|
||||
parser.adev = adev;
|
||||
parser.filp = filp;
|
||||
|
||||
r = amdgpu_cs_parser_init(&parser, data);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to initialize parser !\n");
|
||||
amdgpu_cs_parser_fini(parser, r, false);
|
||||
amdgpu_cs_parser_fini(&parser, r, false);
|
||||
r = amdgpu_cs_handle_lockup(adev, r);
|
||||
return r;
|
||||
}
|
||||
mutex_lock(&vm->mutex);
|
||||
r = amdgpu_cs_parser_relocs(parser);
|
||||
r = amdgpu_cs_parser_relocs(&parser);
|
||||
if (r == -ENOMEM)
|
||||
DRM_ERROR("Not enough memory for command submission!\n");
|
||||
else if (r && r != -ERESTARTSYS)
|
||||
DRM_ERROR("Failed to process the buffer list %d!\n", r);
|
||||
else if (!r) {
|
||||
reserved_buffers = true;
|
||||
r = amdgpu_cs_ib_fill(adev, parser);
|
||||
r = amdgpu_cs_ib_fill(adev, &parser);
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
r = amdgpu_cs_dependencies(adev, parser);
|
||||
r = amdgpu_cs_dependencies(adev, &parser);
|
||||
if (r)
|
||||
DRM_ERROR("Failed in the dependencies handling %d!\n", r);
|
||||
}
|
||||
|
@ -865,62 +823,71 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|||
if (r)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < parser->num_ibs; i++)
|
||||
trace_amdgpu_cs(parser, i);
|
||||
for (i = 0; i < parser.num_ibs; i++)
|
||||
trace_amdgpu_cs(&parser, i);
|
||||
|
||||
r = amdgpu_cs_ib_vm_chunk(adev, parser);
|
||||
r = amdgpu_cs_ib_vm_chunk(adev, &parser);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
if (amdgpu_enable_scheduler && parser->num_ibs) {
|
||||
if (amdgpu_enable_scheduler && parser.num_ibs) {
|
||||
struct amdgpu_ring * ring = parser.ibs->ring;
|
||||
struct amd_sched_fence *fence;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ring * ring = parser->ibs->ring;
|
||||
|
||||
job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
|
||||
if (!job) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
job->base.sched = &ring->sched;
|
||||
job->base.s_entity = &parser->ctx->rings[ring->idx].entity;
|
||||
job->adev = parser->adev;
|
||||
job->ibs = parser->ibs;
|
||||
job->num_ibs = parser->num_ibs;
|
||||
job->base.owner = parser->filp;
|
||||
mutex_init(&job->job_lock);
|
||||
job->base.s_entity = &parser.ctx->rings[ring->idx].entity;
|
||||
job->adev = parser.adev;
|
||||
job->owner = parser.filp;
|
||||
job->free_job = amdgpu_cs_free_job;
|
||||
|
||||
job->ibs = parser.ibs;
|
||||
job->num_ibs = parser.num_ibs;
|
||||
parser.ibs = NULL;
|
||||
parser.num_ibs = 0;
|
||||
|
||||
if (job->ibs[job->num_ibs - 1].user) {
|
||||
memcpy(&job->uf, &parser->uf,
|
||||
sizeof(struct amdgpu_user_fence));
|
||||
job->uf = parser.uf;
|
||||
job->ibs[job->num_ibs - 1].user = &job->uf;
|
||||
parser.uf.bo = NULL;
|
||||
}
|
||||
|
||||
job->free_job = amdgpu_cs_free_job;
|
||||
mutex_lock(&job->job_lock);
|
||||
r = amd_sched_entity_push_job(&job->base);
|
||||
if (r) {
|
||||
mutex_unlock(&job->job_lock);
|
||||
fence = amd_sched_fence_create(job->base.s_entity,
|
||||
parser.filp);
|
||||
if (!fence) {
|
||||
r = -ENOMEM;
|
||||
amdgpu_cs_free_job(job);
|
||||
kfree(job);
|
||||
goto out;
|
||||
}
|
||||
cs->out.handle =
|
||||
amdgpu_ctx_add_fence(parser->ctx, ring,
|
||||
&job->base.s_fence->base);
|
||||
parser->ibs[parser->num_ibs - 1].sequence = cs->out.handle;
|
||||
job->base.s_fence = fence;
|
||||
parser.fence = fence_get(&fence->base);
|
||||
|
||||
list_sort(NULL, &parser->validated, cmp_size_smaller_first);
|
||||
ttm_eu_fence_buffer_objects(&parser->ticket,
|
||||
&parser->validated,
|
||||
&job->base.s_fence->base);
|
||||
cs->out.handle = amdgpu_ctx_add_fence(parser.ctx, ring,
|
||||
&fence->base);
|
||||
job->ibs[job->num_ibs - 1].sequence = cs->out.handle;
|
||||
|
||||
mutex_unlock(&job->job_lock);
|
||||
amdgpu_cs_parser_fini_late(parser);
|
||||
mutex_unlock(&vm->mutex);
|
||||
return 0;
|
||||
trace_amdgpu_cs_ioctl(job);
|
||||
amd_sched_entity_push_job(&job->base);
|
||||
|
||||
} else {
|
||||
struct amdgpu_fence *fence;
|
||||
|
||||
r = amdgpu_ib_schedule(adev, parser.num_ibs, parser.ibs,
|
||||
parser.filp);
|
||||
fence = parser.ibs[parser.num_ibs - 1].fence;
|
||||
parser.fence = fence_get(&fence->base);
|
||||
cs->out.handle = parser.ibs[parser.num_ibs - 1].sequence;
|
||||
}
|
||||
|
||||
cs->out.handle = parser->ibs[parser->num_ibs - 1].sequence;
|
||||
out:
|
||||
amdgpu_cs_parser_fini(parser, r, reserved_buffers);
|
||||
amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
|
||||
mutex_unlock(&vm->mutex);
|
||||
r = amdgpu_cs_handle_lockup(adev, r);
|
||||
return r;
|
||||
|
|
|
@ -47,6 +47,9 @@
|
|||
* that the the relevant GPU caches have been flushed.
|
||||
*/
|
||||
|
||||
static struct kmem_cache *amdgpu_fence_slab;
|
||||
static atomic_t amdgpu_fence_slab_ref = ATOMIC_INIT(0);
|
||||
|
||||
/**
|
||||
* amdgpu_fence_write - write a fence value
|
||||
*
|
||||
|
@ -84,24 +87,6 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
|
|||
return seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_fence_schedule_check - schedule lockup check
|
||||
*
|
||||
* @ring: pointer to struct amdgpu_ring
|
||||
*
|
||||
* Queues a delayed work item to check for lockups.
|
||||
*/
|
||||
static void amdgpu_fence_schedule_check(struct amdgpu_ring *ring)
|
||||
{
|
||||
/*
|
||||
* Do not reset the timer here with mod_delayed_work,
|
||||
* this can livelock in an interaction with TTM delayed destroy.
|
||||
*/
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&ring->fence_drv.lockup_work,
|
||||
AMDGPU_FENCE_JIFFIES_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_fence_emit - emit a fence on the requested ring
|
||||
*
|
||||
|
@ -118,7 +103,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
|
|||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
/* we are protected by the ring emission mutex */
|
||||
*fence = kmalloc(sizeof(struct amdgpu_fence), GFP_KERNEL);
|
||||
*fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL);
|
||||
if ((*fence) == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -132,10 +117,22 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
|
|||
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
|
||||
(*fence)->seq,
|
||||
AMDGPU_FENCE_FLAG_INT);
|
||||
trace_amdgpu_fence_emit(ring->adev->ddev, ring->idx, (*fence)->seq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_fence_schedule_fallback - schedule fallback check
|
||||
*
|
||||
* @ring: pointer to struct amdgpu_ring
|
||||
*
|
||||
* Start a timer as fallback to our interrupts.
|
||||
*/
|
||||
static void amdgpu_fence_schedule_fallback(struct amdgpu_ring *ring)
|
||||
{
|
||||
mod_timer(&ring->fence_drv.fallback_timer,
|
||||
jiffies + AMDGPU_FENCE_JIFFIES_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_fence_activity - check for fence activity
|
||||
*
|
||||
|
@ -202,32 +199,11 @@ static bool amdgpu_fence_activity(struct amdgpu_ring *ring)
|
|||
} while (atomic64_xchg(&ring->fence_drv.last_seq, seq) > seq);
|
||||
|
||||
if (seq < last_emitted)
|
||||
amdgpu_fence_schedule_check(ring);
|
||||
amdgpu_fence_schedule_fallback(ring);
|
||||
|
||||
return wake;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_fence_check_lockup - check for hardware lockup
|
||||
*
|
||||
* @work: delayed work item
|
||||
*
|
||||
* Checks for fence activity and if there is none probe
|
||||
* the hardware if a lockup occured.
|
||||
*/
|
||||
static void amdgpu_fence_check_lockup(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_fence_driver *fence_drv;
|
||||
struct amdgpu_ring *ring;
|
||||
|
||||
fence_drv = container_of(work, struct amdgpu_fence_driver,
|
||||
lockup_work.work);
|
||||
ring = fence_drv->ring;
|
||||
|
||||
if (amdgpu_fence_activity(ring))
|
||||
wake_up_all(&ring->fence_drv.fence_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_fence_process - process a fence
|
||||
*
|
||||
|
@ -243,6 +219,20 @@ void amdgpu_fence_process(struct amdgpu_ring *ring)
|
|||
wake_up_all(&ring->fence_drv.fence_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_fence_fallback - fallback for hardware interrupts
|
||||
*
|
||||
* @work: delayed work item
|
||||
*
|
||||
* Checks for fence activity.
|
||||
*/
|
||||
static void amdgpu_fence_fallback(unsigned long arg)
|
||||
{
|
||||
struct amdgpu_ring *ring = (void *)arg;
|
||||
|
||||
amdgpu_fence_process(ring);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_fence_seq_signaled - check if a fence sequence number has signaled
|
||||
*
|
||||
|
@ -290,7 +280,7 @@ static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq)
|
|||
if (atomic64_read(&ring->fence_drv.last_seq) >= seq)
|
||||
return 0;
|
||||
|
||||
amdgpu_fence_schedule_check(ring);
|
||||
amdgpu_fence_schedule_fallback(ring);
|
||||
wait_event(ring->fence_drv.fence_queue, (
|
||||
(signaled = amdgpu_fence_seq_signaled(ring, seq))));
|
||||
|
||||
|
@ -491,9 +481,8 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
|
|||
atomic64_set(&ring->fence_drv.last_seq, 0);
|
||||
ring->fence_drv.initialized = false;
|
||||
|
||||
INIT_DELAYED_WORK(&ring->fence_drv.lockup_work,
|
||||
amdgpu_fence_check_lockup);
|
||||
ring->fence_drv.ring = ring;
|
||||
setup_timer(&ring->fence_drv.fallback_timer, amdgpu_fence_fallback,
|
||||
(unsigned long)ring);
|
||||
|
||||
init_waitqueue_head(&ring->fence_drv.fence_queue);
|
||||
|
||||
|
@ -536,6 +525,13 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
|
|||
*/
|
||||
int amdgpu_fence_driver_init(struct amdgpu_device *adev)
|
||||
{
|
||||
if (atomic_inc_return(&amdgpu_fence_slab_ref) == 1) {
|
||||
amdgpu_fence_slab = kmem_cache_create(
|
||||
"amdgpu_fence", sizeof(struct amdgpu_fence), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!amdgpu_fence_slab)
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (amdgpu_debugfs_fence_init(adev))
|
||||
dev_err(adev->dev, "fence debugfs file creation failed\n");
|
||||
|
||||
|
@ -554,9 +550,12 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
|
|||
{
|
||||
int i, r;
|
||||
|
||||
if (atomic_dec_and_test(&amdgpu_fence_slab_ref))
|
||||
kmem_cache_destroy(amdgpu_fence_slab);
|
||||
mutex_lock(&adev->ring_lock);
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
|
||||
struct amdgpu_ring *ring = adev->rings[i];
|
||||
|
||||
if (!ring || !ring->fence_drv.initialized)
|
||||
continue;
|
||||
r = amdgpu_fence_wait_empty(ring);
|
||||
|
@ -568,6 +567,7 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
|
|||
amdgpu_irq_put(adev, ring->fence_drv.irq_src,
|
||||
ring->fence_drv.irq_type);
|
||||
amd_sched_fini(&ring->sched);
|
||||
del_timer_sync(&ring->fence_drv.fallback_timer);
|
||||
ring->fence_drv.initialized = false;
|
||||
}
|
||||
mutex_unlock(&adev->ring_lock);
|
||||
|
@ -751,18 +751,25 @@ static bool amdgpu_fence_enable_signaling(struct fence *f)
|
|||
fence->fence_wake.func = amdgpu_fence_check_signaled;
|
||||
__add_wait_queue(&ring->fence_drv.fence_queue, &fence->fence_wake);
|
||||
fence_get(f);
|
||||
amdgpu_fence_schedule_check(ring);
|
||||
if (!timer_pending(&ring->fence_drv.fallback_timer))
|
||||
amdgpu_fence_schedule_fallback(ring);
|
||||
FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void amdgpu_fence_release(struct fence *f)
|
||||
{
|
||||
struct amdgpu_fence *fence = to_amdgpu_fence(f);
|
||||
kmem_cache_free(amdgpu_fence_slab, fence);
|
||||
}
|
||||
|
||||
const struct fence_ops amdgpu_fence_ops = {
|
||||
.get_driver_name = amdgpu_fence_get_driver_name,
|
||||
.get_timeline_name = amdgpu_fence_get_timeline_name,
|
||||
.enable_signaling = amdgpu_fence_enable_signaling,
|
||||
.signaled = amdgpu_fence_is_signaled,
|
||||
.wait = fence_default_wait,
|
||||
.release = NULL,
|
||||
.release = amdgpu_fence_release,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -483,6 +483,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
|
|||
if (domain == AMDGPU_GEM_DOMAIN_CPU)
|
||||
goto error_unreserve;
|
||||
}
|
||||
r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
|
||||
if (r)
|
||||
goto error_unreserve;
|
||||
|
||||
r = amdgpu_vm_clear_freed(adev, bo_va->vm);
|
||||
if (r)
|
||||
|
@ -512,6 +515,9 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
|||
struct amdgpu_fpriv *fpriv = filp->driver_priv;
|
||||
struct amdgpu_bo *rbo;
|
||||
struct amdgpu_bo_va *bo_va;
|
||||
struct ttm_validate_buffer tv, tv_pd;
|
||||
struct ww_acquire_ctx ticket;
|
||||
struct list_head list, duplicates;
|
||||
uint32_t invalid_flags, va_flags = 0;
|
||||
int r = 0;
|
||||
|
||||
|
@ -549,7 +555,18 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
|||
return -ENOENT;
|
||||
mutex_lock(&fpriv->vm.mutex);
|
||||
rbo = gem_to_amdgpu_bo(gobj);
|
||||
r = amdgpu_bo_reserve(rbo, false);
|
||||
INIT_LIST_HEAD(&list);
|
||||
INIT_LIST_HEAD(&duplicates);
|
||||
tv.bo = &rbo->tbo;
|
||||
tv.shared = true;
|
||||
list_add(&tv.head, &list);
|
||||
|
||||
if (args->operation == AMDGPU_VA_OP_MAP) {
|
||||
tv_pd.bo = &fpriv->vm.page_directory->tbo;
|
||||
tv_pd.shared = true;
|
||||
list_add(&tv_pd.head, &list);
|
||||
}
|
||||
r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
|
||||
if (r) {
|
||||
mutex_unlock(&fpriv->vm.mutex);
|
||||
drm_gem_object_unreference_unlocked(gobj);
|
||||
|
@ -558,7 +575,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
bo_va = amdgpu_vm_bo_find(&fpriv->vm, rbo);
|
||||
if (!bo_va) {
|
||||
amdgpu_bo_unreserve(rbo);
|
||||
ttm_eu_backoff_reservation(&ticket, &list);
|
||||
drm_gem_object_unreference_unlocked(gobj);
|
||||
mutex_unlock(&fpriv->vm.mutex);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -581,7 +599,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ttm_eu_backoff_reservation(&ticket, &list);
|
||||
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
|
||||
amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
|
||||
mutex_unlock(&fpriv->vm.mutex);
|
||||
|
|
|
@ -62,7 +62,7 @@ int amdgpu_ib_get(struct amdgpu_ring *ring, struct amdgpu_vm *vm,
|
|||
int r;
|
||||
|
||||
if (size) {
|
||||
r = amdgpu_sa_bo_new(adev, &adev->ring_tmp_bo,
|
||||
r = amdgpu_sa_bo_new(&adev->ring_tmp_bo,
|
||||
&ib->sa_bo, size, 256);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "failed to get a new IB (%d)\n", r);
|
||||
|
@ -216,7 +216,7 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs,
|
|||
}
|
||||
|
||||
if (ib->vm)
|
||||
amdgpu_vm_fence(adev, ib->vm, ib->fence);
|
||||
amdgpu_vm_fence(adev, ib->vm, &ib->fence->base);
|
||||
|
||||
amdgpu_ring_unlock_commit(ring);
|
||||
return 0;
|
||||
|
|
|
@ -189,10 +189,9 @@ int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,
|
|||
struct amdgpu_sa_manager *sa_manager);
|
||||
int amdgpu_sa_bo_manager_suspend(struct amdgpu_device *adev,
|
||||
struct amdgpu_sa_manager *sa_manager);
|
||||
int amdgpu_sa_bo_new(struct amdgpu_device *adev,
|
||||
struct amdgpu_sa_manager *sa_manager,
|
||||
struct amdgpu_sa_bo **sa_bo,
|
||||
unsigned size, unsigned align);
|
||||
int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
|
||||
struct amdgpu_sa_bo **sa_bo,
|
||||
unsigned size, unsigned align);
|
||||
void amdgpu_sa_bo_free(struct amdgpu_device *adev,
|
||||
struct amdgpu_sa_bo **sa_bo,
|
||||
struct fence *fence);
|
||||
|
|
|
@ -311,8 +311,7 @@ static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager,
|
|||
return false;
|
||||
}
|
||||
|
||||
int amdgpu_sa_bo_new(struct amdgpu_device *adev,
|
||||
struct amdgpu_sa_manager *sa_manager,
|
||||
int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager,
|
||||
struct amdgpu_sa_bo **sa_bo,
|
||||
unsigned size, unsigned align)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <drm/drmP.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_trace.h"
|
||||
|
||||
static struct fence *amdgpu_sched_dependency(struct amd_sched_job *sched_job)
|
||||
{
|
||||
|
@ -44,11 +45,8 @@ static struct fence *amdgpu_sched_run_job(struct amd_sched_job *sched_job)
|
|||
return NULL;
|
||||
}
|
||||
job = to_amdgpu_job(sched_job);
|
||||
mutex_lock(&job->job_lock);
|
||||
r = amdgpu_ib_schedule(job->adev,
|
||||
job->num_ibs,
|
||||
job->ibs,
|
||||
job->base.owner);
|
||||
trace_amdgpu_sched_run_job(job);
|
||||
r = amdgpu_ib_schedule(job->adev, job->num_ibs, job->ibs, job->owner);
|
||||
if (r) {
|
||||
DRM_ERROR("Error scheduling IBs (%d)\n", r);
|
||||
goto err;
|
||||
|
@ -61,8 +59,6 @@ static struct fence *amdgpu_sched_run_job(struct amd_sched_job *sched_job)
|
|||
if (job->free_job)
|
||||
job->free_job(job);
|
||||
|
||||
mutex_unlock(&job->job_lock);
|
||||
fence_put(&job->base.s_fence->base);
|
||||
kfree(job);
|
||||
return fence ? &fence->base : NULL;
|
||||
}
|
||||
|
@ -88,21 +84,19 @@ int amdgpu_sched_ib_submit_kernel_helper(struct amdgpu_device *adev,
|
|||
return -ENOMEM;
|
||||
job->base.sched = &ring->sched;
|
||||
job->base.s_entity = &adev->kernel_ctx.rings[ring->idx].entity;
|
||||
job->base.s_fence = amd_sched_fence_create(job->base.s_entity, owner);
|
||||
if (!job->base.s_fence) {
|
||||
kfree(job);
|
||||
return -ENOMEM;
|
||||
}
|
||||
*f = fence_get(&job->base.s_fence->base);
|
||||
|
||||
job->adev = adev;
|
||||
job->ibs = ibs;
|
||||
job->num_ibs = num_ibs;
|
||||
job->base.owner = owner;
|
||||
mutex_init(&job->job_lock);
|
||||
job->owner = owner;
|
||||
job->free_job = free_job;
|
||||
mutex_lock(&job->job_lock);
|
||||
r = amd_sched_entity_push_job(&job->base);
|
||||
if (r) {
|
||||
mutex_unlock(&job->job_lock);
|
||||
kfree(job);
|
||||
return r;
|
||||
}
|
||||
*f = fence_get(&job->base.s_fence->base);
|
||||
mutex_unlock(&job->job_lock);
|
||||
amd_sched_entity_push_job(&job->base);
|
||||
} else {
|
||||
r = amdgpu_ib_schedule(adev, num_ibs, ibs, owner);
|
||||
if (r)
|
||||
|
|
|
@ -40,7 +40,7 @@ int amdgpu_semaphore_create(struct amdgpu_device *adev,
|
|||
if (*semaphore == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
r = amdgpu_sa_bo_new(adev, &adev->ring_tmp_bo,
|
||||
r = amdgpu_sa_bo_new(&adev->ring_tmp_bo,
|
||||
&(*semaphore)->sa_bo, 8, 8);
|
||||
if (r) {
|
||||
kfree(*semaphore);
|
||||
|
|
|
@ -302,8 +302,14 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores ||
|
||||
(count >= AMDGPU_NUM_SYNCS)) {
|
||||
if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores) {
|
||||
r = fence_wait(&fence->base, true);
|
||||
if (r)
|
||||
return r;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count >= AMDGPU_NUM_SYNCS) {
|
||||
/* not enough room, wait manually */
|
||||
r = fence_wait(&fence->base, false);
|
||||
if (r)
|
||||
|
|
|
@ -48,6 +48,57 @@ TRACE_EVENT(amdgpu_cs,
|
|||
__entry->fences)
|
||||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_cs_ioctl,
|
||||
TP_PROTO(struct amdgpu_job *job),
|
||||
TP_ARGS(job),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct amdgpu_device *, adev)
|
||||
__field(struct amd_sched_job *, sched_job)
|
||||
__field(struct amdgpu_ib *, ib)
|
||||
__field(struct fence *, fence)
|
||||
__field(char *, ring_name)
|
||||
__field(u32, num_ibs)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->adev = job->adev;
|
||||
__entry->sched_job = &job->base;
|
||||
__entry->ib = job->ibs;
|
||||
__entry->fence = &job->base.s_fence->base;
|
||||
__entry->ring_name = job->ibs[0].ring->name;
|
||||
__entry->num_ibs = job->num_ibs;
|
||||
),
|
||||
TP_printk("adev=%p, sched_job=%p, first ib=%p, sched fence=%p, ring name:%s, num_ibs:%u",
|
||||
__entry->adev, __entry->sched_job, __entry->ib,
|
||||
__entry->fence, __entry->ring_name, __entry->num_ibs)
|
||||
);
|
||||
|
||||
TRACE_EVENT(amdgpu_sched_run_job,
|
||||
TP_PROTO(struct amdgpu_job *job),
|
||||
TP_ARGS(job),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct amdgpu_device *, adev)
|
||||
__field(struct amd_sched_job *, sched_job)
|
||||
__field(struct amdgpu_ib *, ib)
|
||||
__field(struct fence *, fence)
|
||||
__field(char *, ring_name)
|
||||
__field(u32, num_ibs)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->adev = job->adev;
|
||||
__entry->sched_job = &job->base;
|
||||
__entry->ib = job->ibs;
|
||||
__entry->fence = &job->base.s_fence->base;
|
||||
__entry->ring_name = job->ibs[0].ring->name;
|
||||
__entry->num_ibs = job->num_ibs;
|
||||
),
|
||||
TP_printk("adev=%p, sched_job=%p, first ib=%p, sched fence=%p, ring name:%s, num_ibs:%u",
|
||||
__entry->adev, __entry->sched_job, __entry->ib,
|
||||
__entry->fence, __entry->ring_name, __entry->num_ibs)
|
||||
);
|
||||
|
||||
|
||||
TRACE_EVENT(amdgpu_vm_grab_id,
|
||||
TP_PROTO(unsigned vmid, int ring),
|
||||
TP_ARGS(vmid, ring),
|
||||
|
@ -196,49 +247,6 @@ TRACE_EVENT(amdgpu_bo_list_set,
|
|||
TP_printk("list=%p, bo=%p", __entry->list, __entry->bo)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(amdgpu_fence_request,
|
||||
|
||||
TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
|
||||
|
||||
TP_ARGS(dev, ring, seqno),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, dev)
|
||||
__field(int, ring)
|
||||
__field(u32, seqno)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dev = dev->primary->index;
|
||||
__entry->ring = ring;
|
||||
__entry->seqno = seqno;
|
||||
),
|
||||
|
||||
TP_printk("dev=%u, ring=%d, seqno=%u",
|
||||
__entry->dev, __entry->ring, __entry->seqno)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_emit,
|
||||
|
||||
TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
|
||||
|
||||
TP_ARGS(dev, ring, seqno)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_wait_begin,
|
||||
|
||||
TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
|
||||
|
||||
TP_ARGS(dev, ring, seqno)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(amdgpu_fence_request, amdgpu_fence_wait_end,
|
||||
|
||||
TP_PROTO(struct drm_device *dev, int ring, u32 seqno),
|
||||
|
||||
TP_ARGS(dev, ring, seqno)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(amdgpu_semaphore_request,
|
||||
|
||||
TP_PROTO(int ring, struct amdgpu_semaphore *sem),
|
||||
|
|
|
@ -1073,10 +1073,10 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data)
|
|||
ret = drm_mm_dump_table(m, mm);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
if (ttm_pl == TTM_PL_VRAM)
|
||||
seq_printf(m, "man size:%llu pages, ram usage:%luMB, vis usage:%luMB\n",
|
||||
seq_printf(m, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n",
|
||||
adev->mman.bdev.man[ttm_pl].size,
|
||||
atomic64_read(&adev->vram_usage) >> 20,
|
||||
atomic64_read(&adev->vram_vis_usage) >> 20);
|
||||
(u64)atomic64_read(&adev->vram_usage) >> 20,
|
||||
(u64)atomic64_read(&adev->vram_vis_usage) >> 20);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,10 +143,15 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
|||
unsigned i;
|
||||
|
||||
/* check if the id is still valid */
|
||||
if (vm_id->id && vm_id->last_id_use &&
|
||||
vm_id->last_id_use == adev->vm_manager.active[vm_id->id]) {
|
||||
trace_amdgpu_vm_grab_id(vm_id->id, ring->idx);
|
||||
return 0;
|
||||
if (vm_id->id) {
|
||||
unsigned id = vm_id->id;
|
||||
long owner;
|
||||
|
||||
owner = atomic_long_read(&adev->vm_manager.ids[id].owner);
|
||||
if (owner == (long)vm) {
|
||||
trace_amdgpu_vm_grab_id(vm_id->id, ring->idx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* we definately need to flush */
|
||||
|
@ -154,7 +159,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
|||
|
||||
/* skip over VMID 0, since it is the system VM */
|
||||
for (i = 1; i < adev->vm_manager.nvm; ++i) {
|
||||
struct fence *fence = adev->vm_manager.active[i];
|
||||
struct fence *fence = adev->vm_manager.ids[i].active;
|
||||
struct amdgpu_ring *fring;
|
||||
|
||||
if (fence == NULL) {
|
||||
|
@ -176,7 +181,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
|
|||
if (choices[i]) {
|
||||
struct fence *fence;
|
||||
|
||||
fence = adev->vm_manager.active[choices[i]];
|
||||
fence = adev->vm_manager.ids[choices[i]].active;
|
||||
vm_id->id = choices[i];
|
||||
|
||||
trace_amdgpu_vm_grab_id(choices[i], ring->idx);
|
||||
|
@ -207,24 +212,21 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring,
|
|||
uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
|
||||
struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx];
|
||||
struct fence *flushed_updates = vm_id->flushed_updates;
|
||||
bool is_earlier = false;
|
||||
bool is_later;
|
||||
|
||||
if (flushed_updates && updates) {
|
||||
BUG_ON(flushed_updates->context != updates->context);
|
||||
is_earlier = (updates->seqno - flushed_updates->seqno <=
|
||||
INT_MAX) ? true : false;
|
||||
}
|
||||
|
||||
if (pd_addr != vm_id->pd_gpu_addr || !flushed_updates ||
|
||||
is_earlier) {
|
||||
if (!flushed_updates)
|
||||
is_later = true;
|
||||
else if (!updates)
|
||||
is_later = false;
|
||||
else
|
||||
is_later = fence_is_later(updates, flushed_updates);
|
||||
|
||||
if (pd_addr != vm_id->pd_gpu_addr || is_later) {
|
||||
trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id->id);
|
||||
if (is_earlier) {
|
||||
if (is_later) {
|
||||
vm_id->flushed_updates = fence_get(updates);
|
||||
fence_put(flushed_updates);
|
||||
}
|
||||
if (!flushed_updates)
|
||||
vm_id->flushed_updates = fence_get(updates);
|
||||
vm_id->pd_gpu_addr = pd_addr;
|
||||
amdgpu_ring_emit_vm_flush(ring, vm_id->id, vm_id->pd_gpu_addr);
|
||||
}
|
||||
|
@ -244,16 +246,14 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring,
|
|||
*/
|
||||
void amdgpu_vm_fence(struct amdgpu_device *adev,
|
||||
struct amdgpu_vm *vm,
|
||||
struct amdgpu_fence *fence)
|
||||
struct fence *fence)
|
||||
{
|
||||
unsigned ridx = fence->ring->idx;
|
||||
unsigned vm_id = vm->ids[ridx].id;
|
||||
struct amdgpu_ring *ring = amdgpu_ring_from_fence(fence);
|
||||
unsigned vm_id = vm->ids[ring->idx].id;
|
||||
|
||||
fence_put(adev->vm_manager.active[vm_id]);
|
||||
adev->vm_manager.active[vm_id] = fence_get(&fence->base);
|
||||
|
||||
fence_put(vm->ids[ridx].last_id_use);
|
||||
vm->ids[ridx].last_id_use = fence_get(&fence->base);
|
||||
fence_put(adev->vm_manager.ids[vm_id].active);
|
||||
adev->vm_manager.ids[vm_id].active = fence_get(fence);
|
||||
atomic_long_set(&adev->vm_manager.ids[vm_id].owner, (long)vm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,6 +332,8 @@ int amdgpu_vm_free_job(struct amdgpu_job *job)
|
|||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @bo: bo to clear
|
||||
*
|
||||
* need to reserve bo first before calling it.
|
||||
*/
|
||||
static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo *bo)
|
||||
|
@ -343,24 +345,20 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
|
|||
uint64_t addr;
|
||||
int r;
|
||||
|
||||
r = amdgpu_bo_reserve(bo, false);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = reservation_object_reserve_shared(bo->tbo.resv);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
|
||||
if (r)
|
||||
goto error_unreserve;
|
||||
goto error;
|
||||
|
||||
addr = amdgpu_bo_gpu_offset(bo);
|
||||
entries = amdgpu_bo_size(bo) / 8;
|
||||
|
||||
ib = kzalloc(sizeof(struct amdgpu_ib), GFP_KERNEL);
|
||||
if (!ib)
|
||||
goto error_unreserve;
|
||||
goto error;
|
||||
|
||||
r = amdgpu_ib_get(ring, NULL, entries * 2 + 64, ib);
|
||||
if (r)
|
||||
|
@ -378,16 +376,14 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
|
|||
if (!r)
|
||||
amdgpu_bo_fence(bo, fence, true);
|
||||
fence_put(fence);
|
||||
if (amdgpu_enable_scheduler) {
|
||||
amdgpu_bo_unreserve(bo);
|
||||
if (amdgpu_enable_scheduler)
|
||||
return 0;
|
||||
}
|
||||
|
||||
error_free:
|
||||
amdgpu_ib_free(adev, ib);
|
||||
kfree(ib);
|
||||
|
||||
error_unreserve:
|
||||
amdgpu_bo_unreserve(bo);
|
||||
error:
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -989,7 +985,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
|
|||
* Add a mapping of the BO at the specefied addr into the VM.
|
||||
* Returns 0 for success, error for failure.
|
||||
*
|
||||
* Object has to be reserved and gets unreserved by this function!
|
||||
* Object has to be reserved and unreserved outside!
|
||||
*/
|
||||
int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
|
@ -1005,30 +1001,27 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||
|
||||
/* validate the parameters */
|
||||
if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
|
||||
size == 0 || size & AMDGPU_GPU_PAGE_MASK) {
|
||||
amdgpu_bo_unreserve(bo_va->bo);
|
||||
size == 0 || size & AMDGPU_GPU_PAGE_MASK)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* make sure object fit at this offset */
|
||||
eaddr = saddr + size;
|
||||
if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo))) {
|
||||
amdgpu_bo_unreserve(bo_va->bo);
|
||||
if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE;
|
||||
if (last_pfn > adev->vm_manager.max_pfn) {
|
||||
dev_err(adev->dev, "va above limit (0x%08X > 0x%08X)\n",
|
||||
last_pfn, adev->vm_manager.max_pfn);
|
||||
amdgpu_bo_unreserve(bo_va->bo);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
saddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||
eaddr /= AMDGPU_GPU_PAGE_SIZE;
|
||||
|
||||
spin_lock(&vm->it_lock);
|
||||
it = interval_tree_iter_first(&vm->va, saddr, eaddr - 1);
|
||||
spin_unlock(&vm->it_lock);
|
||||
if (it) {
|
||||
struct amdgpu_bo_va_mapping *tmp;
|
||||
tmp = container_of(it, struct amdgpu_bo_va_mapping, it);
|
||||
|
@ -1036,14 +1029,12 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||
dev_err(adev->dev, "bo %p va 0x%010Lx-0x%010Lx conflict with "
|
||||
"0x%010lx-0x%010lx\n", bo_va->bo, saddr, eaddr,
|
||||
tmp->it.start, tmp->it.last + 1);
|
||||
amdgpu_bo_unreserve(bo_va->bo);
|
||||
r = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
|
||||
if (!mapping) {
|
||||
amdgpu_bo_unreserve(bo_va->bo);
|
||||
r = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
@ -1055,7 +1046,9 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||
mapping->flags = flags;
|
||||
|
||||
list_add(&mapping->list, &bo_va->invalids);
|
||||
spin_lock(&vm->it_lock);
|
||||
interval_tree_insert(&mapping->it, &vm->va);
|
||||
spin_unlock(&vm->it_lock);
|
||||
trace_amdgpu_vm_bo_map(bo_va, mapping);
|
||||
|
||||
/* Make sure the page tables are allocated */
|
||||
|
@ -1067,8 +1060,6 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||
if (eaddr > vm->max_pde_used)
|
||||
vm->max_pde_used = eaddr;
|
||||
|
||||
amdgpu_bo_unreserve(bo_va->bo);
|
||||
|
||||
/* walk over the address space and allocate the page tables */
|
||||
for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) {
|
||||
struct reservation_object *resv = vm->page_directory->tbo.resv;
|
||||
|
@ -1077,13 +1068,11 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||
if (vm->page_tables[pt_idx].bo)
|
||||
continue;
|
||||
|
||||
ww_mutex_lock(&resv->lock, NULL);
|
||||
r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
|
||||
AMDGPU_GPU_PAGE_SIZE, true,
|
||||
AMDGPU_GEM_DOMAIN_VRAM,
|
||||
AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
|
||||
NULL, resv, &pt);
|
||||
ww_mutex_unlock(&resv->lock);
|
||||
if (r)
|
||||
goto error_free;
|
||||
|
||||
|
@ -1101,7 +1090,9 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||
|
||||
error_free:
|
||||
list_del(&mapping->list);
|
||||
spin_lock(&vm->it_lock);
|
||||
interval_tree_remove(&mapping->it, &vm->va);
|
||||
spin_unlock(&vm->it_lock);
|
||||
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
|
||||
kfree(mapping);
|
||||
|
||||
|
@ -1119,7 +1110,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
|||
* Remove a mapping of the BO at the specefied addr from the VM.
|
||||
* Returns 0 for success, error for failure.
|
||||
*
|
||||
* Object has to be reserved and gets unreserved by this function!
|
||||
* Object has to be reserved and unreserved outside!
|
||||
*/
|
||||
int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va *bo_va,
|
||||
|
@ -1144,21 +1135,20 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
|
|||
break;
|
||||
}
|
||||
|
||||
if (&mapping->list == &bo_va->invalids) {
|
||||
amdgpu_bo_unreserve(bo_va->bo);
|
||||
if (&mapping->list == &bo_va->invalids)
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
list_del(&mapping->list);
|
||||
spin_lock(&vm->it_lock);
|
||||
interval_tree_remove(&mapping->it, &vm->va);
|
||||
spin_unlock(&vm->it_lock);
|
||||
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
|
||||
|
||||
if (valid)
|
||||
list_add(&mapping->list, &vm->freed);
|
||||
else
|
||||
kfree(mapping);
|
||||
amdgpu_bo_unreserve(bo_va->bo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1187,13 +1177,17 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
|
|||
|
||||
list_for_each_entry_safe(mapping, next, &bo_va->valids, list) {
|
||||
list_del(&mapping->list);
|
||||
spin_lock(&vm->it_lock);
|
||||
interval_tree_remove(&mapping->it, &vm->va);
|
||||
spin_unlock(&vm->it_lock);
|
||||
trace_amdgpu_vm_bo_unmap(bo_va, mapping);
|
||||
list_add(&mapping->list, &vm->freed);
|
||||
}
|
||||
list_for_each_entry_safe(mapping, next, &bo_va->invalids, list) {
|
||||
list_del(&mapping->list);
|
||||
spin_lock(&vm->it_lock);
|
||||
interval_tree_remove(&mapping->it, &vm->va);
|
||||
spin_unlock(&vm->it_lock);
|
||||
kfree(mapping);
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1235,6 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
|
|||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
|
||||
vm->ids[i].id = 0;
|
||||
vm->ids[i].flushed_updates = NULL;
|
||||
vm->ids[i].last_id_use = NULL;
|
||||
}
|
||||
mutex_init(&vm->mutex);
|
||||
vm->va = RB_ROOT;
|
||||
|
@ -1249,7 +1242,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
|
|||
INIT_LIST_HEAD(&vm->invalidated);
|
||||
INIT_LIST_HEAD(&vm->cleared);
|
||||
INIT_LIST_HEAD(&vm->freed);
|
||||
|
||||
spin_lock_init(&vm->it_lock);
|
||||
pd_size = amdgpu_vm_directory_size(adev);
|
||||
pd_entries = amdgpu_vm_num_pdes(adev);
|
||||
|
||||
|
@ -1269,8 +1262,14 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
|
|||
NULL, NULL, &vm->page_directory);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_bo_reserve(vm->page_directory, false);
|
||||
if (r) {
|
||||
amdgpu_bo_unref(&vm->page_directory);
|
||||
vm->page_directory = NULL;
|
||||
return r;
|
||||
}
|
||||
r = amdgpu_vm_clear_bo(adev, vm->page_directory);
|
||||
amdgpu_bo_unreserve(vm->page_directory);
|
||||
if (r) {
|
||||
amdgpu_bo_unref(&vm->page_directory);
|
||||
vm->page_directory = NULL;
|
||||
|
@ -1313,11 +1312,28 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
|
|||
|
||||
amdgpu_bo_unref(&vm->page_directory);
|
||||
fence_put(vm->page_directory_fence);
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
|
||||
unsigned id = vm->ids[i].id;
|
||||
|
||||
atomic_long_cmpxchg(&adev->vm_manager.ids[id].owner,
|
||||
(long)vm, 0);
|
||||
fence_put(vm->ids[i].flushed_updates);
|
||||
fence_put(vm->ids[i].last_id_use);
|
||||
}
|
||||
|
||||
mutex_destroy(&vm->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_vm_manager_fini - cleanup VM manager
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Cleanup the VM manager and free resources.
|
||||
*/
|
||||
void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < AMDGPU_NUM_VM; ++i)
|
||||
fence_put(adev->vm_manager.ids[i].active);
|
||||
}
|
||||
|
|
|
@ -6569,12 +6569,12 @@ static int ci_dpm_set_interrupt_state(struct amdgpu_device *adev,
|
|||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
|
||||
cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
|
||||
cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
|
||||
WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
|
||||
break;
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
|
||||
cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
|
||||
cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK;
|
||||
WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
|
||||
break;
|
||||
default:
|
||||
|
@ -6586,12 +6586,12 @@ static int ci_dpm_set_interrupt_state(struct amdgpu_device *adev,
|
|||
switch (state) {
|
||||
case AMDGPU_IRQ_STATE_DISABLE:
|
||||
cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
|
||||
cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
|
||||
cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
|
||||
WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
|
||||
break;
|
||||
case AMDGPU_IRQ_STATE_ENABLE:
|
||||
cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT);
|
||||
cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
|
||||
cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK;
|
||||
WREG32_SMC(ixCG_THERMAL_INT, cg_thermal_int);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -268,7 +268,6 @@ static const u32 fiji_mgcg_cgcg_init[] =
|
|||
mmCGTT_CP_CLK_CTRL, 0xffffffff, 0x00000100,
|
||||
mmCGTT_CPC_CLK_CTRL, 0xffffffff, 0x00000100,
|
||||
mmCGTT_CPF_CLK_CTRL, 0xffffffff, 0x40000100,
|
||||
mmCGTT_DRM_CLK_CTRL0, 0xffffffff, 0x00600100,
|
||||
mmCGTT_GDS_CLK_CTRL, 0xffffffff, 0x00000100,
|
||||
mmCGTT_IA_CLK_CTRL, 0xffffffff, 0x06000100,
|
||||
mmCGTT_PA_CLK_CTRL, 0xffffffff, 0x00000100,
|
||||
|
@ -296,10 +295,6 @@ static const u32 fiji_mgcg_cgcg_init[] =
|
|||
mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96e00200,
|
||||
mmCP_RB_WPTR_POLL_CNTL, 0xffffffff, 0x00900100,
|
||||
mmRLC_CGCG_CGLS_CTRL, 0xffffffff, 0x0020003c,
|
||||
mmPCIE_INDEX, 0xffffffff, 0x0140001c,
|
||||
mmPCIE_DATA, 0x000f0000, 0x00000000,
|
||||
mmCGTT_DRM_CLK_CTRL0, 0xff000fff, 0x00000100,
|
||||
mmHDP_XDP_CGTT_BLK_CTRL, 0xc0000fff, 0x00000104,
|
||||
mmCP_MEM_SLP_CNTL, 0x00000001, 0x00000001,
|
||||
};
|
||||
|
||||
|
@ -1000,7 +995,7 @@ static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
|
|||
adev->gfx.config.max_cu_per_sh = 16;
|
||||
adev->gfx.config.max_sh_per_se = 1;
|
||||
adev->gfx.config.max_backends_per_se = 4;
|
||||
adev->gfx.config.max_texture_channel_caches = 8;
|
||||
adev->gfx.config.max_texture_channel_caches = 16;
|
||||
adev->gfx.config.max_gprs = 256;
|
||||
adev->gfx.config.max_gs_threads = 32;
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
|
@ -1613,6 +1608,296 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
|
|||
WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
|
||||
}
|
||||
case CHIP_FIJI:
|
||||
for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
|
||||
switch (reg_offset) {
|
||||
case 0:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
|
||||
break;
|
||||
case 1:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
|
||||
break;
|
||||
case 2:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
|
||||
break;
|
||||
case 3:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
|
||||
break;
|
||||
case 4:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
|
||||
break;
|
||||
case 5:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
|
||||
break;
|
||||
case 6:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
|
||||
break;
|
||||
case 7:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P4_16x16) |
|
||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
|
||||
break;
|
||||
case 8:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16));
|
||||
break;
|
||||
case 9:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
|
||||
break;
|
||||
case 10:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
|
||||
break;
|
||||
case 11:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
|
||||
break;
|
||||
case 12:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P4_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
|
||||
break;
|
||||
case 13:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
|
||||
break;
|
||||
case 14:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
|
||||
break;
|
||||
case 15:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
|
||||
break;
|
||||
case 16:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
|
||||
break;
|
||||
case 17:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P4_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
|
||||
break;
|
||||
case 18:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 19:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 20:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 21:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 22:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 23:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P4_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 24:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 25:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 26:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
|
||||
break;
|
||||
case 27:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
|
||||
break;
|
||||
case 28:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
|
||||
break;
|
||||
case 29:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
|
||||
break;
|
||||
case 30:
|
||||
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
|
||||
PIPE_CONFIG(ADDR_SURF_P4_16x16) |
|
||||
MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
|
||||
SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
|
||||
break;
|
||||
default:
|
||||
gb_tile_moden = 0;
|
||||
break;
|
||||
}
|
||||
adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
|
||||
WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
|
||||
}
|
||||
for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) {
|
||||
switch (reg_offset) {
|
||||
case 0:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 1:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 2:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 3:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 4:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 5:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 6:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 8:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 9:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 10:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 11:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 12:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 13:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
|
||||
NUM_BANKS(ADDR_SURF_8_BANK));
|
||||
break;
|
||||
case 14:
|
||||
gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
|
||||
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
|
||||
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
|
||||
NUM_BANKS(ADDR_SURF_4_BANK));
|
||||
break;
|
||||
case 7:
|
||||
/* unused idx */
|
||||
continue;
|
||||
default:
|
||||
gb_tile_moden = 0;
|
||||
break;
|
||||
}
|
||||
adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden;
|
||||
WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden);
|
||||
}
|
||||
break;
|
||||
case CHIP_TONGA:
|
||||
for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
|
||||
switch (reg_offset) {
|
||||
|
@ -2971,10 +3256,13 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)
|
|||
amdgpu_ring_write(ring, mmPA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
amdgpu_ring_write(ring, 0x16000012);
|
||||
amdgpu_ring_write(ring, 0x0000002A);
|
||||
break;
|
||||
case CHIP_FIJI:
|
||||
amdgpu_ring_write(ring, 0x3a00161a);
|
||||
amdgpu_ring_write(ring, 0x0000002e);
|
||||
break;
|
||||
case CHIP_TOPAZ:
|
||||
case CHIP_CARRIZO:
|
||||
amdgpu_ring_write(ring, 0x00000002);
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
static void gmc_v7_0_set_gart_funcs(struct amdgpu_device *adev);
|
||||
static void gmc_v7_0_set_irq_funcs(struct amdgpu_device *adev);
|
||||
|
||||
MODULE_FIRMWARE("radeon/boniare_mc.bin");
|
||||
MODULE_FIRMWARE("radeon/bonaire_mc.bin");
|
||||
MODULE_FIRMWARE("radeon/hawaii_mc.bin");
|
||||
|
||||
/**
|
||||
|
@ -501,6 +501,7 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev)
|
|||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, EFFECTIVE_L2_QUEUE_SIZE, 7);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
|
||||
WREG32(mmVM_L2_CNTL, tmp);
|
||||
tmp = REG_SET_FIELD(0, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
|
||||
|
@ -960,12 +961,10 @@ static int gmc_v7_0_sw_init(void *handle)
|
|||
|
||||
static int gmc_v7_0_sw_fini(void *handle)
|
||||
{
|
||||
int i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->vm_manager.enabled) {
|
||||
for (i = 0; i < AMDGPU_NUM_VM; ++i)
|
||||
fence_put(adev->vm_manager.active[i]);
|
||||
amdgpu_vm_manager_fini(adev);
|
||||
gmc_v7_0_vm_fini(adev);
|
||||
adev->vm_manager.enabled = false;
|
||||
}
|
||||
|
@ -1010,12 +1009,10 @@ static int gmc_v7_0_hw_fini(void *handle)
|
|||
|
||||
static int gmc_v7_0_suspend(void *handle)
|
||||
{
|
||||
int i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->vm_manager.enabled) {
|
||||
for (i = 0; i < AMDGPU_NUM_VM; ++i)
|
||||
fence_put(adev->vm_manager.active[i]);
|
||||
amdgpu_vm_manager_fini(adev);
|
||||
gmc_v7_0_vm_fini(adev);
|
||||
adev->vm_manager.enabled = false;
|
||||
}
|
||||
|
|
|
@ -629,6 +629,7 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev)
|
|||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, EFFECTIVE_L2_QUEUE_SIZE, 7);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL, ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
|
||||
WREG32(mmVM_L2_CNTL, tmp);
|
||||
tmp = RREG32(mmVM_L2_CNTL2);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
|
||||
|
@ -979,12 +980,10 @@ static int gmc_v8_0_sw_init(void *handle)
|
|||
|
||||
static int gmc_v8_0_sw_fini(void *handle)
|
||||
{
|
||||
int i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->vm_manager.enabled) {
|
||||
for (i = 0; i < AMDGPU_NUM_VM; ++i)
|
||||
fence_put(adev->vm_manager.active[i]);
|
||||
amdgpu_vm_manager_fini(adev);
|
||||
gmc_v8_0_vm_fini(adev);
|
||||
adev->vm_manager.enabled = false;
|
||||
}
|
||||
|
@ -1031,12 +1030,10 @@ static int gmc_v8_0_hw_fini(void *handle)
|
|||
|
||||
static int gmc_v8_0_suspend(void *handle)
|
||||
{
|
||||
int i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->vm_manager.enabled) {
|
||||
for (i = 0; i < AMDGPU_NUM_VM; ++i)
|
||||
fence_put(adev->vm_manager.active[i]);
|
||||
amdgpu_vm_manager_fini(adev);
|
||||
gmc_v8_0_vm_fini(adev);
|
||||
adev->vm_manager.enabled = false;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ TRACE_EVENT(amd_sched_job,
|
|||
TP_ARGS(sched_job),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct amd_sched_entity *, entity)
|
||||
__field(struct amd_sched_job *, sched_job)
|
||||
__field(struct fence *, fence)
|
||||
__field(const char *, name)
|
||||
__field(u32, job_count)
|
||||
__field(int, hw_job_count)
|
||||
|
@ -23,16 +25,32 @@ TRACE_EVENT(amd_sched_job,
|
|||
|
||||
TP_fast_assign(
|
||||
__entry->entity = sched_job->s_entity;
|
||||
__entry->sched_job = sched_job;
|
||||
__entry->fence = &sched_job->s_fence->base;
|
||||
__entry->name = sched_job->sched->name;
|
||||
__entry->job_count = kfifo_len(
|
||||
&sched_job->s_entity->job_queue) / sizeof(sched_job);
|
||||
__entry->hw_job_count = atomic_read(
|
||||
&sched_job->sched->hw_rq_count);
|
||||
),
|
||||
TP_printk("entity=%p, ring=%s, job count:%u, hw job count:%d",
|
||||
__entry->entity, __entry->name, __entry->job_count,
|
||||
__entry->hw_job_count)
|
||||
TP_printk("entity=%p, sched job=%p, fence=%p, ring=%s, job count:%u, hw job count:%d",
|
||||
__entry->entity, __entry->sched_job, __entry->fence, __entry->name,
|
||||
__entry->job_count, __entry->hw_job_count)
|
||||
);
|
||||
|
||||
TRACE_EVENT(amd_sched_process_job,
|
||||
TP_PROTO(struct amd_sched_fence *fence),
|
||||
TP_ARGS(fence),
|
||||
TP_STRUCT__entry(
|
||||
__field(struct fence *, fence)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->fence = &fence->base;
|
||||
),
|
||||
TP_printk("fence=%p signaled", __entry->fence)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
|
|
@ -34,6 +34,9 @@ static struct amd_sched_job *
|
|||
amd_sched_entity_pop_job(struct amd_sched_entity *entity);
|
||||
static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
|
||||
|
||||
struct kmem_cache *sched_fence_slab;
|
||||
atomic_t sched_fence_slab_ref = ATOMIC_INIT(0);
|
||||
|
||||
/* Initialize a given run queue struct */
|
||||
static void amd_sched_rq_init(struct amd_sched_rq *rq)
|
||||
{
|
||||
|
@ -273,22 +276,13 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job)
|
|||
*
|
||||
* Returns 0 for success, negative error code otherwise.
|
||||
*/
|
||||
int amd_sched_entity_push_job(struct amd_sched_job *sched_job)
|
||||
void amd_sched_entity_push_job(struct amd_sched_job *sched_job)
|
||||
{
|
||||
struct amd_sched_entity *entity = sched_job->s_entity;
|
||||
struct amd_sched_fence *fence = amd_sched_fence_create(
|
||||
entity, sched_job->owner);
|
||||
|
||||
if (!fence)
|
||||
return -ENOMEM;
|
||||
|
||||
fence_get(&fence->base);
|
||||
sched_job->s_fence = fence;
|
||||
|
||||
wait_event(entity->sched->job_scheduled,
|
||||
amd_sched_entity_in(sched_job));
|
||||
trace_amd_sched_job(sched_job);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -343,6 +337,7 @@ static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
|
|||
list_del_init(&s_fence->list);
|
||||
spin_unlock_irqrestore(&sched->fence_list_lock, flags);
|
||||
}
|
||||
trace_amd_sched_process_job(s_fence);
|
||||
fence_put(&s_fence->base);
|
||||
wake_up_interruptible(&sched->wake_up_worker);
|
||||
}
|
||||
|
@ -450,6 +445,13 @@ int amd_sched_init(struct amd_gpu_scheduler *sched,
|
|||
init_waitqueue_head(&sched->wake_up_worker);
|
||||
init_waitqueue_head(&sched->job_scheduled);
|
||||
atomic_set(&sched->hw_rq_count, 0);
|
||||
if (atomic_inc_return(&sched_fence_slab_ref) == 1) {
|
||||
sched_fence_slab = kmem_cache_create(
|
||||
"amd_sched_fence", sizeof(struct amd_sched_fence), 0,
|
||||
SLAB_HWCACHE_ALIGN, NULL);
|
||||
if (!sched_fence_slab)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Each scheduler will run on a seperate kernel thread */
|
||||
sched->thread = kthread_run(amd_sched_main, sched, sched->name);
|
||||
|
@ -470,4 +472,6 @@ void amd_sched_fini(struct amd_gpu_scheduler *sched)
|
|||
{
|
||||
if (sched->thread)
|
||||
kthread_stop(sched->thread);
|
||||
if (atomic_dec_and_test(&sched_fence_slab_ref))
|
||||
kmem_cache_destroy(sched_fence_slab);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
struct amd_gpu_scheduler;
|
||||
struct amd_sched_rq;
|
||||
|
||||
extern struct kmem_cache *sched_fence_slab;
|
||||
extern atomic_t sched_fence_slab_ref;
|
||||
|
||||
/**
|
||||
* A scheduler entity is a wrapper around a job queue or a group
|
||||
* of other entities. Entities take turns emitting jobs from their
|
||||
|
@ -76,7 +79,6 @@ struct amd_sched_job {
|
|||
struct amd_gpu_scheduler *sched;
|
||||
struct amd_sched_entity *s_entity;
|
||||
struct amd_sched_fence *s_fence;
|
||||
void *owner;
|
||||
};
|
||||
|
||||
extern const struct fence_ops amd_sched_fence_ops;
|
||||
|
@ -128,7 +130,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
|
|||
uint32_t jobs);
|
||||
void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
|
||||
struct amd_sched_entity *entity);
|
||||
int amd_sched_entity_push_job(struct amd_sched_job *sched_job);
|
||||
void amd_sched_entity_push_job(struct amd_sched_job *sched_job);
|
||||
|
||||
struct amd_sched_fence *amd_sched_fence_create(
|
||||
struct amd_sched_entity *s_entity, void *owner);
|
||||
|
|
|
@ -32,7 +32,7 @@ struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *s_entity
|
|||
struct amd_sched_fence *fence = NULL;
|
||||
unsigned seq;
|
||||
|
||||
fence = kzalloc(sizeof(struct amd_sched_fence), GFP_KERNEL);
|
||||
fence = kmem_cache_zalloc(sched_fence_slab, GFP_KERNEL);
|
||||
if (fence == NULL)
|
||||
return NULL;
|
||||
fence->owner = owner;
|
||||
|
@ -71,11 +71,17 @@ static bool amd_sched_fence_enable_signaling(struct fence *f)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void amd_sched_fence_release(struct fence *f)
|
||||
{
|
||||
struct amd_sched_fence *fence = to_amd_sched_fence(f);
|
||||
kmem_cache_free(sched_fence_slab, fence);
|
||||
}
|
||||
|
||||
const struct fence_ops amd_sched_fence_ops = {
|
||||
.get_driver_name = amd_sched_fence_get_driver_name,
|
||||
.get_timeline_name = amd_sched_fence_get_timeline_name,
|
||||
.enable_signaling = amd_sched_fence_enable_signaling,
|
||||
.signaled = NULL,
|
||||
.wait = fence_default_wait,
|
||||
.release = NULL,
|
||||
.release = amd_sched_fence_release,
|
||||
};
|
||||
|
|
|
@ -1432,6 +1432,45 @@ static int atomic_set_prop(struct drm_atomic_state *state,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers.
|
||||
*
|
||||
* @dev: drm device to check.
|
||||
* @plane_mask: plane mask for planes that were updated.
|
||||
* @ret: return value, can be -EDEADLK for a retry.
|
||||
*
|
||||
* Before doing an update plane->old_fb is set to plane->fb,
|
||||
* but before dropping the locks old_fb needs to be set to NULL
|
||||
* and plane->fb updated. This is a common operation for each
|
||||
* atomic update, so this call is split off as a helper.
|
||||
*/
|
||||
void drm_atomic_clean_old_fb(struct drm_device *dev,
|
||||
unsigned plane_mask,
|
||||
int ret)
|
||||
{
|
||||
struct drm_plane *plane;
|
||||
|
||||
/* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
|
||||
* locks (ie. while it is still safe to deref plane->state). We
|
||||
* need to do this here because the driver entry points cannot
|
||||
* distinguish between legacy and atomic ioctls.
|
||||
*/
|
||||
drm_for_each_plane_mask(plane, dev, plane_mask) {
|
||||
if (ret == 0) {
|
||||
struct drm_framebuffer *new_fb = plane->state->fb;
|
||||
if (new_fb)
|
||||
drm_framebuffer_reference(new_fb);
|
||||
plane->fb = new_fb;
|
||||
plane->crtc = plane->state->crtc;
|
||||
|
||||
if (plane->old_fb)
|
||||
drm_framebuffer_unreference(plane->old_fb);
|
||||
}
|
||||
plane->old_fb = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_clean_old_fb);
|
||||
|
||||
int drm_mode_atomic_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
|
@ -1446,7 +1485,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
|
|||
struct drm_plane *plane;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
unsigned plane_mask = 0;
|
||||
unsigned plane_mask;
|
||||
int ret = 0;
|
||||
unsigned int i, j;
|
||||
|
||||
|
@ -1486,6 +1525,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
|
|||
state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
|
||||
|
||||
retry:
|
||||
plane_mask = 0;
|
||||
copied_objs = 0;
|
||||
copied_props = 0;
|
||||
|
||||
|
@ -1576,24 +1616,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
|
|||
}
|
||||
|
||||
out:
|
||||
/* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
|
||||
* locks (ie. while it is still safe to deref plane->state). We
|
||||
* need to do this here because the driver entry points cannot
|
||||
* distinguish between legacy and atomic ioctls.
|
||||
*/
|
||||
drm_for_each_plane_mask(plane, dev, plane_mask) {
|
||||
if (ret == 0) {
|
||||
struct drm_framebuffer *new_fb = plane->state->fb;
|
||||
if (new_fb)
|
||||
drm_framebuffer_reference(new_fb);
|
||||
plane->fb = new_fb;
|
||||
plane->crtc = plane->state->crtc;
|
||||
|
||||
if (plane->old_fb)
|
||||
drm_framebuffer_unreference(plane->old_fb);
|
||||
}
|
||||
plane->old_fb = NULL;
|
||||
}
|
||||
drm_atomic_clean_old_fb(dev, plane_mask, ret);
|
||||
|
||||
if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
|
||||
/*
|
||||
|
|
|
@ -210,6 +210,14 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) {
|
||||
DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n",
|
||||
new_encoder->base.id,
|
||||
new_encoder->name,
|
||||
connector_state->crtc->base.id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (new_encoder == connector_state->best_encoder) {
|
||||
DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n",
|
||||
connector->base.id,
|
||||
|
@ -1553,6 +1561,9 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (plane_state->crtc && (plane == plane->crtc->cursor))
|
||||
plane_state->state->legacy_cursor_update = true;
|
||||
|
||||
ret = __drm_atomic_helper_disable_plane(plane, plane_state);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
@ -1605,9 +1616,6 @@ int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
|
|||
plane_state->src_h = 0;
|
||||
plane_state->src_w = 0;
|
||||
|
||||
if (plane->crtc && (plane == plane->crtc->cursor))
|
||||
plane_state->state->legacy_cursor_update = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1741,6 +1749,7 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
|
|||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_plane_state *primary_state;
|
||||
struct drm_crtc *crtc = set->crtc;
|
||||
int hdisplay, vdisplay;
|
||||
int ret;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
|
@ -1783,19 +1792,21 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);
|
||||
|
||||
drm_atomic_set_fb_for_plane(primary_state, set->fb);
|
||||
primary_state->crtc_x = 0;
|
||||
primary_state->crtc_y = 0;
|
||||
primary_state->crtc_h = set->mode->vdisplay;
|
||||
primary_state->crtc_w = set->mode->hdisplay;
|
||||
primary_state->crtc_h = vdisplay;
|
||||
primary_state->crtc_w = hdisplay;
|
||||
primary_state->src_x = set->x << 16;
|
||||
primary_state->src_y = set->y << 16;
|
||||
if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
|
||||
primary_state->src_h = set->mode->hdisplay << 16;
|
||||
primary_state->src_w = set->mode->vdisplay << 16;
|
||||
primary_state->src_h = hdisplay << 16;
|
||||
primary_state->src_w = vdisplay << 16;
|
||||
} else {
|
||||
primary_state->src_h = set->mode->vdisplay << 16;
|
||||
primary_state->src_w = set->mode->hdisplay << 16;
|
||||
primary_state->src_h = vdisplay << 16;
|
||||
primary_state->src_w = hdisplay << 16;
|
||||
}
|
||||
|
||||
commit:
|
||||
|
|
|
@ -342,6 +342,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
|
|||
struct drm_plane *plane;
|
||||
struct drm_atomic_state *state;
|
||||
int i, ret;
|
||||
unsigned plane_mask;
|
||||
|
||||
state = drm_atomic_state_alloc(dev);
|
||||
if (!state)
|
||||
|
@ -349,11 +350,10 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
|
|||
|
||||
state->acquire_ctx = dev->mode_config.acquire_ctx;
|
||||
retry:
|
||||
plane_mask = 0;
|
||||
drm_for_each_plane(plane, dev) {
|
||||
struct drm_plane_state *plane_state;
|
||||
|
||||
plane->old_fb = plane->fb;
|
||||
|
||||
plane_state = drm_atomic_get_plane_state(state, plane);
|
||||
if (IS_ERR(plane_state)) {
|
||||
ret = PTR_ERR(plane_state);
|
||||
|
@ -362,6 +362,9 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
|
|||
|
||||
plane_state->rotation = BIT(DRM_ROTATE_0);
|
||||
|
||||
plane->old_fb = plane->fb;
|
||||
plane_mask |= 1 << drm_plane_index(plane);
|
||||
|
||||
/* disable non-primary: */
|
||||
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
|
||||
continue;
|
||||
|
@ -382,19 +385,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
|
|||
ret = drm_atomic_commit(state);
|
||||
|
||||
fail:
|
||||
drm_for_each_plane(plane, dev) {
|
||||
if (ret == 0) {
|
||||
struct drm_framebuffer *new_fb = plane->state->fb;
|
||||
if (new_fb)
|
||||
drm_framebuffer_reference(new_fb);
|
||||
plane->fb = new_fb;
|
||||
plane->crtc = plane->state->crtc;
|
||||
|
||||
if (plane->old_fb)
|
||||
drm_framebuffer_unreference(plane->old_fb);
|
||||
}
|
||||
plane->old_fb = NULL;
|
||||
}
|
||||
drm_atomic_clean_old_fb(dev, plane_mask, ret);
|
||||
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
@ -1236,7 +1227,9 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
|
|||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_plane *plane;
|
||||
int i, ret;
|
||||
unsigned plane_mask;
|
||||
|
||||
state = drm_atomic_state_alloc(dev);
|
||||
if (!state)
|
||||
|
@ -1244,19 +1237,22 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
|
|||
|
||||
state->acquire_ctx = dev->mode_config.acquire_ctx;
|
||||
retry:
|
||||
plane_mask = 0;
|
||||
for(i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set;
|
||||
|
||||
mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
|
||||
mode_set->crtc->primary->old_fb = mode_set->crtc->primary->fb;
|
||||
|
||||
mode_set->x = var->xoffset;
|
||||
mode_set->y = var->yoffset;
|
||||
|
||||
ret = __drm_atomic_helper_set_config(mode_set, state);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
||||
plane = mode_set->crtc->primary;
|
||||
plane_mask |= drm_plane_index(plane);
|
||||
plane->old_fb = plane->fb;
|
||||
}
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
|
@ -1268,26 +1264,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
|
|||
|
||||
|
||||
fail:
|
||||
for(i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set;
|
||||
struct drm_plane *plane;
|
||||
|
||||
mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
plane = mode_set->crtc->primary;
|
||||
|
||||
if (ret == 0) {
|
||||
struct drm_framebuffer *new_fb = plane->state->fb;
|
||||
|
||||
if (new_fb)
|
||||
drm_framebuffer_reference(new_fb);
|
||||
plane->fb = new_fb;
|
||||
plane->crtc = plane->state->crtc;
|
||||
|
||||
if (plane->old_fb)
|
||||
drm_framebuffer_unreference(plane->old_fb);
|
||||
}
|
||||
plane->old_fb = NULL;
|
||||
}
|
||||
drm_atomic_clean_old_fb(dev, plane_mask, ret);
|
||||
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
|
|
@ -351,6 +351,8 @@ enum intel_dpll_id {
|
|||
/* hsw/bdw */
|
||||
DPLL_ID_WRPLL1 = 0,
|
||||
DPLL_ID_WRPLL2 = 1,
|
||||
DPLL_ID_SPLL = 2,
|
||||
|
||||
/* skl */
|
||||
DPLL_ID_SKL_DPLL1 = 0,
|
||||
DPLL_ID_SKL_DPLL2 = 1,
|
||||
|
@ -367,6 +369,7 @@ struct intel_dpll_hw_state {
|
|||
|
||||
/* hsw, bdw */
|
||||
uint32_t wrpll;
|
||||
uint32_t spll;
|
||||
|
||||
/* skl */
|
||||
/*
|
||||
|
@ -2648,6 +2651,7 @@ struct i915_params {
|
|||
int enable_cmd_parser;
|
||||
/* leave bools at the end to not create holes */
|
||||
bool enable_hangcheck;
|
||||
bool fastboot;
|
||||
bool prefault_disable;
|
||||
bool load_detect_test;
|
||||
bool reset;
|
||||
|
|
|
@ -3809,6 +3809,7 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
|
|||
int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_caching *args = data;
|
||||
struct drm_i915_gem_object *obj;
|
||||
enum i915_cache_level level;
|
||||
|
@ -3837,9 +3838,11 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
ret = i915_mutex_lock_interruptible(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto rpm_put;
|
||||
|
||||
obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
|
||||
if (&obj->base == NULL) {
|
||||
|
@ -3852,6 +3855,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
|
|||
drm_gem_object_unreference(&obj->base);
|
||||
unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
rpm_put:
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ struct i915_params i915 __read_mostly = {
|
|||
.preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT),
|
||||
.disable_power_well = -1,
|
||||
.enable_ips = 1,
|
||||
.fastboot = 0,
|
||||
.prefault_disable = 0,
|
||||
.load_detect_test = 0,
|
||||
.reset = true,
|
||||
|
@ -133,6 +134,10 @@ MODULE_PARM_DESC(disable_power_well,
|
|||
module_param_named_unsafe(enable_ips, i915.enable_ips, int, 0600);
|
||||
MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
|
||||
|
||||
module_param_named(fastboot, i915.fastboot, bool, 0600);
|
||||
MODULE_PARM_DESC(fastboot,
|
||||
"Try to skip unnecessary mode sets at boot time (default: false)");
|
||||
|
||||
module_param_named_unsafe(prefault_disable, i915.prefault_disable, bool, 0600);
|
||||
MODULE_PARM_DESC(prefault_disable,
|
||||
"Disable page prefaulting for pread/pwrite/reloc (default:false). "
|
||||
|
|
|
@ -138,18 +138,6 @@ static void hsw_crt_get_config(struct intel_encoder *encoder,
|
|||
pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
|
||||
}
|
||||
|
||||
static void hsw_crt_pre_enable(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL already enabled\n");
|
||||
I915_WRITE(SPLL_CTL,
|
||||
SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC);
|
||||
POSTING_READ(SPLL_CTL);
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
/* Note: The caller is required to filter out dpms modes not supported by the
|
||||
* platform. */
|
||||
static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
|
||||
|
@ -216,19 +204,6 @@ static void pch_post_disable_crt(struct intel_encoder *encoder)
|
|||
intel_disable_crt(encoder);
|
||||
}
|
||||
|
||||
static void hsw_crt_post_disable(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t val;
|
||||
|
||||
DRM_DEBUG_KMS("Disabling SPLL\n");
|
||||
val = I915_READ(SPLL_CTL);
|
||||
WARN_ON(!(val & SPLL_PLL_ENABLE));
|
||||
I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
|
||||
POSTING_READ(SPLL_CTL);
|
||||
}
|
||||
|
||||
static void intel_enable_crt(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_crt *crt = intel_encoder_to_crt(encoder);
|
||||
|
@ -280,6 +255,10 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
|
|||
if (HAS_DDI(dev)) {
|
||||
pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
|
||||
pipe_config->port_clock = 135000 * 2;
|
||||
|
||||
pipe_config->dpll_hw_state.wrpll = 0;
|
||||
pipe_config->dpll_hw_state.spll =
|
||||
SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -860,8 +839,6 @@ void intel_crt_init(struct drm_device *dev)
|
|||
if (HAS_DDI(dev)) {
|
||||
crt->base.get_config = hsw_crt_get_config;
|
||||
crt->base.get_hw_state = intel_ddi_get_hw_state;
|
||||
crt->base.pre_enable = hsw_crt_pre_enable;
|
||||
crt->base.post_disable = hsw_crt_post_disable;
|
||||
} else {
|
||||
crt->base.get_config = intel_crt_get_config;
|
||||
crt->base.get_hw_state = intel_crt_get_hw_state;
|
||||
|
|
|
@ -1286,6 +1286,18 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
|
|||
}
|
||||
|
||||
crtc_state->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
|
||||
} else if (crtc_state->ddi_pll_sel == PORT_CLK_SEL_SPLL) {
|
||||
struct drm_atomic_state *state = crtc_state->base.state;
|
||||
struct intel_shared_dpll_config *spll =
|
||||
&intel_atomic_get_shared_dpll_state(state)[DPLL_ID_SPLL];
|
||||
|
||||
if (spll->crtc_mask &&
|
||||
WARN_ON(spll->hw_state.spll != crtc_state->dpll_hw_state.spll))
|
||||
return false;
|
||||
|
||||
crtc_state->shared_dpll = DPLL_ID_SPLL;
|
||||
spll->hw_state.spll = crtc_state->dpll_hw_state.spll;
|
||||
spll->crtc_mask |= 1 << intel_crtc->pipe;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2437,7 +2449,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
|
|||
}
|
||||
}
|
||||
|
||||
static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
|
||||
static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll)
|
||||
{
|
||||
I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
|
||||
|
@ -2445,8 +2457,16 @@ static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv,
|
|||
udelay(20);
|
||||
}
|
||||
|
||||
static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
|
||||
static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll)
|
||||
{
|
||||
I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
|
||||
POSTING_READ(SPLL_CTL);
|
||||
udelay(20);
|
||||
}
|
||||
|
||||
static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
|
@ -2455,9 +2475,19 @@ static void hsw_ddi_pll_disable(struct drm_i915_private *dev_priv,
|
|||
POSTING_READ(WRPLL_CTL(pll->id));
|
||||
}
|
||||
|
||||
static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = I915_READ(SPLL_CTL);
|
||||
I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
|
||||
POSTING_READ(SPLL_CTL);
|
||||
}
|
||||
|
||||
static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
|
@ -2470,25 +2500,50 @@ static bool hsw_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
|||
return val & WRPLL_PLL_ENABLE;
|
||||
}
|
||||
|
||||
static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
|
||||
return false;
|
||||
|
||||
val = I915_READ(SPLL_CTL);
|
||||
hw_state->spll = val;
|
||||
|
||||
return val & SPLL_PLL_ENABLE;
|
||||
}
|
||||
|
||||
|
||||
static const char * const hsw_ddi_pll_names[] = {
|
||||
"WRPLL 1",
|
||||
"WRPLL 2",
|
||||
"SPLL"
|
||||
};
|
||||
|
||||
static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
int i;
|
||||
|
||||
dev_priv->num_shared_dpll = 2;
|
||||
dev_priv->num_shared_dpll = 3;
|
||||
|
||||
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
dev_priv->shared_dplls[i].id = i;
|
||||
dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
|
||||
dev_priv->shared_dplls[i].disable = hsw_ddi_pll_disable;
|
||||
dev_priv->shared_dplls[i].enable = hsw_ddi_pll_enable;
|
||||
dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable;
|
||||
dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable;
|
||||
dev_priv->shared_dplls[i].get_hw_state =
|
||||
hsw_ddi_pll_get_hw_state;
|
||||
hsw_ddi_wrpll_get_hw_state;
|
||||
}
|
||||
|
||||
/* SPLL is special, but needs to be initialized anyway.. */
|
||||
dev_priv->shared_dplls[i].id = i;
|
||||
dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
|
||||
dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable;
|
||||
dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable;
|
||||
dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state;
|
||||
|
||||
}
|
||||
|
||||
static const char * const skl_ddi_pll_names[] = {
|
||||
|
|
|
@ -2646,11 +2646,13 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
|||
return;
|
||||
|
||||
valid_fb:
|
||||
plane_state->src_x = plane_state->src_y = 0;
|
||||
plane_state->src_x = 0;
|
||||
plane_state->src_y = 0;
|
||||
plane_state->src_w = fb->width << 16;
|
||||
plane_state->src_h = fb->height << 16;
|
||||
|
||||
plane_state->crtc_x = plane_state->src_y = 0;
|
||||
plane_state->crtc_x = 0;
|
||||
plane_state->crtc_y = 0;
|
||||
plane_state->crtc_w = fb->width;
|
||||
plane_state->crtc_h = fb->height;
|
||||
|
||||
|
@ -4237,6 +4239,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
|
|||
struct intel_shared_dpll *pll;
|
||||
struct intel_shared_dpll_config *shared_dpll;
|
||||
enum intel_dpll_id i;
|
||||
int max = dev_priv->num_shared_dpll;
|
||||
|
||||
shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
|
||||
|
||||
|
@ -4271,9 +4274,11 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
|
|||
WARN_ON(shared_dpll[i].crtc_mask);
|
||||
|
||||
goto found;
|
||||
}
|
||||
} else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv))
|
||||
/* Do not consider SPLL */
|
||||
max = 2;
|
||||
|
||||
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
||||
for (i = 0; i < max; i++) {
|
||||
pll = &dev_priv->shared_dplls[i];
|
||||
|
||||
/* Only want to check enabled timings first */
|
||||
|
@ -9723,6 +9728,8 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
|
|||
case PORT_CLK_SEL_WRPLL2:
|
||||
pipe_config->shared_dpll = DPLL_ID_WRPLL2;
|
||||
break;
|
||||
case PORT_CLK_SEL_SPLL:
|
||||
pipe_config->shared_dpll = DPLL_ID_SPLL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12003,9 +12010,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
|
|||
pipe_config->dpll_hw_state.cfgcr1,
|
||||
pipe_config->dpll_hw_state.cfgcr2);
|
||||
} else if (HAS_DDI(dev)) {
|
||||
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x\n",
|
||||
DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
|
||||
pipe_config->ddi_pll_sel,
|
||||
pipe_config->dpll_hw_state.wrpll);
|
||||
pipe_config->dpll_hw_state.wrpll,
|
||||
pipe_config->dpll_hw_state.spll);
|
||||
} else {
|
||||
DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
|
||||
"fp0: 0x%x, fp1: 0x%x\n",
|
||||
|
@ -12528,6 +12536,7 @@ intel_pipe_config_compare(struct drm_device *dev,
|
|||
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
|
||||
PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
|
||||
PIPE_CONF_CHECK_X(dpll_hw_state.wrpll);
|
||||
PIPE_CONF_CHECK_X(dpll_hw_state.spll);
|
||||
PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1);
|
||||
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
|
||||
PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
|
||||
|
@ -13032,6 +13041,9 @@ static int intel_atomic_check(struct drm_device *dev,
|
|||
struct intel_crtc_state *pipe_config =
|
||||
to_intel_crtc_state(crtc_state);
|
||||
|
||||
memset(&to_intel_crtc(crtc)->atomic, 0,
|
||||
sizeof(struct intel_crtc_atomic_commit));
|
||||
|
||||
/* Catch I915_MODE_FLAG_INHERITED */
|
||||
if (crtc_state->mode.private_flags != crtc->state->mode.private_flags)
|
||||
crtc_state->mode_changed = true;
|
||||
|
@ -13056,7 +13068,8 @@ static int intel_atomic_check(struct drm_device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (intel_pipe_config_compare(state->dev,
|
||||
if (i915.fastboot &&
|
||||
intel_pipe_config_compare(state->dev,
|
||||
to_intel_crtc_state(crtc->state),
|
||||
pipe_config, true)) {
|
||||
crtc_state->mode_changed = false;
|
||||
|
@ -14364,16 +14377,17 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|||
static struct drm_framebuffer *
|
||||
intel_user_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_file *filp,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
struct drm_mode_fb_cmd2 *user_mode_cmd)
|
||||
{
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
|
||||
|
||||
obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
|
||||
mode_cmd->handles[0]));
|
||||
mode_cmd.handles[0]));
|
||||
if (&obj->base == NULL)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
return intel_framebuffer_create(dev, mode_cmd, obj);
|
||||
return intel_framebuffer_create(dev, &mode_cmd, obj);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DRM_FBDEV_EMULATION
|
||||
|
@ -14705,6 +14719,9 @@ static struct intel_quirk intel_quirks[] = {
|
|||
/* Apple Macbook 2,1 (Core 2 T7400) */
|
||||
{ 0x27a2, 0x8086, 0x7270, quirk_backlight_present },
|
||||
|
||||
/* Apple Macbook 4,1 */
|
||||
{ 0x2a02, 0x106b, 0x00a1, quirk_backlight_present },
|
||||
|
||||
/* Toshiba CB35 Chromebook (Celeron 2955U) */
|
||||
{ 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
|
||||
|
||||
|
|
|
@ -4449,7 +4449,7 @@ static void gen6_set_rps(struct drm_device *dev, u8 val)
|
|||
POSTING_READ(GEN6_RPNSWREQ);
|
||||
|
||||
dev_priv->rps.cur_freq = val;
|
||||
trace_intel_gpu_freq_change(val * 50);
|
||||
trace_intel_gpu_freq_change(intel_gpu_freq(dev_priv, val));
|
||||
}
|
||||
|
||||
static void valleyview_set_rps(struct drm_device *dev, u8 val)
|
||||
|
@ -7255,7 +7255,8 @@ static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
|
|||
int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
|
||||
{
|
||||
if (IS_GEN9(dev_priv->dev))
|
||||
return (val * GT_FREQUENCY_MULTIPLIER) / GEN9_FREQ_SCALER;
|
||||
return DIV_ROUND_CLOSEST(val * GT_FREQUENCY_MULTIPLIER,
|
||||
GEN9_FREQ_SCALER);
|
||||
else if (IS_CHERRYVIEW(dev_priv->dev))
|
||||
return chv_gpu_freq(dev_priv, val);
|
||||
else if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
|
@ -7267,13 +7268,14 @@ int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
|
|||
int intel_freq_opcode(struct drm_i915_private *dev_priv, int val)
|
||||
{
|
||||
if (IS_GEN9(dev_priv->dev))
|
||||
return (val * GEN9_FREQ_SCALER) / GT_FREQUENCY_MULTIPLIER;
|
||||
return DIV_ROUND_CLOSEST(val * GEN9_FREQ_SCALER,
|
||||
GT_FREQUENCY_MULTIPLIER);
|
||||
else if (IS_CHERRYVIEW(dev_priv->dev))
|
||||
return chv_freq_opcode(dev_priv, val);
|
||||
else if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
return byt_freq_opcode(dev_priv, val);
|
||||
else
|
||||
return val / GT_FREQUENCY_MULTIPLIER;
|
||||
return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER);
|
||||
}
|
||||
|
||||
struct request_boost {
|
||||
|
|
|
@ -70,6 +70,11 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
BUG_ON(pixels_2 != pixels_current && pixels_2 != pixels_prev);
|
||||
BUG_ON(pixels_current == pixels_prev);
|
||||
|
||||
if (!handle || !file_priv) {
|
||||
mga_hide_cursor(mdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, handle);
|
||||
if (!obj)
|
||||
return -ENOENT;
|
||||
|
@ -88,12 +93,6 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
goto out_unreserve1;
|
||||
}
|
||||
|
||||
if (!handle) {
|
||||
mga_hide_cursor(mdev);
|
||||
ret = 0;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
/* Move cursor buffers into VRAM if they aren't already */
|
||||
if (!pixels_1->pin_count) {
|
||||
ret = mgag200_bo_pin(pixels_1, TTM_PL_FLAG_VRAM,
|
||||
|
|
|
@ -221,11 +221,17 @@ int radeon_bo_create(struct radeon_device *rdev,
|
|||
if (!(rdev->flags & RADEON_IS_PCIE))
|
||||
bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
|
||||
|
||||
/* Write-combined CPU mappings of GTT cause GPU hangs with RV6xx
|
||||
* See https://bugs.freedesktop.org/show_bug.cgi?id=91268
|
||||
*/
|
||||
if (rdev->family >= CHIP_RV610 && rdev->family <= CHIP_RV635)
|
||||
bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit
|
||||
* See https://bugs.freedesktop.org/show_bug.cgi?id=84627
|
||||
*/
|
||||
bo->flags &= ~RADEON_GEM_GTT_WC;
|
||||
bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
|
||||
#elif defined(CONFIG_X86) && !defined(CONFIG_X86_PAT)
|
||||
/* Don't try to enable write-combining when it can't work, or things
|
||||
* may be slow
|
||||
|
@ -235,9 +241,10 @@ int radeon_bo_create(struct radeon_device *rdev,
|
|||
#warning Please enable CONFIG_MTRR and CONFIG_X86_PAT for better performance \
|
||||
thanks to write-combining
|
||||
|
||||
DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
|
||||
"better performance thanks to write-combining\n");
|
||||
bo->flags &= ~RADEON_GEM_GTT_WC;
|
||||
if (bo->flags & RADEON_GEM_GTT_WC)
|
||||
DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
|
||||
"better performance thanks to write-combining\n");
|
||||
bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
|
||||
#endif
|
||||
|
||||
radeon_ttm_placement_from_domain(bo, domain);
|
||||
|
|
|
@ -1542,8 +1542,7 @@ int radeon_pm_late_init(struct radeon_device *rdev)
|
|||
ret = device_create_file(rdev->dev, &dev_attr_power_method);
|
||||
if (ret)
|
||||
DRM_ERROR("failed to create device file for power method\n");
|
||||
if (!ret)
|
||||
rdev->pm.sysfs_initialized = true;
|
||||
rdev->pm.sysfs_initialized = true;
|
||||
}
|
||||
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
|
|
|
@ -2927,7 +2927,7 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
|
|||
{ PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x1762, 0x2015, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 },
|
||||
{ PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
|
|
@ -168,7 +168,7 @@ static int vc4_get_clock_select(struct drm_crtc *crtc)
|
|||
struct drm_connector *connector;
|
||||
|
||||
drm_for_each_connector(connector, crtc->dev) {
|
||||
if (connector && connector->state->crtc == crtc) {
|
||||
if (connector->state->crtc == crtc) {
|
||||
struct drm_encoder *encoder = connector->encoder;
|
||||
struct vc4_encoder *vc4_encoder =
|
||||
to_vc4_encoder(encoder);
|
||||
|
@ -401,7 +401,8 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
dlist_next++;
|
||||
|
||||
HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
|
||||
(u32 *)vc4_crtc->dlist - (u32 *)vc4->hvs->dlist);
|
||||
(u32 __iomem *)vc4_crtc->dlist -
|
||||
(u32 __iomem *)vc4->hvs->dlist);
|
||||
|
||||
/* Make the next display list start after ours. */
|
||||
vc4_crtc->dlist_size -= (dlist_next - vc4_crtc->dlist);
|
||||
|
@ -591,14 +592,14 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
|
|||
* that will take too much.
|
||||
*/
|
||||
primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
|
||||
if (!primary_plane) {
|
||||
if (IS_ERR(primary_plane)) {
|
||||
dev_err(dev, "failed to construct primary plane\n");
|
||||
ret = PTR_ERR(primary_plane);
|
||||
goto err;
|
||||
}
|
||||
|
||||
cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
|
||||
if (!cursor_plane) {
|
||||
if (IS_ERR(cursor_plane)) {
|
||||
dev_err(dev, "failed to construct cursor plane\n");
|
||||
ret = PTR_ERR(cursor_plane);
|
||||
goto err_primary;
|
||||
|
|
|
@ -259,7 +259,6 @@ static struct platform_driver vc4_platform_driver = {
|
|||
.remove = vc4_platform_drm_remove,
|
||||
.driver = {
|
||||
.name = "vc4-drm",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = vc4_of_match,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -75,10 +75,10 @@ void vc4_hvs_dump_state(struct drm_device *dev)
|
|||
for (i = 0; i < 64; i += 4) {
|
||||
DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
i * 4, i < HVS_BOOTLOADER_DLIST_END ? "B" : "D",
|
||||
((uint32_t *)vc4->hvs->dlist)[i + 0],
|
||||
((uint32_t *)vc4->hvs->dlist)[i + 1],
|
||||
((uint32_t *)vc4->hvs->dlist)[i + 2],
|
||||
((uint32_t *)vc4->hvs->dlist)[i + 3]);
|
||||
readl((u32 __iomem *)vc4->hvs->dlist + i + 0),
|
||||
readl((u32 __iomem *)vc4->hvs->dlist + i + 1),
|
||||
readl((u32 __iomem *)vc4->hvs->dlist + i + 2),
|
||||
readl((u32 __iomem *)vc4->hvs->dlist + i + 3));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ static bool plane_enabled(struct drm_plane_state *state)
|
|||
return state->fb && state->crtc;
|
||||
}
|
||||
|
||||
struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
|
||||
static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
|
||||
{
|
||||
struct vc4_plane_state *vc4_state;
|
||||
|
||||
|
@ -97,8 +97,8 @@ struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane)
|
|||
return &vc4_state->base;
|
||||
}
|
||||
|
||||
void vc4_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
static void vc4_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
|
||||
|
||||
|
@ -108,7 +108,7 @@ void vc4_plane_destroy_state(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
/* Called during init to allocate the plane's atomic state. */
|
||||
void vc4_plane_reset(struct drm_plane *plane)
|
||||
static void vc4_plane_reset(struct drm_plane *plane)
|
||||
{
|
||||
struct vc4_plane_state *vc4_state;
|
||||
|
||||
|
@ -157,6 +157,16 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
|
|||
int crtc_w = state->crtc_w;
|
||||
int crtc_h = state->crtc_h;
|
||||
|
||||
if (state->crtc_w << 16 != state->src_w ||
|
||||
state->crtc_h << 16 != state->src_h) {
|
||||
/* We don't support scaling yet, which involves
|
||||
* allocating the LBM memory for scaling temporary
|
||||
* storage, and putting filter kernels in the HVS
|
||||
* context.
|
||||
*/
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (crtc_x < 0) {
|
||||
offset += drm_format_plane_cpp(fb->pixel_format, 0) * -crtc_x;
|
||||
crtc_w += crtc_x;
|
||||
|
|
|
@ -136,6 +136,9 @@ drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,
|
|||
|
||||
void drm_atomic_legacy_backoff(struct drm_atomic_state *state);
|
||||
|
||||
void
|
||||
drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
|
||||
|
||||
int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
|
||||
int __must_check drm_atomic_commit(struct drm_atomic_state *state);
|
||||
int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
|
||||
|
|
Loading…
Reference in a new issue