25,7 → 25,7 |
* Alex Deucher |
* Jerome Glisse |
*/ |
//#include <linux/seq_file.h> |
#include <linux/seq_file.h> |
#include "drmP.h" |
#include "radeon_drm.h" |
#include "radeon_reg.h" |
32,7 → 32,6 |
#include "radeon.h" |
#include "atom.h" |
|
|
int radeon_debugfs_ib_init(struct radeon_device *rdev); |
|
/* |
60,10 → 59,12 |
set_bit(i, rdev->ib_pool.alloc_bm); |
rdev->ib_pool.ibs[i].length_dw = 0; |
*ib = &rdev->ib_pool.ibs[i]; |
mutex_unlock(&rdev->ib_pool.mutex); |
goto out; |
} |
if (list_empty(&rdev->ib_pool.scheduled_ibs)) { |
/* we go do nothings here */ |
mutex_unlock(&rdev->ib_pool.mutex); |
DRM_ERROR("all IB allocated none scheduled.\n"); |
r = -EINVAL; |
goto out; |
73,10 → 74,13 |
struct radeon_ib, list); |
if (nib->fence == NULL) { |
/* we go do nothings here */ |
mutex_unlock(&rdev->ib_pool.mutex); |
DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx); |
r = -EINVAL; |
goto out; |
} |
mutex_unlock(&rdev->ib_pool.mutex); |
|
r = radeon_fence_wait(nib->fence, false); |
if (r) { |
DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx, |
85,12 → 89,17 |
goto out; |
} |
radeon_fence_unref(&nib->fence); |
|
nib->length_dw = 0; |
|
/* scheduled list is accessed here */ |
mutex_lock(&rdev->ib_pool.mutex); |
list_del(&nib->list); |
INIT_LIST_HEAD(&nib->list); |
mutex_unlock(&rdev->ib_pool.mutex); |
|
*ib = nib; |
out: |
mutex_unlock(&rdev->ib_pool.mutex); |
if (r) { |
radeon_fence_unref(&fence); |
} else { |
115,60 → 124,36 |
} |
list_del(&tmp->list); |
INIT_LIST_HEAD(&tmp->list); |
if (tmp->fence) { |
if (tmp->fence) |
radeon_fence_unref(&tmp->fence); |
} |
|
tmp->length_dw = 0; |
clear_bit(tmp->idx, rdev->ib_pool.alloc_bm); |
mutex_unlock(&rdev->ib_pool.mutex); |
} |
|
static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib) |
{ |
while ((ib->length_dw & rdev->cp.align_mask)) { |
ib->ptr[ib->length_dw++] = PACKET2(0); |
} |
} |
|
static void radeon_ib_cpu_flush(struct radeon_device *rdev, |
struct radeon_ib *ib) |
{ |
unsigned long tmp; |
unsigned i; |
|
/* To force CPU cache flush ugly but seems reliable */ |
for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) { |
tmp = readl(&ib->ptr[i]); |
} |
} |
|
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) |
{ |
int r = 0; |
|
mutex_lock(&rdev->ib_pool.mutex); |
radeon_ib_align(rdev, ib); |
radeon_ib_cpu_flush(rdev, ib); |
if (!ib->length_dw || !rdev->cp.ready) { |
/* TODO: Nothings in the ib we should report. */ |
mutex_unlock(&rdev->ib_pool.mutex); |
DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); |
return -EINVAL; |
} |
/* 64 dwords should be enought for fence too */ |
|
/* 64 dwords should be enough for fence too */ |
r = radeon_ring_lock(rdev, 64); |
if (r) { |
DRM_ERROR("radeon: scheduling IB failled (%d).\n", r); |
mutex_unlock(&rdev->ib_pool.mutex); |
return r; |
} |
radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1)); |
radeon_ring_write(rdev, ib->gpu_addr); |
radeon_ring_write(rdev, ib->length_dw); |
radeon_ring_ib_execute(rdev, ib); |
radeon_fence_emit(rdev, ib->fence); |
radeon_ring_unlock_commit(rdev); |
mutex_lock(&rdev->ib_pool.mutex); |
list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs); |
mutex_unlock(&rdev->ib_pool.mutex); |
radeon_ring_unlock_commit(rdev); |
return 0; |
} |
#endif |
180,6 → 165,8 |
int i; |
int r = 0; |
|
if (rdev->ib_pool.robj) |
return 0; |
/* Allocate 1M object buffer */ |
INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs); |
r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, |
223,7 → 210,7 |
if (!rdev->ib_pool.ready) { |
return; |
} |
// mutex_lock(&rdev->ib_pool.mutex); |
mutex_lock(&rdev->ib_pool.mutex); |
bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); |
if (rdev->ib_pool.robj) { |
// radeon_object_kunmap(rdev->ib_pool.robj); |
230,74 → 217,18 |
// radeon_object_unref(&rdev->ib_pool.robj); |
rdev->ib_pool.robj = NULL; |
} |
// mutex_unlock(&rdev->ib_pool.mutex); |
mutex_unlock(&rdev->ib_pool.mutex); |
} |
|
#if 0 |
|
int radeon_ib_test(struct radeon_device *rdev) |
{ |
struct radeon_ib *ib; |
uint32_t scratch; |
uint32_t tmp = 0; |
unsigned i; |
int r; |
|
r = radeon_scratch_get(rdev, &scratch); |
if (r) { |
DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); |
return r; |
} |
WREG32(scratch, 0xCAFEDEAD); |
r = radeon_ib_get(rdev, &ib); |
if (r) { |
return r; |
} |
ib->ptr[0] = PACKET0(scratch, 0); |
ib->ptr[1] = 0xDEADBEEF; |
ib->ptr[2] = PACKET2(0); |
ib->ptr[3] = PACKET2(0); |
ib->ptr[4] = PACKET2(0); |
ib->ptr[5] = PACKET2(0); |
ib->ptr[6] = PACKET2(0); |
ib->ptr[7] = PACKET2(0); |
ib->length_dw = 8; |
r = radeon_ib_schedule(rdev, ib); |
if (r) { |
radeon_scratch_free(rdev, scratch); |
radeon_ib_free(rdev, &ib); |
return r; |
} |
r = radeon_fence_wait(ib->fence, false); |
if (r) { |
return r; |
} |
for (i = 0; i < rdev->usec_timeout; i++) { |
tmp = RREG32(scratch); |
if (tmp == 0xDEADBEEF) { |
break; |
} |
DRM_UDELAY(1); |
} |
if (i < rdev->usec_timeout) { |
DRM_INFO("ib test succeeded in %u usecs\n", i); |
} else { |
DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n", |
scratch, tmp); |
r = -EINVAL; |
} |
radeon_scratch_free(rdev, scratch); |
radeon_ib_free(rdev, &ib); |
return r; |
} |
|
#endif |
|
/* |
* Ring. |
*/ |
void radeon_ring_free_size(struct radeon_device *rdev) |
{ |
if (rdev->family >= CHIP_R600) |
rdev->cp.rptr = RREG32(R600_CP_RB_RPTR); |
else |
rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); |
/* This works because ring_size is a power of 2 */ |
rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4)); |
315,14 → 246,12 |
/* Align requested size with padding so unlock_commit can |
* pad safely */ |
ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask; |
// mutex_lock(&rdev->cp.mutex); |
mutex_lock(&rdev->cp.mutex); |
while (ndw > (rdev->cp.ring_free_dw - 1)) { |
radeon_ring_free_size(rdev); |
if (ndw < rdev->cp.ring_free_dw) { |
break; |
} |
delay(1); |
|
// r = radeon_fence_wait_next(rdev); |
// if (r) { |
// mutex_unlock(&rdev->cp.mutex); |
343,79 → 272,26 |
count_dw_pad = (rdev->cp.align_mask + 1) - |
(rdev->cp.wptr & rdev->cp.align_mask); |
for (i = 0; i < count_dw_pad; i++) { |
radeon_ring_write(rdev, PACKET2(0)); |
radeon_ring_write(rdev, 2 << 30); |
} |
DRM_MEMORYBARRIER(); |
WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr); |
(void)RREG32(RADEON_CP_RB_WPTR); |
// mutex_unlock(&rdev->cp.mutex); |
radeon_cp_commit(rdev); |
mutex_unlock(&rdev->cp.mutex); |
} |
|
void radeon_ring_unlock_undo(struct radeon_device *rdev) |
{ |
rdev->cp.wptr = rdev->cp.wptr_old; |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
} |
|
|
int radeon_ring_test(struct radeon_device *rdev) |
{ |
uint32_t scratch; |
uint32_t tmp = 0; |
unsigned i; |
int r; |
|
dbgprintf("%s\n",__FUNCTION__); |
|
r = radeon_scratch_get(rdev, &scratch); |
if (r) { |
DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r); |
return r; |
} |
WREG32(scratch, 0xCAFEDEAD); |
r = radeon_ring_lock(rdev, 2); |
if (r) { |
DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); |
radeon_scratch_free(rdev, scratch); |
return r; |
} |
radeon_ring_write(rdev, PACKET0(scratch, 0)); |
radeon_ring_write(rdev, 0xDEADBEEF); |
radeon_ring_unlock_commit(rdev); |
for (i = 0; i < 100000; i++) { |
tmp = RREG32(scratch); |
if (tmp == 0xDEADBEEF) { |
break; |
} |
DRM_UDELAY(1); |
} |
if (i < 100000) { |
DRM_INFO("ring test succeeded in %d usecs\n", i); |
} else { |
DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n", |
scratch, tmp); |
r = -EINVAL; |
} |
radeon_scratch_free(rdev, scratch); |
|
dbgprintf("done %s\n",__FUNCTION__); |
return r; |
} |
|
|
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, |
int pages, u32_t *pagelist); |
|
|
|
int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size) |
{ |
int r; |
|
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
|
rdev->cp.ring_size = ring_size; |
|
/* Allocate ring buffer */ |
if (rdev->cp.ring_obj == NULL) { |
r = radeon_object_create(rdev, NULL, rdev->cp.ring_size, |
425,7 → 301,7 |
&rdev->cp.ring_obj); |
if (r) { |
DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r); |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
return r; |
} |
r = radeon_object_pin(rdev->cp.ring_obj, |
433,7 → 309,7 |
&rdev->cp.gpu_addr); |
if (r) { |
DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r); |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
return r; |
} |
r = radeon_object_kmap(rdev->cp.ring_obj, |
440,7 → 316,7 |
(void **)&rdev->cp.ring); |
if (r) { |
DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r); |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
return r; |
} |
} |
461,7 → 337,7 |
rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1; |
rdev->cp.ring_free_dw = rdev->cp.ring_size / 4; |
|
dbgprintf("done %s\n",__FUNCTION__); |
LEAVE(); |
|
return 0; |
} |
468,7 → 344,7 |
|
void radeon_ring_fini(struct radeon_device *rdev) |
{ |
// mutex_lock(&rdev->cp.mutex); |
mutex_lock(&rdev->cp.mutex); |
if (rdev->cp.ring_obj) { |
// radeon_object_kunmap(rdev->cp.ring_obj); |
// radeon_object_unpin(rdev->cp.ring_obj); |
476,7 → 352,7 |
rdev->cp.ring = NULL; |
rdev->cp.ring_obj = NULL; |
} |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
} |
|
|
524,18 → 400,3 |
return 0; |
#endif |
} |
|
|
int drm_order(unsigned long size) |
{ |
int order; |
unsigned long tmp; |
|
for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ; |
|
if (size & (size - 1)) |
++order; |
|
return order; |
} |
|