Skip to content

Commit

Permalink
Merge branch 'drm-next-4.3' of git://people.freedesktop.org/~agd5f/li…
Browse files Browse the repository at this point in the history
…nux into drm-next

More fixes for radeon and amdgpu for 4.3:
- Send full DP aux address fixes for radeon and amdgpu
- Fix an HDMI display regression for pre-DCE5 parts
- UVD suspend fixes for amdgpu
- Add an rs480 suspend quirk
- Fix bo reserve handling in amdgpu GEM_OP ioctl
- GPU scheduler fixes
- SDMA optimizations
- MEC fix for Fiji

* 'drm-next-4.3' of git://people.freedesktop.org/~agd5f/linux: (21 commits)
  drm/amdgpu: set MEC doorbell range for Fiji
  drm/amdgpu: implement burst NOP for SDMA
  drm/amdgpu: add insert_nop ring func and default implementation
  drm/amdgpu: add amdgpu_get_sdma_instance helper function
  drm/amdgpu: add AMDGPU_MAX_SDMA_INSTANCES
  drm/amdgpu: add burst_nop flag for sdma
  drm/amdgpu: add count field for the SDMA NOP packet v2
  drm/amdgpu: use PT for VM sync on unmap
  drm/amdgpu: make wait_event uninterruptible in push_job
  drm/amdgpu: fix amdgpu_bo_unreserve order in GEM_OP IOCTL v2
  drm/amdgpu: partially revert "modify amdgpu_fence_wait_any() to amdgpu_fence_wait_multiple()" v2
  Add radeon suspend/resume quirk for HP Compaq dc5750.
  drm/amdgpu: re-work sync_resv
  drm/amdgpu/atom: Send out the full AUX address
  drm/radeon/native: Send out the full AUX address
  drm/radeon/atom: Send out the full AUX address
  drm/amdgpu: use IB for fill_buffer instead of direct command
  drm/amdgpu: stop trying to suspend UVD sessions v2
  drm/amdgpu: add scheduler dependency callback v2
  drm/amdgpu: let the scheduler work more with jobs v2
  ...
  • Loading branch information
Dave Airlie committed Sep 4, 2015
2 parents 879a37d + bddf802 commit 9949558
Show file tree
Hide file tree
Showing 29 changed files with 360 additions and 164 deletions.
41 changes: 31 additions & 10 deletions drivers/gpu/drm/amd/amdgpu/amdgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ extern int amdgpu_sched_hw_submission;
#define AMDGPU_MAX_COMPUTE_RINGS 8
#define AMDGPU_MAX_VCE_RINGS 2

/* max number of IP instances */
#define AMDGPU_MAX_SDMA_INSTANCES 2

/* number of hw syncs before falling back on blocking */
#define AMDGPU_NUM_SYNCS 4

Expand Down Expand Up @@ -262,7 +265,7 @@ struct amdgpu_buffer_funcs {
unsigned fill_num_dw;

/* used for buffer clearing */
void (*emit_fill_buffer)(struct amdgpu_ring *ring,
void (*emit_fill_buffer)(struct amdgpu_ib *ib,
/* value to write to memory */
uint32_t src_data,
/* dst addr in bytes */
Expand Down Expand Up @@ -340,6 +343,8 @@ struct amdgpu_ring_funcs {
int (*test_ring)(struct amdgpu_ring *ring);
int (*test_ib)(struct amdgpu_ring *ring);
bool (*is_lockup)(struct amdgpu_ring *ring);
/* insert NOP packets */
void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
};

/*
Expand Down Expand Up @@ -440,12 +445,11 @@ int amdgpu_fence_wait_next(struct amdgpu_ring *ring);
int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);

signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
struct fence **array,
uint32_t count,
bool wait_all,
bool intr,
signed long t);
signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
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);

Expand Down Expand Up @@ -717,6 +721,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
void *owner);
int amdgpu_sync_rings(struct amdgpu_sync *sync,
struct amdgpu_ring *ring);
struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
int amdgpu_sync_wait(struct amdgpu_sync *sync);
void amdgpu_sync_free(struct amdgpu_device *adev, struct amdgpu_sync *sync,
struct fence *fence);
Expand Down Expand Up @@ -1214,6 +1219,7 @@ int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
void amdgpu_ring_free_size(struct amdgpu_ring *ring);
int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
int amdgpu_ring_lock(struct amdgpu_ring *ring, unsigned ndw);
void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
void amdgpu_ring_commit(struct amdgpu_ring *ring);
void amdgpu_ring_unlock_commit(struct amdgpu_ring *ring);
void amdgpu_ring_undo(struct amdgpu_ring *ring);
Expand Down Expand Up @@ -1665,7 +1671,6 @@ struct amdgpu_uvd {
struct amdgpu_bo *vcpu_bo;
void *cpu_addr;
uint64_t gpu_addr;
void *saved_bo;
atomic_t handles[AMDGPU_MAX_UVD_HANDLES];
struct drm_file *filp[AMDGPU_MAX_UVD_HANDLES];
struct delayed_work idle_work;
Expand Down Expand Up @@ -1709,6 +1714,7 @@ struct amdgpu_sdma {
uint32_t feature_version;

struct amdgpu_ring ring;
bool burst_nop;
};

/*
Expand Down Expand Up @@ -2057,7 +2063,7 @@ struct amdgpu_device {
struct amdgpu_gfx gfx;

/* sdma */
struct amdgpu_sdma sdma[2];
struct amdgpu_sdma sdma[AMDGPU_MAX_SDMA_INSTANCES];
struct amdgpu_irq_src sdma_trap_irq;
struct amdgpu_irq_src sdma_illegal_inst_irq;

Expand Down Expand Up @@ -2196,6 +2202,21 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v)
ring->ring_free_dw--;
}

static inline struct amdgpu_sdma * amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
int i;

for (i = 0; i < AMDGPU_MAX_SDMA_INSTANCES; i++)
if (&adev->sdma[i].ring == ring)
break;

if (i < AMDGPU_MAX_SDMA_INSTANCES)
return &adev->sdma[i];
else
return NULL;
}

