Commit 793423ff authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-next-4.4' of git://people.freedesktop.org/~agd5f/linux into drm-next

- Updated register headers for GFX 8.1 for Stoney
- Add some new CZ revisions
- minor pageflip optimizations
- Fencing clean up
- Warning fix
- More fence cleanup
- oops fix
- Fiji fixes

* 'drm-next-4.4' of git://people.freedesktop.org/~agd5f/linux: (29 commits)
  drm/amdgpu: group together common fence implementation
  drm/amdgpu: remove AMDGPU_FENCE_OWNER_MOVE
  drm/amdgpu: remove now unused fence functions
  drm/amdgpu: fix fence fallback check
  drm/amdgpu: fix stoping the scheduler timeout
  drm/amdgpu: cleanup on error in amdgpu_cs_ioctl()
  drm/amdgpu: update Fiji's Golden setting
  drm/amdgpu: update Fiji's rev id
  drm/amdgpu: extract common code in vi_common_early_init
  drm/amd/scheduler: don't oops on failure to load
  drm/amdgpu: don't oops on failure to load (v2)
  drm/amdgpu: don't VT switch on suspend
  drm/amdgpu: Make amdgpu_mn functions inline
  drm/amdgpu: remove amdgpu_fence_ref/unref
  drm/amdgpu: use common fence for sync
  drm/amdgpu: use the new fence_is_later
  drm/amdgpu: use common fences for VMID management v2
  drm/amdgpu: move ring_from_fence to common code
  drm/amdgpu: switch to common fence_wait_any_timeout v2
  drm/amdgpu: remove unneeded fence functions
  ...
