radeon_cs: add relocate hook for mm and non-mm relocations
parent
42e373e903
commit
4234f82acc
|
@ -805,10 +805,45 @@ static int radeon_gem_ib_destroy(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int radeon_gem_relocate(struct drm_device *dev, struct drm_file *file_priv,
|
||||
uint32_t *reloc, uint32_t *offset)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
/* relocate the handle */
|
||||
int domains = reloc[2];
|
||||
struct drm_gem_object *obj;
|
||||
int flags = 0;
|
||||
int ret;
|
||||
struct drm_radeon_gem_object *obj_priv;
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, reloc[1]);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
obj_priv = obj->driver_private;
|
||||
if (domains == RADEON_GEM_DOMAIN_VRAM) {
|
||||
flags = DRM_BO_FLAG_MEM_VRAM;
|
||||
} else {
|
||||
flags = DRM_BO_FLAG_MEM_TT;
|
||||
}
|
||||
|
||||
ret = drm_bo_do_validate(obj_priv->bo, flags, DRM_BO_MASK_MEM, 0, 0, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (flags == DRM_BO_FLAG_MEM_VRAM)
|
||||
*offset = obj_priv->bo->offset + dev_priv->fb_location;
|
||||
else
|
||||
*offset = obj_priv->bo->offset + dev_priv->gart_vm_start;
|
||||
|
||||
/* BAD BAD BAD - LINKED LIST THE OBJS and UNREF ONCE IB is SUBMITTED */
|
||||
drm_gem_object_unreference(obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* allocate 1MB of 64k IBs the the kernel can keep mapped */
|
||||
static int radeon_gem_ib_init(struct drm_device *dev)
|
||||
{
|
||||
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
int ret;
|
||||
|
@ -843,6 +878,7 @@ static int radeon_gem_ib_init(struct drm_device *dev)
|
|||
dev_priv->cs.ib_free = radeon_gem_ib_free;
|
||||
|
||||
radeon_cs_init(dev);
|
||||
dev_priv->cs.relocate = radeon_gem_relocate;
|
||||
return 0;
|
||||
|
||||
free_all:
|
||||
|
|
|
@ -74,7 +74,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
|
|||
}
|
||||
|
||||
/* now parse command stream */
|
||||
r = radeon->cs.parse(dev, ib, packets, cs->dwords);
|
||||
r = radeon->cs.parse(dev, fpriv, ib, packets, cs->dwords);
|
||||
if (r) {
|
||||
goto out;
|
||||
}
|
||||
|
@ -88,6 +88,69 @@ out:
|
|||
return r;
|
||||
}
|
||||
|
||||
/* for non-mm */
|
||||
static int radeon_nomm_relocate(struct drm_device *dev, struct drm_file *file_priv, uint32_t *reloc, uint32_t *offset)
|
||||
{
|
||||
*offset = reloc[1];
|
||||
return 0;
|
||||
}
|
||||
#define RELOC_SIZE 2
|
||||
#define RADEON_2D_OFFSET_MASK 0x3fffff
|
||||
|
||||
static __inline__ int radeon_cs_relocate_offset(struct drm_device *dev, struct drm_file *file_priv,
|
||||
uint32_t *packets, uint32_t offset_dw)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t hdr = packets[offset_dw];
|
||||
uint32_t reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2;
|
||||
uint32_t val = packets[offset_dw + 1];
|
||||
uint32_t packet3_hdr = packets[offset_dw+2];
|
||||
uint32_t tmp, offset;
|
||||
int ret;
|
||||
|
||||
/* this is too strict we may want to expand the length in the future and have
|
||||
old kernels ignore it. */
|
||||
if (packet3_hdr != (RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16))) {
|
||||
DRM_ERROR("Packet 3 was %x should have been %x\n", packet3_hdr, RADEON_CP_PACKET3 | RADEON_CP_NOP | (RELOC_SIZE << 16));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch(reg) {
|
||||
case RADEON_DST_PITCH_OFFSET:
|
||||
case RADEON_SRC_PITCH_OFFSET:
|
||||
/* pass in the start of the reloc */
|
||||
ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
tmp = (val & RADEON_2D_OFFSET_MASK) << 10;
|
||||
val &= ~RADEON_2D_OFFSET_MASK;
|
||||
offset += tmp;
|
||||
offset >>= 10;
|
||||
val |= offset;
|
||||
break;
|
||||
case R300_RB3D_COLOROFFSET0:
|
||||
case R300_RB3D_DEPTHOFFSET:
|
||||
case R300_TX_OFFSET_0:
|
||||
case R300_TX_OFFSET_0+4:
|
||||
offset = packets[offset_dw + 3];
|
||||
|
||||
ret = dev_priv->cs.relocate(dev, file_priv, packets + offset_dw + 2, &offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
offset &= 0xffffffe0;
|
||||
val += offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
DRM_ERROR("New offset %x %x %x\n", packets[offset_dw+1], val, offset);
|
||||
packets[offset_dw + 1] = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static __inline__ int radeon_cs_check_offset(struct drm_device *dev,
|
||||
uint32_t reg, uint32_t val)
|
||||
{
|
||||
|
@ -113,11 +176,11 @@ static __inline__ int radeon_cs_check_offset(struct drm_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets,
|
||||
uint32_t offset_dw)
|
||||
int radeon_cs_packet0(struct drm_device *dev, struct drm_file *file_priv,
|
||||
uint32_t *packets, uint32_t offset_dw)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
int hdr = packets[offset_dw];
|
||||
uint32_t hdr = packets[offset_dw];
|
||||
int num_dw = ((hdr & RADEON_CP_PACKET_COUNT_MASK) >> 16) + 2;
|
||||
int need_reloc = 0;
|
||||
int reg = (hdr & R300_CP_PACKET0_REG_MASK) << 2;
|
||||
|
@ -139,9 +202,16 @@ int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets,
|
|||
case 1:
|
||||
flags = r300_get_reg_flags(reg);
|
||||
if (flags == MARK_CHECK_OFFSET) {
|
||||
radeon_cs_check_offset(dev, reg, packets[offset_dw+count_dw]);
|
||||
|
||||
if (num_dw > 2) {
|
||||
DRM_ERROR("Cannot relocate inside type stream of reg0 packets\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = radeon_cs_relocate_offset(dev, file_priv, packets, offset_dw);
|
||||
if (ret)
|
||||
return ret;
|
||||
DRM_DEBUG("need to relocate %x %d\n", reg, flags);
|
||||
/* okay it should be followed by a NOP */
|
||||
} else if (flags == MARK_CHECK_SCISSOR) {
|
||||
DRM_DEBUG("need to validate scissor %x %d\n", reg, flags);
|
||||
} else {
|
||||
|
@ -156,8 +226,8 @@ int radeon_cs_packet0(struct drm_device *dev, uint32_t *packets,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int radeon_cs_parse(struct drm_device *dev, void *ib,
|
||||
uint32_t *packets, uint32_t dwords)
|
||||
int radeon_cs_parse(struct drm_device *dev, struct drm_file *file_priv,
|
||||
void *ib, uint32_t *packets, uint32_t dwords)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
volatile int rb;
|
||||
|
@ -173,7 +243,7 @@ int radeon_cs_parse(struct drm_device *dev, void *ib,
|
|||
|
||||
switch (hdr & RADEON_CP_PACKET_MASK) {
|
||||
case RADEON_CP_PACKET0:
|
||||
ret = radeon_cs_packet0(dev, packets, count_dw);
|
||||
ret = radeon_cs_packet0(dev, file_priv, packets, count_dw);
|
||||
break;
|
||||
case RADEON_CP_PACKET1:
|
||||
case RADEON_CP_PACKET2:
|
||||
|
@ -191,6 +261,7 @@ int radeon_cs_parse(struct drm_device *dev, void *ib,
|
|||
offset = packets[count_dw+2] & ((1 << 22) - 1);
|
||||
offset <<= 10;
|
||||
DRM_ERROR("Offset check for Packet 3 %x %x\n", reg, offset);
|
||||
/* okay it should be followed by a NOP */
|
||||
break;
|
||||
}
|
||||
case RADEON_CNTL_BITBLT_MULTI:
|
||||
|
@ -302,5 +373,6 @@ int radeon_cs_init(struct drm_device *dev)
|
|||
|
||||
dev_priv->cs.parse = radeon_cs_parse;
|
||||
/* ib get depends on memory manager or not so memory manager */
|
||||
dev_priv->cs.relocate = radeon_nomm_relocate;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -293,8 +293,8 @@ struct drm_radeon_cs_priv {
|
|||
uint32_t id_last_wcnt;
|
||||
uint32_t id_last_scnt;
|
||||
|
||||
int (*parse)(struct drm_device *dev, void *ib,
|
||||
uint32_t *packets, uint32_t dwords);
|
||||
int (*parse)(struct drm_device *dev, struct drm_file *file_priv,
|
||||
void *ib, uint32_t *packets, uint32_t dwords);
|
||||
void (*id_emit)(struct drm_device *dev, uint32_t *id);
|
||||
uint32_t (*id_last_get)(struct drm_device *dev);
|
||||
/* this ib handling callback are for hidding memory manager drm
|
||||
|
@ -303,6 +303,9 @@ struct drm_radeon_cs_priv {
|
|||
int (*ib_get)(struct drm_device *dev, void **ib, uint32_t dwords);
|
||||
uint32_t (*ib_get_ptr)(struct drm_device *dev, void *ib);
|
||||
void (*ib_free)(struct drm_device *dev, void *ib, uint32_t dwords);
|
||||
/* do a relocation either MM or non-MM */
|
||||
bool (*relocate)(struct drm_device *dev, struct drm_file *file_priv,
|
||||
uint32_t *reloc, uint32_t *offset);
|
||||
};
|
||||
|
||||
typedef struct drm_radeon_private {
|
||||
|
@ -391,6 +394,7 @@ typedef struct drm_radeon_private {
|
|||
|
||||
int num_gb_pipes;
|
||||
|
||||
int mm_disabled; /* on OSes with no MM this will be 1*/
|
||||
struct radeon_mm_info mm;
|
||||
drm_local_map_t *mmio;
|
||||
|
||||
|
|
Loading…
Reference in New Issue