/*
* ASICs macro.
*/
Expand Down Expand Up @@ -2248,7 +2269,7 @@ static inline void amdgpu_ring_write(struct amdgpu_ring *ring, uint32_t v)
#define amdgpu_display_stop_mc_access(adev, s) (adev)->mode_info.funcs->stop_mc_access((adev), (s))
#define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s))
#define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b))
#define amdgpu_emit_fill_buffer(adev, r, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((r), (s), (d), (b))
#define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b))
#define amdgpu_dpm_get_temperature(adev) (adev)->pm.funcs->get_temperature((adev))
#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev))
#define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev))
Expand Down
44 changes: 9 additions & 35 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,22 +851,6 @@ static bool amdgpu_test_signaled_any(struct fence **fences, uint32_t count)
return false;
}

static bool amdgpu_test_signaled_all(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 false;
}
}

return true;
}

struct amdgpu_wait_cb {
struct fence_cb base;
struct task_struct *task;
Expand All @@ -885,7 +869,7 @@ static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
struct amdgpu_fence *fence = to_amdgpu_fence(f);
struct amdgpu_device *adev = fence->ring->adev;

return amdgpu_fence_wait_multiple(adev, &f, 1, false, intr, t);
return amdgpu_fence_wait_any(adev, &f, 1, intr, t);
}

/**
Expand All @@ -894,23 +878,18 @@ static signed long amdgpu_fence_default_wait(struct fence *f, bool intr,
* @adev: amdgpu device
* @array: the fence array with amdgpu fence pointer
* @count: the number of the fence array
* @wait_all: the flag of wait all(true) or wait any(false)
* @intr: when sleep, set the current task interruptable or not
* @t: timeout to wait
*
* If wait_all is true, it will return when all fences are signaled or timeout.
* If wait_all is false, it will return when any fence is signaled or timeout.
* It will return when any fence is signaled or timeout.
*/
signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
struct fence **array,
uint32_t count,
bool wait_all,
bool intr,
signed long t)
{
long idx = 0;
signed long amdgpu_fence_wait_any(struct amdgpu_device *adev,
struct fence **array, uint32_t count,
bool intr, signed long t)
{
struct amdgpu_wait_cb *cb;
struct fence *fence;
unsigned idx;

BUG_ON(!array);

Expand All @@ -927,10 +906,7 @@ signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
if (fence_add_callback(fence,
&cb[idx].base, amdgpu_fence_wait_cb)) {
/* The fence is already signaled */
if (wait_all)
continue;
else
goto fence_rm_cb;
goto fence_rm_cb;
}
}
}
Expand All @@ -945,9 +921,7 @@ signed long amdgpu_fence_wait_multiple(struct amdgpu_device *adev,
* amdgpu_test_signaled_any must be called after
* set_current_state to prevent a race with wake_up_process
*/
if (!wait_all && amdgpu_test_signaled_any(array, count))
break;
if (wait_all && amdgpu_test_signaled_all(array, count))
if (amdgpu_test_signaled_any(array, count))
break;

if (adev->needs_reset) {
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,24 +615,27 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
info.alignment = robj->tbo.mem.page_alignment << PAGE_SHIFT;
info.domains = robj->initial_domain;
info.domain_flags = robj->flags;
amdgpu_bo_unreserve(robj);
if (copy_to_user(out, &info, sizeof(info)))
r = -EFAULT;
break;
}
case AMDGPU_GEM_OP_SET_PLACEMENT:
if (amdgpu_ttm_tt_has_userptr(robj->tbo.ttm)) {
r = -EPERM;
amdgpu_bo_unreserve(robj);
break;
}
robj->initial_domain = args->value & (AMDGPU_GEM_DOMAIN_VRAM |
AMDGPU_GEM_DOMAIN_GTT |
AMDGPU_GEM_DOMAIN_CPU);
amdgpu_bo_unreserve(robj);
break;
default:
amdgpu_bo_unreserve(robj);
r = -EINVAL;
}

amdgpu_bo_unreserve(robj);
out:
drm_gem_object_unreference_unlocked(gobj);
return r;
Expand Down
24 changes: 21 additions & 3 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ int amdgpu_ring_lock(struct amdgpu_ring *ring, unsigned ndw)
return 0;
}

/** amdgpu_ring_insert_nop - insert NOP packets
*
* @ring: amdgpu_ring structure holding ring information
* @count: the number of NOP packets to insert
*
* This is the generic insert_nop function for rings except SDMA
*/
void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
{
int i;

for (i = 0; i < count; i++)
amdgpu_ring_write(ring, ring->nop);
}

/**
* amdgpu_ring_commit - tell the GPU to execute the new
* commands on the ring buffer
Expand All @@ -143,10 +158,13 @@ int amdgpu_ring_lock(struct amdgpu_ring *ring, unsigned ndw)
*/
void amdgpu_ring_commit(struct amdgpu_ring *ring)
{
uint32_t count;

/* We pad to match fetch size */
while (ring->wptr & ring->align_mask) {
amdgpu_ring_write(ring, ring->nop);
}
count = ring->align_mask + 1 - (ring->wptr & ring->align_mask);
count %= ring->align_mask + 1;
ring->funcs->insert_nop(ring, count);

mb();
amdgpu_ring_set_wptr(ring);
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,8 @@ int amdgpu_sa_bo_new(struct amdgpu_device *adev,
} while (amdgpu_sa_bo_next_hole(sa_manager, fences, tries));

spin_unlock(&sa_manager->wq.lock);
t = amdgpu_fence_wait_multiple(adev, fences, AMDGPU_MAX_RINGS, false, false,
MAX_SCHEDULE_TIMEOUT);
t = amdgpu_fence_wait_any(adev, fences, AMDGPU_MAX_RINGS,
false, MAX_SCHEDULE_TIMEOUT);
r = (t > 0) ? 0 : t;
spin_lock(&sa_manager->wq.lock);
/* if we have nothing to wait for block */
Expand Down
7 changes: 7 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
#include <drm/drmP.h>
#include "amdgpu.h"

static struct fence *amdgpu_sched_dependency(struct amd_sched_job *job)
{
struct amdgpu_job *sched_job = (struct amdgpu_job *)job;
return amdgpu_sync_get_fence(&sched_job->ibs->sync);
}

static struct fence *amdgpu_sched_run_job(struct amd_sched_job *job)
{
struct amdgpu_job *sched_job;
Expand Down Expand Up @@ -75,6 +81,7 @@ static void amdgpu_sched_process_job(struct amd_sched_job *job)
}

struct amd_sched_backend_ops amdgpu_sched_ops = {
.dependency = amdgpu_sched_dependency,
.run_job = amdgpu_sched_run_job,
.process_job = amdgpu_sched_process_job
};
Expand Down
46 changes: 40 additions & 6 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
return 0;
}

static void *amdgpu_sync_get_owner(struct fence *f)
{
struct amdgpu_fence *a_fence = to_amdgpu_fence(f);
struct amd_sched_fence *s_fence = to_amd_sched_fence(f);

if (s_fence)
return s_fence->owner;
else if (a_fence)
return a_fence->owner;
return AMDGPU_FENCE_OWNER_UNDEFINED;
}

/**
* amdgpu_sync_resv - use the semaphores to sync to a reservation object
*
Expand All @@ -158,7 +170,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
{
struct reservation_object_list *flist;
struct fence *f;
struct amdgpu_fence *fence;
void *fence_owner;
unsigned i;
int r = 0;

Expand All @@ -176,22 +188,22 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
for (i = 0; i < flist->shared_count; ++i) {
f = rcu_dereference_protected(flist->shared[i],
reservation_object_held(resv));
fence = f ? to_amdgpu_fence(f) : NULL;
if (fence && fence->ring->adev == adev) {
if (amdgpu_sync_same_dev(adev, f)) {
/* VM updates are only interesting
* for other VM updates and moves.
*/
fence_owner = amdgpu_sync_get_owner(f);
if ((owner != AMDGPU_FENCE_OWNER_MOVE) &&
(fence->owner != AMDGPU_FENCE_OWNER_MOVE) &&
(fence_owner != AMDGPU_FENCE_OWNER_MOVE) &&
((owner == AMDGPU_FENCE_OWNER_VM) !=
(fence->owner == AMDGPU_FENCE_OWNER_VM)))
(fence_owner == AMDGPU_FENCE_OWNER_VM)))
continue;

/* Ignore fence from the same owner as
* long as it isn't undefined.
*/
if (owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
fence->owner == owner)
fence_owner == owner)
continue;
}

Expand All @@ -202,6 +214,28 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
return r;
}

struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
{
struct amdgpu_sync_entry *e;
struct hlist_node *tmp;
struct fence *f;
int i;

hash_for_each_safe(sync->fences, i, tmp, e, node) {

f = e->fence;

hash_del(&e->node);
kfree(e);

if (!fence_is_signaled(f))
return f;

fence_put(f);
}
return NULL;
}

int amdgpu_sync_wait(struct amdgpu_sync *sync)
{
struct amdgpu_sync_entry *e;
Expand Down
Loading

0 comments on commit 9949558

Please sign in to comment.