parents bf248ca1 a95e2642
...@@ -397,6 +397,104 @@ fence_default_wait(struct fence *fence, bool intr, signed long timeout) ...@@ -397,6 +397,104 @@ fence_default_wait(struct fence *fence, bool intr, signed long timeout)
} }
EXPORT_SYMBOL(fence_default_wait); EXPORT_SYMBOL(fence_default_wait);
static bool
fence_test_signaled_any(struct fence **fences, uint32_t count)
{
int i;
for (i = 0; i < count; ++i) {
struct fence *fence = fences[i];
if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
return true;
}
return false;
}
/**
* fence_wait_any_timeout - sleep until any fence gets signaled
* or until timeout elapses
* @fences: [in] array of fences to wait on
* @count: [in] number of fences to wait on
* @intr: [in] if true, do an interruptible wait
* @timeout: [in] timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
*
* Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if
* interrupted, 0 if the wait timed out, or the remaining timeout in jiffies
* on success.
*
* Synchronous waits for the first fence in the array to be signaled. The
* caller needs to hold a reference to all fences in the array, otherwise a
* fence might be freed before return, resulting in undefined behavior.
*/
signed long
fence_wait_any_timeout(struct fence **fences, uint32_t count,
bool intr, signed long timeout)
{
struct default_wait_cb *cb;
signed long ret = timeout;
unsigned i;
if (WARN_ON(!fences || !count || timeout < 0))
return -EINVAL;
if (timeout == 0) {
for (i = 0; i < count; ++i)
if (fence_is_signaled(fences[i]))
return 1;
return 0;
}
cb = kcalloc(count, sizeof(struct default_wait_cb), GFP_KERNEL);
if (cb == NULL) {
ret = -ENOMEM;
goto err_free_cb;
}
for (i = 0; i < count; ++i) {
struct fence *fence = fences[i];
if (fence->ops->wait != fence_default_wait) {
ret = -EINVAL;
goto fence_rm_cb;
}
cb[i].task = current;
if (fence_add_callback(fence, &cb[i].base,
fence_default_wait_cb)) {
/* This fence is already signaled */
goto fence_rm_cb;
}
}
while (ret > 0) {
if (intr)
set_current_state(TASK_INTERRUPTIBLE);
else
set_current_state(TASK_UNINTERRUPTIBLE);
if (fence_test_signaled_any(fences, count))
break;
ret = schedule_timeout(ret);
if (ret > 0 && intr && signal_pending(current))
ret = -ERESTARTSYS;
}
__set_current_state(TASK_RUNNING);
fence_rm_cb:
while (i-- > 0)
fence_remove_callback(fences[i], &cb[i].base);
err_free_cb:
kfree(cb);
return ret;
}
EXPORT_SYMBOL(fence_wait_any_timeout);
/** /**
* fence_init - Initialize a custom fence. * fence_init - Initialize a custom fence.
* @fence: [in] the fence to initialize * @fence: [in] the fence to initialize
......
...@@ -405,7 +405,6 @@ struct amdgpu_fence_driver { ...@@ -405,7 +405,6 @@ struct amdgpu_fence_driver {
/* some special values for the owner field */ /* some special values for the owner field */
#define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul) #define AMDGPU_FENCE_OWNER_UNDEFINED ((void*)0ul)
#define AMDGPU_FENCE_OWNER_VM ((void*)1ul) #define AMDGPU_FENCE_OWNER_VM ((void*)1ul)
#define AMDGPU_FENCE_OWNER_MOVE ((void*)2ul)
#define AMDGPU_FENCE_FLAG_64BIT (1 << 0) #define AMDGPU_FENCE_FLAG_64BIT (1 << 0)
#define AMDGPU_FENCE_FLAG_INT (1 << 1) #define AMDGPU_FENCE_FLAG_INT (1 << 1)
...@@ -447,57 +446,11 @@ int amdgpu_fence_wait_next(struct amdgpu_ring *ring); ...@@ -447,57 +446,11 @@ int amdgpu_fence_wait_next(struct amdgpu_ring *ring);
int amdgpu_fence_wait_empty(struct amdgpu_ring *ring); int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
signed long amdgpu_fence_wait_any(struct fence **array,
uint32_t count,
bool intr,
signed long t);
struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence);
void amdgpu_fence_unref(struct amdgpu_fence **fence);
bool amdgpu_fence_need_sync(struct amdgpu_fence *fence, bool amdgpu_fence_need_sync(struct amdgpu_fence *fence,
struct amdgpu_ring *ring); struct amdgpu_ring *ring);
void amdgpu_fence_note_sync(struct amdgpu_fence *fence, void amdgpu_fence_note_sync(struct amdgpu_fence *fence,
struct amdgpu_ring *ring); struct amdgpu_ring *ring);
static inline struct amdgpu_fence *amdgpu_fence_later(struct amdgpu_fence *a,
struct amdgpu_fence *b)
{
if (!a) {
return b;
}
if (!b) {
return a;
}
BUG_ON(a->ring != b->ring);
if (a->seq > b->seq) {
return a;
} else {
return b;
}
}
static inline bool amdgpu_fence_is_earlier(struct amdgpu_fence *a,
struct amdgpu_fence *b)
{
if (!a) {
return false;
}
if (!b) {
return true;
}
BUG_ON(a->ring != b->ring);
return a->seq < b->seq;
}
int amdgpu_user_fence_emit(struct amdgpu_ring *ring, struct amdgpu_user_fence *user,
void *owner, struct amdgpu_fence **fence);
/* /*
* TTM. * TTM.
*/ */
...@@ -708,7 +661,7 @@ void amdgpu_semaphore_free(struct amdgpu_device *adev, ...@@ -708,7 +661,7 @@ void amdgpu_semaphore_free(struct amdgpu_device *adev,
*/ */
struct amdgpu_sync { struct amdgpu_sync {
struct amdgpu_semaphore *semaphores[AMDGPU_NUM_SYNCS]; struct amdgpu_semaphore *semaphores[AMDGPU_NUM_SYNCS];
struct amdgpu_fence *sync_to[AMDGPU_MAX_RINGS]; struct fence *sync_to[AMDGPU_MAX_RINGS];
DECLARE_HASHTABLE(fences, 4); DECLARE_HASHTABLE(fences, 4);
struct fence *last_vm_update; struct fence *last_vm_update;
}; };
...@@ -974,7 +927,7 @@ struct amdgpu_vm_id { ...@@ -974,7 +927,7 @@ struct amdgpu_vm_id {
/* last flushed PD/PT update */ /* last flushed PD/PT update */
struct fence *flushed_updates; struct fence *flushed_updates;
/* last use of vmid */ /* last use of vmid */
struct amdgpu_fence *last_id_use; struct fence *last_id_use;
}; };
struct amdgpu_vm { struct amdgpu_vm {
...@@ -1007,7 +960,7 @@ struct amdgpu_vm { ...@@ -1007,7 +960,7 @@ struct amdgpu_vm {
}; };
struct amdgpu_vm_manager { struct amdgpu_vm_manager {
struct amdgpu_fence *active[AMDGPU_NUM_VM]; struct fence *active[AMDGPU_NUM_VM];
uint32_t max_pfn; uint32_t max_pfn;
/* number of VMIDs */ /* number of VMIDs */
unsigned nvm; unsigned nvm;
...@@ -1235,6 +1188,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, ...@@ -1235,6 +1188,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
struct amdgpu_irq_src *irq_src, unsigned irq_type, struct amdgpu_irq_src *irq_src, unsigned irq_type,
enum amdgpu_ring_type ring_type); enum amdgpu_ring_type ring_type);
void amdgpu_ring_fini(struct amdgpu_ring *ring); void amdgpu_ring_fini(struct amdgpu_ring *ring);
struct amdgpu_ring *amdgpu_ring_from_fence(struct fence *f);
/* /*
* CS. * CS.
...@@ -1758,11 +1712,11 @@ void amdgpu_test_syncing(struct amdgpu_device *adev); ...@@ -1758,11 +1712,11 @@ void amdgpu_test_syncing(struct amdgpu_device *adev);
int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr); int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr);
void amdgpu_mn_unregister(struct amdgpu_bo *bo); void amdgpu_mn_unregister(struct amdgpu_bo *bo);
#else #else
static int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) static inline int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
{ {
return -ENODEV; return -ENODEV;
} }
static void amdgpu_mn_unregister(struct amdgpu_bo *bo) {} static inline void amdgpu_mn_unregister(struct amdgpu_bo *bo) {}
#endif #endif
/* /*
......
...@@ -876,8 +876,10 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ...@@ -876,8 +876,10 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
struct amdgpu_job *job; struct amdgpu_job *job;
struct amdgpu_ring * ring = parser->ibs->ring; struct amdgpu_ring * ring = parser->ibs->ring;
job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL); job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
if (!job) if (!job) {
return -ENOMEM; r = -ENOMEM;
goto out;
}
job->base.sched = &ring->sched; job->base.sched = &ring->sched;
job->base.s_entity = &parser->ctx->rings[ring->idx].entity; job->base.s_entity = &parser->ctx->rings[ring->idx].entity;
job->adev = parser->adev; job->adev = parser->adev;
......
...@@ -69,6 +69,9 @@ void amdgpu_ctx_fini(struct amdgpu_ctx *ctx) ...@@ -69,6 +69,9 @@ void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)
struct amdgpu_device *adev = ctx->adev; struct amdgpu_device *adev = ctx->adev;
unsigned i, j; unsigned i, j;
if (!adev)
return;
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
for (j = 0; j < AMDGPU_CTX_MAX_CS_PENDING; ++j) for (j = 0; j < AMDGPU_CTX_MAX_CS_PENDING; ++j)
fence_put(ctx->rings[i].fences[j]); fence_put(ctx->rings[i].fences[j]);
......
...@@ -207,6 +207,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, ...@@ -207,6 +207,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
} }
info->par = rfbdev; info->par = rfbdev;
info->skip_vt_switch = true;
ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj); ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
if (ret) { if (ret) {
......
...@@ -136,42 +136,6 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner, ...@@ -136,42 +136,6 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, void *owner,
return 0; return 0;
} }
/**
* amdgpu_fence_check_signaled - callback from fence_queue
*
* this function is called with fence_queue lock held, which is also used
* for the fence locking itself, so unlocked variants are used for
* fence_signal, and remove_wait_queue.
*/
static int amdgpu_fence_check_signaled(wait_queue_t *wait, unsigned mode, int flags, void *key)
{
struct amdgpu_fence *fence;
struct amdgpu_device *adev;
u64 seq;
int ret;
fence = container_of(wait, struct amdgpu_fence, fence_wake);
adev = fence->ring->adev;
/*
* We cannot use amdgpu_fence_process here because we're already
* in the waitqueue, in a call from wake_up_all.
*/
seq = atomic64_read(&fence->ring->fence_drv.last_seq);
if (seq >= fence->seq) {
ret = fence_signal_locked(&fence->base);
if (!ret)
FENCE_TRACE(&fence->base, "signaled from irq context\n");
else
FENCE_TRACE(&fence->base, "was already signaled\n");
__remove_wait_queue(&fence->ring->fence_drv.fence_queue, &fence->fence_wake);
fence_put(&fence->base);
} else
FENCE_TRACE(&fence->base, "pending\n");
return 0;
}
/** /**
* amdgpu_fence_activity - check for fence activity * amdgpu_fence_activity - check for fence activity
* *
...@@ -305,47 +269,6 @@ static bool amdgpu_fence_seq_signaled(struct amdgpu_ring *ring, u64 seq) ...@@ -305,47 +269,6 @@ static bool amdgpu_fence_seq_signaled(struct amdgpu_ring *ring, u64 seq)
return false; return false;
} }
static bool amdgpu_fence_is_signaled(struct fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
struct amdgpu_ring *ring = fence->ring;
if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
return true;
amdgpu_fence_process(ring);
if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
return true;
return false;
}
/**
* amdgpu_fence_enable_signaling - enable signalling on fence
* @fence: fence
*
* This function is called with fence_queue lock held, and adds a callback
* to fence_queue that checks if this fence is signaled, and if so it
* signals the fence and removes itself.
*/
static bool amdgpu_fence_enable_signaling(struct fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
struct amdgpu_ring *ring = fence->ring;
if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
return false;
fence->fence_wake.flags = 0;
fence->fence_wake.private = NULL;
fence->fence_wake.func = amdgpu_fence_check_signaled;
__add_wait_queue(&ring->fence_drv.fence_queue, &fence->fence_wake);
fence_get(f);
FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
return true;
}
/* /*
* amdgpu_ring_wait_seq_timeout - wait for seq of the specific ring to signal * amdgpu_ring_wait_seq_timeout - wait for seq of the specific ring to signal
* @ring: ring to wait on for the seq number * @ring: ring to wait on for the seq number
...@@ -367,6 +290,7 @@ static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq) ...@@ -367,6 +290,7 @@ static int amdgpu_fence_ring_wait_seq(struct amdgpu_ring *ring, uint64_t seq)
if (atomic64_read(&ring->fence_drv.last_seq) >= seq) if (atomic64_read(&ring->fence_drv.last_seq) >= seq)
return 0; return 0;
amdgpu_fence_schedule_check(ring);
wait_event(ring->fence_drv.fence_queue, ( wait_event(ring->fence_drv.fence_queue, (
(signaled = amdgpu_fence_seq_signaled(ring, seq)))); (signaled = amdgpu_fence_seq_signaled(ring, seq))));
...@@ -416,36 +340,6 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring) ...@@ -416,36 +340,6 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring)
return amdgpu_fence_ring_wait_seq(ring, seq); return amdgpu_fence_ring_wait_seq(ring, seq);
} }
/**
* amdgpu_fence_ref - take a ref on a fence
*
* @fence: amdgpu fence object
*
* Take a reference on a fence (all asics).
* Returns the fence.
*/
struct amdgpu_fence *amdgpu_fence_ref(struct amdgpu_fence *fence)
{
fence_get(&fence->base);
return fence;
}
/**
* amdgpu_fence_unref - remove a ref on a fence
*
* @fence: amdgpu fence object
*
* Remove a reference on a fence (all asics).
*/
void amdgpu_fence_unref(struct amdgpu_fence **fence)
{
struct amdgpu_fence *tmp = *fence;
*fence = NULL;
if (tmp)
fence_put(&tmp->base);
}
/** /**
* amdgpu_fence_count_emitted - get the count of emitted fences * amdgpu_fence_count_emitted - get the count of emitted fences
* *
...@@ -761,6 +655,115 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev) ...@@ -761,6 +655,115 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev)
} }
} }
/*
* Common fence implementation
*/
static const char *amdgpu_fence_get_driver_name(struct fence *fence)
{
return "amdgpu";
}
static const char *amdgpu_fence_get_timeline_name(struct fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
return (const char *)fence->ring->name;
}
/**
* amdgpu_fence_is_signaled - test if fence is signaled
*
* @f: fence to test
*
* Test the fence sequence number if it is already signaled. If it isn't
* signaled start fence processing. Returns True if the fence is signaled.
*/
static bool amdgpu_fence_is_signaled(struct fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
struct amdgpu_ring *ring = fence->ring;
if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
return true;
amdgpu_fence_process(ring);
if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
return true;
return false;
}
/**
* amdgpu_fence_check_signaled - callback from fence_queue
*
* this function is called with fence_queue lock held, which is also used
* for the fence locking itself, so unlocked variants are used for
* fence_signal, and remove_wait_queue.
*/
static int amdgpu_fence_check_signaled(wait_queue_t *wait, unsigned mode, int flags, void *key)
{
struct amdgpu_fence *fence;
struct amdgpu_device *adev;
u64 seq;
int ret;
fence = container_of(wait, struct amdgpu_fence, fence_wake);
adev = fence->ring->adev;
/*
* We cannot use amdgpu_fence_process here because we're already
* in the waitqueue, in a call from wake_up_all.
*/
seq = atomic64_read(&fence->ring->fence_drv.last_seq);
if (seq >= fence->seq) {
ret = fence_signal_locked(&fence->base);
if (!ret)
FENCE_TRACE(&fence->base, "signaled from irq context\n");
else
FENCE_TRACE(&fence->base, "was already signaled\n");
__remove_wait_queue(&fence->ring->fence_drv.fence_queue, &fence->fence_wake);
fence_put(&fence->base);
} else
FENCE_TRACE(&fence->base, "pending\n");
return 0;
}
/**
* amdgpu_fence_enable_signaling - enable signalling on fence
* @fence: fence
*
* This function is called with fence_queue lock held, and adds a callback
* to fence_queue that checks if this fence is signaled, and if so it
* signals the fence and removes itself.
*/
static bool amdgpu_fence_enable_signaling(struct fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
struct amdgpu_ring *ring = fence->ring;
if (atomic64_read(&ring->fence_drv.last_seq) >= fence->seq)
return false;
fence->fence_wake.flags = 0;
fence->fence_wake.private = NULL;
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);
FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
return true;
}
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,
};
/* /*
* Fence debugfs * Fence debugfs
...@@ -811,131 +814,3 @@ int amdgpu_debugfs_fence_init(struct amdgpu_device *adev) ...@@ -811,131 +814,3 @@ int amdgpu_debugfs_fence_init(struct amdgpu_device *adev)
#endif #endif
} }
static const char *amdgpu_fence_get_driver_name(struct fence *fence)
{
return "amdgpu";
}
static const char *amdgpu_fence_get_timeline_name(struct fence *f)
{
struct amdgpu_fence *fence = to_amdgpu_fence(f);
return (const char *)fence->ring->name;
}
static inline bool amdgpu_test_signaled(struct amdgpu_fence *fence)
{
return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags);
}
static bool amdgpu_test_signaled_any(struct fence **fences, uint32_t count)
{
int idx;
struct fence *fence;
for (idx = 0; idx < count; ++idx) {
fence = fences[idx];
if (fence) {
if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
return true;
}
}
return false;
}
struct amdgpu_wait_cb {
struct fence_cb base;
struct task_struct *task;
};
static void amdgpu_fence_wait_cb(struct fence *fence, struct fence_cb *cb)
{
struct amdgpu_wait_cb *wait =
container_of(cb, struct amdgpu_wait_cb, base);
wake_up_process(wait->task);
}
static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
signed long t)
{
return amdgpu_fence_wait_any(&f, 1, intr, t);
}
/**
* Wait the fence array with timeout
*
* @array: the fence array with amdgpu fence pointer
* @count: the number of the fence array
* @intr: when sleep, set the current task interruptable or not
* @t: timeout to wait
*
* It will return when any fence is signaled or timeout.
*/
signed long amdgpu_fence_wait_any(struct fence **array, uint32_t count,
bool intr, signed long t)
{
struct amdgpu_wait_cb *cb;
struct fence *fence;
unsigned idx;
BUG_ON(!array);
cb = kcalloc(count, sizeof(struct amdgpu_wait_cb), GFP_KERNEL);
if (cb == NULL) {
t = -ENOMEM;
goto err_free_cb;
}
for (idx = 0; idx < count; ++idx) {
fence = array[idx];
if (fence) {
cb[idx].task = current;
if (fence_add_callback(fence,
&cb[idx].base, amdgpu_fence_wait_cb)) {
/* The fence is already signaled */
goto fence_rm_cb;
}
}
}
while (t > 0) {
if (intr)
set_current_state(TASK_INTERRUPTIBLE);
else
set_current_state(TASK_UNINTERRUPTIBLE);
/*
* amdgpu_test_signaled_any must be called after
* set_current_state to prevent a race with wake_up_process
*/
if (amdgpu_test_signaled_any(array, count))
break;
t = schedule_timeout(t);
if (t > 0 && intr && signal_pending(current))
t = -ERESTARTSYS;
}
__set_current_state(TASK_RUNNING);
fence_rm_cb:
for (idx = 0; idx < count; ++idx) {
fence = array[idx];
if (fence && cb[idx].base.func)
fence_remove_callback(fence, &cb[idx].base);
}
err_free_cb:
kfree(cb);
return t;
}
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 = amdgpu_fence_default_wait,
.release = NULL,
};
...@@ -95,7 +95,8 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib) ...@@ -95,7 +95,8 @@ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib)
{ {
amdgpu_sync_free(adev, &ib->sync, &ib->fence->base); amdgpu_sync_free(adev, &ib->sync, &ib->fence->base);
amdgpu_sa_bo_free(adev, &ib->sa_bo, &ib->fence->base); amdgpu_sa_bo_free(adev, &ib->sa_bo, &ib->fence->base);
amdgpu_fence_unref(&ib->fence); if (ib->fence)
fence_put(&ib->fence->base);
} }
/** /**
......
...@@ -436,6 +436,30 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring) ...@@ -436,6 +436,30 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
} }
} }
/**
* amdgpu_ring_from_fence - get ring from fence
*
* @f: fence structure
*
* Extract the ring a fence belongs to. Handles both scheduler as
* well as hardware fences.
*/
struct amdgpu_ring *amdgpu_ring_from_fence(struct fence *f)
{
struct amdgpu_fence *a_fence;
struct amd_sched_fence *s_fence;
s_fence = to_amd_sched_fence(f);
if (s_fence)
return container_of(s_fence->sched, struct amdgpu_ring, sched);
a_fence = to_amdgpu_fence(f);
if (a_fence)
return a_fence->ring;
return NULL;
}
/* /*
* Debugfs info * Debugfs info
*/ */
......
...@@ -139,25 +139,6 @@ int amdgpu_sa_bo_manager_suspend(struct amdgpu_device *adev, ...@@ -139,25 +139,6 @@ int amdgpu_sa_bo_manager_suspend(struct amdgpu_device *adev,
return r; return r;
} }
static uint32_t amdgpu_sa_get_ring_from_fence(struct fence *f)
{
struct amdgpu_fence *a_fence;
struct amd_sched_fence *s_fence;
s_fence = to_amd_sched_fence(f);
if (s_fence) {
struct amdgpu_ring *ring;
ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
return ring->idx;
}
a_fence = to_amdgpu_fence(f);
if (a_fence)
return a_fence->ring->idx;
return 0;
}
static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo) static void amdgpu_sa_bo_remove_locked(struct amdgpu_sa_bo *sa_bo)
{ {
struct amdgpu_sa_manager *sa_manager = sa_bo->manager; struct amdgpu_sa_manager *sa_manager = sa_bo->manager;
...@@ -318,7 +299,7 @@ static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager, ...@@ -318,7 +299,7 @@ static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager,
} }
if (best_bo) { if (best_bo) {
uint32_t idx = amdgpu_sa_get_ring_from_fence(best_bo->fence); uint32_t idx = amdgpu_ring_from_fence(best_bo->fence)->idx;
++tries[idx]; ++tries[idx];
sa_manager->hole = best_bo->olist.prev; sa_manager->hole = best_bo->olist.prev;
...@@ -337,6 +318,7 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev, ...@@ -337,6 +318,7 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev,
{ {
struct fence *fences[AMDGPU_MAX_RINGS]; struct fence *fences[AMDGPU_MAX_RINGS];
unsigned tries[AMDGPU_MAX_RINGS]; unsigned tries[AMDGPU_MAX_RINGS];
unsigned count;
int i, r; int i, r;
signed long t; signed long t;
...@@ -371,13 +353,18 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev, ...@@ -371,13 +353,18 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev,
/* see if we can skip over some allocations */ /* see if we can skip over some allocations */
} while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries)); } while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries));
spin_unlock(&sa_manager->wq.lock); for (i = 0, count = 0; i < AMDGPU_MAX_RINGS; ++i)
t = amdgpu_fence_wait_any(fences, AMDGPU_MAX_RINGS, if (fences[i])
false, MAX_SCHEDULE_TIMEOUT); fences[count++] = fences[i];
r = (t > 0) ? 0 : t;
spin_lock(&sa_manager->wq.lock); if (count) {
/* if we have nothing to wait for block */ spin_unlock(&sa_manager->wq.lock);
if (r == -ENOENT) { t = fence_wait_any_timeout(fences, count, false,
MAX_SCHEDULE_TIMEOUT);
r = (t > 0) ? 0 : t;
spin_lock(&sa_manager->wq.lock);
} else {
/* if we have nothing to wait for block */
r = wait_event_interruptible_locked( r = wait_event_interruptible_locked(
sa_manager->wq, sa_manager->wq,
amdgpu_sa_event(sa_manager, size, align) amdgpu_sa_event(sa_manager, size, align)
...@@ -406,7 +393,7 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo, ...@@ -406,7 +393,7 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo,
if (fence && !fence_is_signaled(fence)) { if (fence && !fence_is_signaled(fence)) {
uint32_t idx; uint32_t idx;
(*sa_bo)->fence = fence_get(fence); (*sa_bo)->fence = fence_get(fence);
idx = amdgpu_sa_get_ring_from_fence(fence); idx = amdgpu_ring_from_fence(fence)->idx;
list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[idx]); list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[idx]);
} else { } else {
amdgpu_sa_bo_remove_locked(*sa_bo); amdgpu_sa_bo_remove_locked(*sa_bo);
......
...@@ -54,7 +54,8 @@ static struct fence *amdgpu_sched_run_job(struct amd_sched_job *sched_job) ...@@ -54,7 +54,8 @@ static struct fence *amdgpu_sched_run_job(struct amd_sched_job *sched_job)
goto err; goto err;
} }
fence = amdgpu_fence_ref(job->ibs[job->num_ibs - 1].fence); fence = job->ibs[job->num_ibs - 1].fence;
fence_get(&fence->base);
err: err:
if (job->free_job) if (job->free_job)
......
...@@ -87,6 +87,15 @@ static bool amdgpu_sync_test_owner(struct fence *f, void *owner) ...@@ -87,6 +87,15 @@ static bool amdgpu_sync_test_owner(struct fence *f, void *owner)
return false; return false;
} }
static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence)
{
if (*keep && fence_is_later(*keep, fence))
return;
fence_put(*keep);
*keep = fence_get(fence);
}
/** /**
* amdgpu_sync_fence - remember to sync to this fence * amdgpu_sync_fence - remember to sync to this fence
* *
...@@ -99,35 +108,21 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, ...@@ -99,35 +108,21 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
{ {
struct amdgpu_sync_entry *e; struct amdgpu_sync_entry *e;
struct amdgpu_fence *fence; struct amdgpu_fence *fence;
struct amdgpu_fence *other;
struct fence *tmp, *later;
if (!f) if (!f)
return 0; return 0;
if (amdgpu_sync_same_dev(adev, f) && if (amdgpu_sync_same_dev(adev, f) &&
amdgpu_sync_test_owner(f, AMDGPU_FENCE_OWNER_VM)) { amdgpu_sync_test_owner(f, AMDGPU_FENCE_OWNER_VM))
if (sync->last_vm_update) { amdgpu_sync_keep_later(&sync->last_vm_update, f);
tmp = sync->last_vm_update;
BUG_ON(f->context != tmp->context);
later = (f->seqno - tmp->seqno <= INT_MAX) ? f : tmp;
sync->last_vm_update = fence_get(later);
fence_put(tmp);
} else
sync->last_vm_update = fence_get(f);
}
fence = to_amdgpu_fence(f); fence = to_amdgpu_fence(f);
if (!fence || fence->ring->adev != adev) { if (!fence || fence->ring->adev != adev) {
hash_for_each_possible(sync->fences, e, node, f->context) { hash_for_each_possible(sync->fences, e, node, f->context) {
struct fence *new;
if (unlikely(e->fence->context != f->context)) if (unlikely(e->fence->context != f->context))
continue; continue;
new = fence_get(fence_later(e->fence, f));
if (new) { amdgpu_sync_keep_later(&e->fence, f);
fence_put(e->fence);
e->fence = new;
}
return 0; return 0;
} }
...@@ -140,10 +135,7 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, ...@@ -140,10 +135,7 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
return 0; return 0;
} }
other = sync->sync_to[fence->ring->idx]; amdgpu_sync_keep_later(&sync->sync_to[fence->ring->idx], f);
sync->sync_to[fence->ring->idx] = amdgpu_fence_ref(
amdgpu_fence_later(fence, other));
amdgpu_fence_unref(&other);
return 0; return 0;
} }
...@@ -199,8 +191,8 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, ...@@ -199,8 +191,8 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
* for other VM updates and moves. * for other VM updates and moves.
*/ */
fence_owner = amdgpu_sync_get_owner(f); fence_owner = amdgpu_sync_get_owner(f);
if ((owner != AMDGPU_FENCE_OWNER_MOVE) && if ((owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
(fence_owner != AMDGPU_FENCE_OWNER_MOVE) && (fence_owner != AMDGPU_FENCE_OWNER_UNDEFINED) &&
((owner == AMDGPU_FENCE_OWNER_VM) != ((owner == AMDGPU_FENCE_OWNER_VM) !=
(fence_owner == AMDGPU_FENCE_OWNER_VM))) (fence_owner == AMDGPU_FENCE_OWNER_VM)))
continue; continue;
...@@ -262,11 +254,11 @@ int amdgpu_sync_wait(struct amdgpu_sync *sync) ...@@ -262,11 +254,11 @@ int amdgpu_sync_wait(struct amdgpu_sync *sync)
return 0; return 0;
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_fence *fence = sync->sync_to[i]; struct fence *fence = sync->sync_to[i];
if (!fence) if (!fence)
continue; continue;
r = fence_wait(&fence->base, false); r = fence_wait(fence, false);
if (r) if (r)
return r; return r;
} }
...@@ -291,9 +283,14 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync, ...@@ -291,9 +283,14 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
int i, r; int i, r;
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_fence *fence = sync->sync_to[i];
struct amdgpu_semaphore *semaphore;
struct amdgpu_ring *other = adev->rings[i]; struct amdgpu_ring *other = adev->rings[i];
struct amdgpu_semaphore *semaphore;
struct amdgpu_fence *fence;
if (!sync->sync_to[i])
continue;
fence = to_amdgpu_fence(sync->sync_to[i]);
/* check if we really need to sync */ /* check if we really need to sync */
if (!amdgpu_fence_need_sync(fence, ring)) if (!amdgpu_fence_need_sync(fence, ring))
...@@ -378,7 +375,7 @@ void amdgpu_sync_free(struct amdgpu_device *adev, ...@@ -378,7 +375,7 @@ void amdgpu_sync_free(struct amdgpu_device *adev,
amdgpu_semaphore_free(adev, &sync->semaphores[i], fence); amdgpu_semaphore_free(adev, &sync->semaphores[i], fence);
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
amdgpu_fence_unref(&sync->sync_to[i]); fence_put(sync->sync_to[i]);
fence_put(sync->last_vm_update); fence_put(sync->last_vm_update);
} }
...@@ -1041,7 +1041,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, ...@@ -1041,7 +1041,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring,
WARN_ON(ib->length_dw > num_dw); WARN_ON(ib->length_dw > num_dw);
r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1, r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, ib, 1,
&amdgpu_vm_free_job, &amdgpu_vm_free_job,
AMDGPU_FENCE_OWNER_MOVE, AMDGPU_FENCE_OWNER_UNDEFINED,
fence); fence);
if (r) if (r)
goto error_free; goto error_free;
......
...@@ -135,7 +135,7 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, ...@@ -135,7 +135,7 @@ struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev,
int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
struct amdgpu_sync *sync) struct amdgpu_sync *sync)
{ {
struct amdgpu_fence *best[AMDGPU_MAX_RINGS] = {}; struct fence *best[AMDGPU_MAX_RINGS] = {};
struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx]; struct amdgpu_vm_id *vm_id = &vm->ids[ring->idx];
struct amdgpu_device *adev = ring->adev; struct amdgpu_device *adev = ring->adev;
...@@ -154,7 +154,8 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, ...@@ -154,7 +154,8 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
/* skip over VMID 0, since it is the system VM */ /* skip over VMID 0, since it is the system VM */
for (i = 1; i < adev->vm_manager.nvm; ++i) { for (i = 1; i < adev->vm_manager.nvm; ++i) {
struct amdgpu_fence *fence = adev->vm_manager.active[i]; struct fence *fence = adev->vm_manager.active[i];
struct amdgpu_ring *fring;
if (fence == NULL) { if (fence == NULL) {
/* found a free one */ /* found a free one */
...@@ -163,21 +164,23 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, ...@@ -163,21 +164,23 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
return 0; return 0;
} }
if (amdgpu_fence_is_earlier(fence, best[fence->ring->idx])) { fring = amdgpu_ring_from_fence(fence);
best[fence->ring->idx] = fence; if (best[fring->idx] == NULL ||
choices[fence->ring == ring ? 0 : 1] = i; fence_is_later(best[fring->idx], fence)) {
best[fring->idx] = fence;
choices[fring == ring ? 0 : 1] = i;
} }
} }
for (i = 0; i < 2; ++i) { for (i = 0; i < 2; ++i) {
if (choices[i]) { if (choices[i]) {
struct amdgpu_fence *fence; struct fence *fence;
fence = adev->vm_manager.active[choices[i]]; fence = adev->vm_manager.active[choices[i]];
vm_id->id = choices[i]; vm_id->id = choices[i];
trace_amdgpu_vm_grab_id(choices[i], ring->idx); trace_amdgpu_vm_grab_id(choices[i], ring->idx);
return amdgpu_sync_fence(ring->adev, sync, &fence->base); return amdgpu_sync_fence(ring->adev, sync, fence);
} }
} }
...@@ -246,11 +249,11 @@ void amdgpu_vm_fence(struct amdgpu_device *adev, ...@@ -246,11 +249,11 @@ void amdgpu_vm_fence(struct amdgpu_device *adev,
unsigned ridx = fence->ring->idx; unsigned ridx = fence->ring->idx;
unsigned vm_id = vm->ids[ridx].id; unsigned vm_id = vm->ids[ridx].id;
amdgpu_fence_unref(&adev->vm_manager.active[vm_id]); fence_put(adev->vm_manager.active[vm_id]);
adev->vm_manager.active[vm_id] = amdgpu_fence_ref(fence); adev->vm_manager.active[vm_id] = fence_get(&fence->base);
amdgpu_fence_unref(&vm->ids[ridx].last_id_use); fence_put(vm->ids[ridx].last_id_use);
vm->ids[ridx].last_id_use = amdgpu_fence_ref(fence); vm->ids[ridx].last_id_use = fence_get(&fence->base);
} }
/** /**
...@@ -1313,7 +1316,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) ...@@ -1313,7 +1316,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
fence_put(vm->ids[i].flushed_updates); fence_put(vm->ids[i].flushed_updates);
amdgpu_fence_unref(&vm->ids[i].last_id_use); fence_put(vm->ids[i].last_id_use);
} }
mutex_destroy(&vm->mutex); mutex_destroy(&vm->mutex);
......
...@@ -262,46 +262,22 @@ static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) ...@@ -262,46 +262,22 @@ static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
* @crtc_id: crtc to cleanup pageflip on * @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address) * @crtc_base: new address of the crtc (GPU MC address)
* *
* Does the actual pageflip (evergreen+). * Triggers the actual pageflip by updating the primary
* During vblank we take the crtc lock and wait for the update_pending * surface base address.
* bit to go high, when it does, we release the lock, and allow the
* double buffered update to take place.
* Returns the current update pending status.
*/ */
static void dce_v10_0_page_flip(struct amdgpu_device *adev, static void dce_v10_0_page_flip(struct amdgpu_device *adev,
int crtc_id, u64 crtc_base) int crtc_id, u64 crtc_base)
{ {
struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
u32 tmp = RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset);
int i;
/* Lock the graphics update lock */
tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
/* update the scanout addresses */
WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base));
WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
lower_32_bits(crtc_base));
/* update the primary scanout address */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base)); upper_32_bits(crtc_base));
/* writing to the low address triggers the update */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset, WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
lower_32_bits(crtc_base)); lower_32_bits(crtc_base));
/* post the write */
/* Wait for update_pending to go high. */ RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
for (i = 0; i < adev->usec_timeout; i++) {
if (RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset) &
GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK)
break;
udelay(1);
}
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
/* Unlock the lock, so double-buffering can take place inside vblank */
tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
} }
static int dce_v10_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, static int dce_v10_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
......
...@@ -252,46 +252,22 @@ static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) ...@@ -252,46 +252,22 @@ static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
* @crtc_id: crtc to cleanup pageflip on * @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address) * @crtc_base: new address of the crtc (GPU MC address)
* *
* Does the actual pageflip (evergreen+). * Triggers the actual pageflip by updating the primary
* During vblank we take the crtc lock and wait for the update_pending * surface base address.
* bit to go high, when it does, we release the lock, and allow the
* double buffered update to take place.
* Returns the current update pending status.
*/ */
static void dce_v11_0_page_flip(struct amdgpu_device *adev, static void dce_v11_0_page_flip(struct amdgpu_device *adev,
int crtc_id, u64 crtc_base) int crtc_id, u64 crtc_base)
{ {
struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
u32 tmp = RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset);
int i;
/* Lock the graphics update lock */
tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
/* update the scanout addresses */ /* update the scanout addresses */
WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base));
WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
lower_32_bits(crtc_base));
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base)); upper_32_bits(crtc_base));
/* writing to the low address triggers the update */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset, WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
lower_32_bits(crtc_base)); lower_32_bits(crtc_base));
/* post the write */
/* Wait for update_pending to go high. */ RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
for (i = 0; i < adev->usec_timeout; i++) {
if (RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset) &
GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK)
break;
udelay(1);
}
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
/* Unlock the lock, so double-buffering can take place inside vblank */
tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
} }
static int dce_v11_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, static int dce_v11_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
......
...@@ -211,46 +211,22 @@ static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc) ...@@ -211,46 +211,22 @@ static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
* @crtc_id: crtc to cleanup pageflip on * @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address) * @crtc_base: new address of the crtc (GPU MC address)
* *
* Does the actual pageflip (evergreen+). * Triggers the actual pageflip by updating the primary
* During vblank we take the crtc lock and wait for the update_pending * surface base address.
* bit to go high, when it does, we release the lock, and allow the
* double buffered update to take place.
* Returns the current update pending status.
*/ */
static void dce_v8_0_page_flip(struct amdgpu_device *adev, static void dce_v8_0_page_flip(struct amdgpu_device *adev,
int crtc_id, u64 crtc_base) int crtc_id, u64 crtc_base)
{ {
struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
u32 tmp = RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset);
int i;
/* Lock the graphics update lock */
tmp |= GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK;
WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
/* update the scanout addresses */
WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base));
WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
(u32)crtc_base);
/* update the primary scanout addresses */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
upper_32_bits(crtc_base)); upper_32_bits(crtc_base));
/* writing to the low address triggers the update */
WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset, WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
(u32)crtc_base); lower_32_bits(crtc_base));
/* post the write */
/* Wait for update_pending to go high. */ RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
for (i = 0; i < adev->usec_timeout; i++) {
if (RREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset) &
GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK)
break;
udelay(1);
}
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
/* Unlock the lock, so double-buffering can take place inside vblank */
tmp &= ~GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK;
WREG32(mmGRPH_UPDATE + amdgpu_crtc->crtc_offset, tmp);
} }
static int dce_v8_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, static int dce_v8_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
......
...@@ -235,11 +235,13 @@ static const u32 fiji_golden_common_all[] = ...@@ -235,11 +235,13 @@ static const u32 fiji_golden_common_all[] =
mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000, mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
mmPA_SC_RASTER_CONFIG, 0xffffffff, 0x3a00161a, mmPA_SC_RASTER_CONFIG, 0xffffffff, 0x3a00161a,
mmPA_SC_RASTER_CONFIG_1, 0xffffffff, 0x0000002e, mmPA_SC_RASTER_CONFIG_1, 0xffffffff, 0x0000002e,
mmGB_ADDR_CONFIG, 0xffffffff, 0x12011003, mmGB_ADDR_CONFIG, 0xffffffff, 0x22011003,
mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800,
mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800, mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800,
mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF, mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF,
mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF,
mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x00000009,
}; };
static const u32 golden_settings_fiji_a10[] = static const u32 golden_settings_fiji_a10[] =
...@@ -247,24 +249,26 @@ static const u32 golden_settings_fiji_a10[] = ...@@ -247,24 +249,26 @@ static const u32 golden_settings_fiji_a10[] =
mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040, mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,
mmDB_DEBUG2, 0xf00fffff, 0x00000400, mmDB_DEBUG2, 0xf00fffff, 0x00000400,
mmPA_SC_ENHANCE, 0xffffffff, 0x20000001, mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
mmPA_SC_FIFO_DEPTH_CNTL, 0x000003ff, 0x00000100,
mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0001003c,
mmSQ_RANDOM_WAVE_PRI, 0x001fffff, 0x000006fd,
mmTA_CNTL_AUX, 0x000f000f, 0x000b0000, mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
mmTCC_CTRL, 0x00100000, 0xf30fff7f, mmTCC_CTRL, 0x00100000, 0xf31fff7f,
mmTCC_EXE_DISABLE, 0x00000002, 0x00000002,
mmTCP_ADDR_CONFIG, 0x000003ff, 0x000000ff, mmTCP_ADDR_CONFIG, 0x000003ff, 0x000000ff,
mmTCP_CHAN_STEER_HI, 0xffffffff, 0x7d6cf5e4, mmVGT_RESET_DEBUG, 0x00000004, 0x00000004,
mmTCP_CHAN_STEER_LO, 0xffffffff, 0x3928b1a0,
}; };
static const u32 fiji_mgcg_cgcg_init[] = static const u32 fiji_mgcg_cgcg_init[] =
{ {
mmRLC_CGTT_MGCG_OVERRIDE, 0xffffffff, 0xffffffc0, mmRLC_CGTT_MGCG_OVERRIDE, 0xffffffff, 0xffffffff,
mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000, mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
mmCB_CGTT_SCLK_CTRL, 0xffffffff, 0x00000100, mmCB_CGTT_SCLK_CTRL, 0xffffffff, 0x00000100,
mmCGTT_BCI_CLK_CTRL, 0xffffffff, 0x00000100, mmCGTT_BCI_CLK_CTRL, 0xffffffff, 0x00000100,
mmCGTT_CP_CLK_CTRL, 0xffffffff, 0x00000100, mmCGTT_CP_CLK_CTRL, 0xffffffff, 0x00000100,
mmCGTT_CPC_CLK_CTRL, 0xffffffff, 0x00000100, mmCGTT_CPC_CLK_CTRL, 0xffffffff, 0x00000100,
mmCGTT_CPF_CLK_CTRL, 0xffffffff, 0x40000100, mmCGTT_CPF_CLK_CTRL, 0xffffffff, 0x40000100,
mmCGTT_DRM_CLK_CTRL0, 0xffffffff, 0x00600100,
mmCGTT_GDS_CLK_CTRL, 0xffffffff, 0x00000100, mmCGTT_GDS_CLK_CTRL, 0xffffffff, 0x00000100,
mmCGTT_IA_CLK_CTRL, 0xffffffff, 0x06000100, mmCGTT_IA_CLK_CTRL, 0xffffffff, 0x06000100,
mmCGTT_PA_CLK_CTRL, 0xffffffff, 0x00000100, mmCGTT_PA_CLK_CTRL, 0xffffffff, 0x00000100,
...@@ -292,6 +296,10 @@ static const u32 fiji_mgcg_cgcg_init[] = ...@@ -292,6 +296,10 @@ static const u32 fiji_mgcg_cgcg_init[] =
mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96e00200, mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96e00200,
mmCP_RB_WPTR_POLL_CNTL, 0xffffffff, 0x00900100, mmCP_RB_WPTR_POLL_CNTL, 0xffffffff, 0x00900100,
mmRLC_CGCG_CGLS_CTRL, 0xffffffff, 0x0020003c, 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, mmCP_MEM_SLP_CNTL, 0x00000001, 0x00000001,
}; };
...@@ -1031,6 +1039,8 @@ static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev) ...@@ -1031,6 +1039,8 @@ static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
case 0x84: case 0x84:
case 0xc8: case 0xc8:
case 0xcc: case 0xcc:
case 0xe1:
case 0xe3:
/* B10 */ /* B10 */
adev->gfx.config.max_cu_per_sh = 8; adev->gfx.config.max_cu_per_sh = 8;
break; break;
...@@ -1039,18 +1049,23 @@ static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev) ...@@ -1039,18 +1049,23 @@ static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
case 0x85: case 0x85:
case 0xc9: case 0xc9:
case 0xcd: case 0xcd:
case 0xe2:
case 0xe4:
/* B8 */ /* B8 */
adev->gfx.config.max_cu_per_sh = 6; adev->gfx.config.max_cu_per_sh = 6;
break; break;
case 0xc6: case 0xc6:
case 0xca: case 0xca:
case 0xce: case 0xce:
case 0x88:
/* B6 */ /* B6 */
adev->gfx.config.max_cu_per_sh = 6; adev->gfx.config.max_cu_per_sh = 6;
break; break;
case 0xc7: case 0xc7:
case 0x87: case 0x87:
case 0xcb: case 0xcb:
case 0xe5:
case 0x89:
default: default:
/* B4 */ /* B4 */
adev->gfx.config.max_cu_per_sh = 4; adev->gfx.config.max_cu_per_sh = 4;
......
...@@ -965,7 +965,7 @@ static int gmc_v7_0_sw_fini(void *handle) ...@@ -965,7 +965,7 @@ static int gmc_v7_0_sw_fini(void *handle)
if (adev->vm_manager.enabled) { if (adev->vm_manager.enabled) {
for (i = 0; i < AMDGPU_NUM_VM; ++i) for (i = 0; i < AMDGPU_NUM_VM; ++i)
amdgpu_fence_unref(&adev->vm_manager.active[i]); fence_put(adev->vm_manager.active[i]);
gmc_v7_0_vm_fini(adev); gmc_v7_0_vm_fini(adev);
adev->vm_manager.enabled = false; adev->vm_manager.enabled = false;
} }
...@@ -1015,7 +1015,7 @@ static int gmc_v7_0_suspend(void *handle) ...@@ -1015,7 +1015,7 @@ static int gmc_v7_0_suspend(void *handle)
if (adev->vm_manager.enabled) { if (adev->vm_manager.enabled) {
for (i = 0; i < AMDGPU_NUM_VM; ++i) for (i = 0; i < AMDGPU_NUM_VM; ++i)
amdgpu_fence_unref(&adev->vm_manager.active[i]); fence_put(adev->vm_manager.active[i]);
gmc_v7_0_vm_fini(adev); gmc_v7_0_vm_fini(adev);
adev->vm_manager.enabled = false; adev->vm_manager.enabled = false;
} }
......
...@@ -984,7 +984,7 @@ static int gmc_v8_0_sw_fini(void *handle) ...@@ -984,7 +984,7 @@ static int gmc_v8_0_sw_fini(void *handle)
if (adev->vm_manager.enabled) { if (adev->vm_manager.enabled) {
for (i = 0; i < AMDGPU_NUM_VM; ++i) for (i = 0; i < AMDGPU_NUM_VM; ++i)
amdgpu_fence_unref(&adev->vm_manager.active[i]); fence_put(adev->vm_manager.active[i]);
gmc_v8_0_vm_fini(adev); gmc_v8_0_vm_fini(adev);
adev->vm_manager.enabled = false; adev->vm_manager.enabled = false;
} }
...@@ -1036,7 +1036,7 @@ static int gmc_v8_0_suspend(void *handle) ...@@ -1036,7 +1036,7 @@ static int gmc_v8_0_suspend(void *handle)
if (adev->vm_manager.enabled) { if (adev->vm_manager.enabled) {
for (i = 0; i < AMDGPU_NUM_VM; ++i) for (i = 0; i < AMDGPU_NUM_VM; ++i)
amdgpu_fence_unref(&adev->vm_manager.active[i]); fence_put(adev->vm_manager.active[i]);
gmc_v8_0_vm_fini(adev); gmc_v8_0_vm_fini(adev);
adev->vm_manager.enabled = false; adev->vm_manager.enabled = false;
} }
......
...@@ -1413,17 +1413,18 @@ static int vi_common_early_init(void *handle) ...@@ -1413,17 +1413,18 @@ static int vi_common_early_init(void *handle)
adev->cg_flags = 0; adev->cg_flags = 0;
adev->pg_flags = 0; adev->pg_flags = 0;
adev->external_rev_id = 0x1; adev->external_rev_id = 0x1;
if (amdgpu_smc_load_fw && smc_enabled)
adev->firmware.smu_load = true;
break; break;
case CHIP_FIJI: case CHIP_FIJI:
adev->has_uvd = true;
adev->cg_flags = 0;
adev->pg_flags = 0;
adev->external_rev_id = adev->rev_id + 0x3c;
break;
case CHIP_TONGA: case CHIP_TONGA:
adev->has_uvd = true; adev->has_uvd = true;
adev->cg_flags = 0; adev->cg_flags = 0;
adev->pg_flags = 0; adev->pg_flags = 0;
adev->external_rev_id = adev->rev_id + 0x14; adev->external_rev_id = adev->rev_id + 0x14;
if (amdgpu_smc_load_fw && smc_enabled)
adev->firmware.smu_load = true;
break; break;
case CHIP_CARRIZO: case CHIP_CARRIZO:
case CHIP_STONEY: case CHIP_STONEY:
...@@ -1432,14 +1433,15 @@ static int vi_common_early_init(void *handle) ...@@ -1432,14 +1433,15 @@ static int vi_common_early_init(void *handle)
/* Disable UVD pg */ /* Disable UVD pg */
adev->pg_flags = /* AMDGPU_PG_SUPPORT_UVD | */AMDGPU_PG_SUPPORT_VCE; adev->pg_flags = /* AMDGPU_PG_SUPPORT_UVD | */AMDGPU_PG_SUPPORT_VCE;
adev->external_rev_id = adev->rev_id + 0x1; adev->external_rev_id = adev->rev_id + 0x1;
if (amdgpu_smc_load_fw && smc_enabled)
adev->firmware.smu_load = true;
break; break;
default: default:
/* FIXME: not supported yet */ /* FIXME: not supported yet */
return -EINVAL; return -EINVAL;
} }
if (amdgpu_smc_load_fw && smc_enabled)
adev->firmware.smu_load = true;
return 0; return 0;
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
...@@ -222,6 +222,12 @@ amd_sched_entity_pop_job(struct amd_sched_entity *entity) ...@@ -222,6 +222,12 @@ amd_sched_entity_pop_job(struct amd_sched_entity *entity)
while ((entity->dependency = sched->ops->dependency(sched_job))) { while ((entity->dependency = sched->ops->dependency(sched_job))) {
if (entity->dependency->context == entity->fence_context) {
/* We can ignore fences from ourself */
fence_put(entity->dependency);
continue;
}
if (fence_add_callback(entity->dependency, &entity->cb, if (fence_add_callback(entity->dependency, &entity->cb,
amd_sched_entity_wakeup)) amd_sched_entity_wakeup))
fence_put(entity->dependency); fence_put(entity->dependency);
...@@ -332,7 +338,7 @@ static void amd_sched_process_job(struct fence *f, struct fence_cb *cb) ...@@ -332,7 +338,7 @@ static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
atomic_dec(&sched->hw_rq_count); atomic_dec(&sched->hw_rq_count);
amd_sched_fence_signal(s_fence); amd_sched_fence_signal(s_fence);
if (sched->timeout != MAX_SCHEDULE_TIMEOUT) { if (sched->timeout != MAX_SCHEDULE_TIMEOUT) {
cancel_delayed_work_sync(&s_fence->dwork); cancel_delayed_work(&s_fence->dwork);
spin_lock_irqsave(&sched->fence_list_lock, flags); spin_lock_irqsave(&sched->fence_list_lock, flags);
list_del_init(&s_fence->list); list_del_init(&s_fence->list);
spin_unlock_irqrestore(&sched->fence_list_lock, flags); spin_unlock_irqrestore(&sched->fence_list_lock, flags);
...@@ -462,5 +468,6 @@ int amd_sched_init(struct amd_gpu_scheduler *sched, ...@@ -462,5 +468,6 @@ int amd_sched_init(struct amd_gpu_scheduler *sched,
*/ */
void amd_sched_fini(struct amd_gpu_scheduler *sched) void amd_sched_fini(struct amd_gpu_scheduler *sched)
{ {
kthread_stop(sched->thread); if (sched->thread)
kthread_stop(sched->thread);
} }
...@@ -1404,44 +1404,20 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) ...@@ -1404,44 +1404,20 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
* @crtc_id: crtc to cleanup pageflip on * @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address) * @crtc_base: new address of the crtc (GPU MC address)
* *
* Does the actual pageflip (evergreen+). * Triggers the actual pageflip by updating the primary
* During vblank we take the crtc lock and wait for the update_pending * surface base address (evergreen+).
* bit to go high, when it does, we release the lock, and allow the
* double buffered update to take place.
* Returns the current update pending status.
*/ */
void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
{ {
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset);
int i;
/* Lock the graphics update lock */
tmp |= EVERGREEN_GRPH_UPDATE_LOCK;
WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
/* update the scanout addresses */ /* update the scanout addresses */
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(crtc_base));
WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
(u32)crtc_base);
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(crtc_base)); upper_32_bits(crtc_base));
WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
(u32)crtc_base); (u32)crtc_base);
/* post the write */
/* Wait for update_pending to go high. */ RREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset);
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)
break;
udelay(1);
}
DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
/* Unlock the lock, so double-buffering can take place inside vblank */
tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
} }
/** /**
......
...@@ -279,6 +279,22 @@ fence_is_signaled(struct fence *fence) ...@@ -279,6 +279,22 @@ fence_is_signaled(struct fence *fence)
return false; return false;
} }
/**
* fence_is_later - return if f1 is chronologically later than f2
* @f1: [in] the first fence from the same context
* @f2: [in] the second fence from the same context
*
* Returns true if f1 is chronologically later than f2. Both fences must be
* from the same context, since a seqno is not re-used across contexts.
*/
static inline bool fence_is_later(struct fence *f1, struct fence *f2)
{
if (WARN_ON(f1->context != f2->context))
return false;
return f1->seqno - f2->seqno < INT_MAX;
}
/** /**
* fence_later - return the chronologically later fence * fence_later - return the chronologically later fence
* @f1: [in] the first fence from the same context * @f1: [in] the first fence from the same context
...@@ -298,14 +314,15 @@ static inline struct fence *fence_later(struct fence *f1, struct fence *f2) ...@@ -298,14 +314,15 @@ static inline struct fence *fence_later(struct fence *f1, struct fence *f2)
* set if enable_signaling wasn't called, and enabling that here is * set if enable_signaling wasn't called, and enabling that here is
* overkill. * overkill.
*/ */
if (f2->seqno - f1->seqno <= INT_MAX) if (fence_is_later(f1, f2))
return fence_is_signaled(f2) ? NULL : f2;
else
return fence_is_signaled(f1) ? NULL : f1; return fence_is_signaled(f1) ? NULL : f1;
else
return fence_is_signaled(f2) ? NULL : f2;
} }
signed long fence_wait_timeout(struct fence *, bool intr, signed long timeout); signed long fence_wait_timeout(struct fence *, bool intr, signed long timeout);
signed long fence_wait_any_timeout(struct fence **fences, uint32_t count,
bool intr, signed long timeout);
/** /**
* fence_wait - sleep until the fence gets signaled * fence_wait - sleep until the fence gets signaled
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment