Skip to content

Commit

Permalink
drm/radeon: add si tile mode array query v3
Browse files Browse the repository at this point in the history
Allow userspace to query for the tile mode array so userspace can properly
compute surface pitch and alignment requirement depending on tiling.

v2: Make strict aliasing safer by casting to char when copying
v3: merge fix from Christian

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
  • Loading branch information
Jerome Glisse authored and Alex Deucher committed Apr 11, 2013
1 parent 902aaef commit 64d7b8b
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 81 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/radeon.h
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,7 @@ struct si_asic {
unsigned multi_gpu_tile_size;

unsigned tile_config;
uint32_t tile_mode_array[32];
};

union radeon_asic_config {
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/radeon/radeon_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@
* 2.30.0 - fix for FMASK texturing
* 2.31.0 - Add fastfb support for rs690
* 2.32.0 - new info request for rings working
* 2.33.0 - Add SI tiling mode array query
*/
#define KMS_DRIVER_MAJOR 2
#define KMS_DRIVER_MINOR 32
#define KMS_DRIVER_MINOR 33
#define KMS_DRIVER_PATCHLEVEL 0
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
int radeon_driver_unload_kms(struct drm_device *dev);
Expand Down
174 changes: 94 additions & 80 deletions drivers/gpu/drm/radeon/radeon_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,80 +176,65 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
struct radeon_device *rdev = dev->dev_private;
struct drm_radeon_info *info = data;
struct radeon_mode_info *minfo = &rdev->mode_info;
uint32_t value, *value_ptr;
uint64_t value64, *value_ptr64;
uint32_t *value, value_tmp, *value_ptr, value_size;
uint64_t value64;
struct drm_crtc *crtc;
int i, found;

/* TIMESTAMP is a 64-bit value, needs special handling. */
if (info->request == RADEON_INFO_TIMESTAMP) {
if (rdev->family >= CHIP_R600) {
value_ptr64 = (uint64_t*)((unsigned long)info->value);
value64 = radeon_get_gpu_clock_counter(rdev);

if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) {
DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
return -EFAULT;
}
return 0;
} else {
DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
return -EINVAL;
}
}

value_ptr = (uint32_t *)((unsigned long)info->value);
if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) {
DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
return -EFAULT;
}
value = &value_tmp;
value_size = sizeof(uint32_t);

switch (info->request) {
case RADEON_INFO_DEVICE_ID:
value = dev->pci_device;
*value = dev->pci_device;
break;
case RADEON_INFO_NUM_GB_PIPES:
value = rdev->num_gb_pipes;
*value = rdev->num_gb_pipes;
break;
case RADEON_INFO_NUM_Z_PIPES:
value = rdev->num_z_pipes;
*value = rdev->num_z_pipes;
break;
case RADEON_INFO_ACCEL_WORKING:
/* xf86-video-ati 6.13.0 relies on this being false for evergreen */
if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK))
value = false;
*value = false;
else
value = rdev->accel_working;
*value = rdev->accel_working;
break;
case RADEON_INFO_CRTC_FROM_ID:
if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
return -EFAULT;
}
for (i = 0, found = 0; i < rdev->num_crtc; i++) {
crtc = (struct drm_crtc *)minfo->crtcs[i];
if (crtc && crtc->base.id == value) {
if (crtc && crtc->base.id == *value) {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
value = radeon_crtc->crtc_id;
*value = radeon_crtc->crtc_id;
found = 1;
break;
}
}
if (!found) {
DRM_DEBUG_KMS("unknown crtc id %d\n", value);
DRM_DEBUG_KMS("unknown crtc id %d\n", *value);
return -EINVAL;
}
break;
case RADEON_INFO_ACCEL_WORKING2:
value = rdev->accel_working;
*value = rdev->accel_working;
break;
case RADEON_INFO_TILING_CONFIG:
if (rdev->family >= CHIP_TAHITI)
value = rdev->config.si.tile_config;
*value = rdev->config.si.tile_config;
else if (rdev->family >= CHIP_CAYMAN)
value = rdev->config.cayman.tile_config;
*value = rdev->config.cayman.tile_config;
else if (rdev->family >= CHIP_CEDAR)
value = rdev->config.evergreen.tile_config;
*value = rdev->config.evergreen.tile_config;
else if (rdev->family >= CHIP_RV770)
value = rdev->config.rv770.tile_config;
*value = rdev->config.rv770.tile_config;
else if (rdev->family >= CHIP_R600)
value = rdev->config.r600.tile_config;
*value = rdev->config.r600.tile_config;
else {
DRM_DEBUG_KMS("tiling config is r6xx+ only!\n");
return -EINVAL;
Expand All @@ -262,73 +247,81 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
*
* When returning, the value is 1 if filp owns hyper-z access,
* 0 otherwise. */
if (value >= 2) {
DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value);
if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
return -EFAULT;
}
if (*value >= 2) {
DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", *value);
return -EINVAL;
}
radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value);
radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, value);
break;
case RADEON_INFO_WANT_CMASK:
/* The same logic as Hyper-Z. */
if (value >= 2) {
DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value);
if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
return -EFAULT;
}
if (*value >= 2) {
DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", *value);
return -EINVAL;
}
radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value);
radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, value);
break;
case RADEON_INFO_CLOCK_CRYSTAL_FREQ:
/* return clock value in KHz */
if (rdev->asic->get_xclk)
value = radeon_get_xclk(rdev) * 10;
*value = radeon_get_xclk(rdev) * 10;
else
value = rdev->clock.spll.reference_freq * 10;
*value = rdev->clock.spll.reference_freq * 10;
break;
case RADEON_INFO_NUM_BACKENDS:
if (rdev->family >= CHIP_TAHITI)
value = rdev->config.si.max_backends_per_se *
*value = rdev->config.si.max_backends_per_se *
rdev->config.si.max_shader_engines;
else if (rdev->family >= CHIP_CAYMAN)
value = rdev->config.cayman.max_backends_per_se *
*value = rdev->config.cayman.max_backends_per_se *
rdev->config.cayman.max_shader_engines;
else if (rdev->family >= CHIP_CEDAR)
value = rdev->config.evergreen.max_backends;
*value = rdev->config.evergreen.max_backends;
else if (rdev->family >= CHIP_RV770)
value = rdev->config.rv770.max_backends;
*value = rdev->config.rv770.max_backends;
else if (rdev->family >= CHIP_R600)
value = rdev->config.r600.max_backends;
*value = rdev->config.r600.max_backends;
else {
return -EINVAL;
}
break;
case RADEON_INFO_NUM_TILE_PIPES:
if (rdev->family >= CHIP_TAHITI)
value = rdev->config.si.max_tile_pipes;
*value = rdev->config.si.max_tile_pipes;
else if (rdev->family >= CHIP_CAYMAN)
value = rdev->config.cayman.max_tile_pipes;
*value = rdev->config.cayman.max_tile_pipes;
else if (rdev->family >= CHIP_CEDAR)
value = rdev->config.evergreen.max_tile_pipes;
*value = rdev->config.evergreen.max_tile_pipes;
else if (rdev->family >= CHIP_RV770)
value = rdev->config.rv770.max_tile_pipes;
*value = rdev->config.rv770.max_tile_pipes;
else if (rdev->family >= CHIP_R600)
value = rdev->config.r600.max_tile_pipes;
*value = rdev->config.r600.max_tile_pipes;
else {
return -EINVAL;
}
break;
case RADEON_INFO_FUSION_GART_WORKING:
value = 1;
*value = 1;
break;
case RADEON_INFO_BACKEND_MAP:
if (rdev->family >= CHIP_TAHITI)
value = rdev->config.si.backend_map;
*value = rdev->config.si.backend_map;
else if (rdev->family >= CHIP_CAYMAN)
value = rdev->config.cayman.backend_map;
*value = rdev->config.cayman.backend_map;
else if (rdev->family >= CHIP_CEDAR)
value = rdev->config.evergreen.backend_map;
*value = rdev->config.evergreen.backend_map;
else if (rdev->family >= CHIP_RV770)
value = rdev->config.rv770.backend_map;
*value = rdev->config.rv770.backend_map;
else if (rdev->family >= CHIP_R600)
value = rdev->config.r600.backend_map;
*value = rdev->config.r600.backend_map;
else {
return -EINVAL;
}
Expand All @@ -337,70 +330,91 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
/* this is where we report if vm is supported or not */
if (rdev->family < CHIP_CAYMAN)
return -EINVAL;
value = RADEON_VA_RESERVED_SIZE;
*value = RADEON_VA_RESERVED_SIZE;
break;
case RADEON_INFO_IB_VM_MAX_SIZE:
/* this is where we report if vm is supported or not */
if (rdev->family < CHIP_CAYMAN)
return -EINVAL;
value = RADEON_IB_VM_MAX_SIZE;
*value = RADEON_IB_VM_MAX_SIZE;
break;
case RADEON_INFO_MAX_PIPES:
if (rdev->family >= CHIP_TAHITI)
value = rdev->config.si.max_cu_per_sh;
*value = rdev->config.si.max_cu_per_sh;
else if (rdev->family >= CHIP_CAYMAN)
value = rdev->config.cayman.max_pipes_per_simd;
*value = rdev->config.cayman.max_pipes_per_simd;
else if (rdev->family >= CHIP_CEDAR)
value = rdev->config.evergreen.max_pipes;
*value = rdev->config.evergreen.max_pipes;
else if (rdev->family >= CHIP_RV770)
value = rdev->config.rv770.max_pipes;
*value = rdev->config.rv770.max_pipes;
else if (rdev->family >= CHIP_R600)
value = rdev->config.r600.max_pipes;
*value = rdev->config.r600.max_pipes;
else {
return -EINVAL;
}
break;
case RADEON_INFO_TIMESTAMP:
if (rdev->family < CHIP_R600) {
DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
return -EINVAL;
}
value = (uint32_t*)&value64;
value_size = sizeof(uint64_t);
value64 = radeon_get_gpu_clock_counter(rdev);
break;
case RADEON_INFO_MAX_SE:
if (rdev->family >= CHIP_TAHITI)
value = rdev->config.si.max_shader_engines;
*value = rdev->config.si.max_shader_engines;
else if (rdev->family >= CHIP_CAYMAN)
value = rdev->config.cayman.max_shader_engines;
*value = rdev->config.cayman.max_shader_engines;
else if (rdev->family >= CHIP_CEDAR)
value = rdev->config.evergreen.num_ses;
*value = rdev->config.evergreen.num_ses;
else
value = 1;
*value = 1;
break;
case RADEON_INFO_MAX_SH_PER_SE:
if (rdev->family >= CHIP_TAHITI)
value = rdev->config.si.max_sh_per_se;
*value = rdev->config.si.max_sh_per_se;
else
return -EINVAL;
break;
case RADEON_INFO_FASTFB_WORKING:
value = rdev->fastfb_working;
*value = rdev->fastfb_working;
break;
case RADEON_INFO_RING_WORKING:
switch (value) {
if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
return -EFAULT;
}
switch (*value) {
case RADEON_CS_RING_GFX:
case RADEON_CS_RING_COMPUTE:
value = rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready;
*value = rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready;
break;
case RADEON_CS_RING_DMA:
value = rdev->ring[R600_RING_TYPE_DMA_INDEX].ready;
value |= rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready;
*value = rdev->ring[R600_RING_TYPE_DMA_INDEX].ready;
*value |= rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready;
break;
case RADEON_CS_RING_UVD:
value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
*value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
break;
default:
return -EINVAL;
}
break;
case RADEON_INFO_SI_TILE_MODE_ARRAY:
if (rdev->family < CHIP_TAHITI) {
DRM_DEBUG_KMS("tile mode array is si only!\n");
return -EINVAL;
}
value = rdev->config.si.tile_mode_array;
value_size = sizeof(uint32_t)*32;
break;
default:
DRM_DEBUG_KMS("Invalid request %d\n", info->request);
return -EINVAL;
}
if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) {
if (DRM_COPY_TO_USER(value_ptr, (char*)value, value_size)) {
DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
return -EFAULT;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/si.c
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,7 @@ static void si_tiling_mode_table_init(struct radeon_device *rdev)
gb_tile_moden = 0;
break;
}
rdev->config.si.tile_mode_array[reg_offset] = gb_tile_moden;
WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden);
}
} else if ((rdev->family == CHIP_VERDE) ||
Expand Down Expand Up @@ -1451,6 +1452,7 @@ static void si_tiling_mode_table_init(struct radeon_device *rdev)
gb_tile_moden = 0;
break;
}
rdev->config.si.tile_mode_array[reg_offset] = gb_tile_moden;
WREG32(GB_TILE_MODE0 + (reg_offset * 4), gb_tile_moden);
}
} else
Expand Down
20 changes: 20 additions & 0 deletions include/uapi/drm/radeon_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,8 @@ struct drm_radeon_cs {
#define RADEON_INFO_FASTFB_WORKING 0x14
/* query if a RADEON_CS_RING_* submission is supported */
#define RADEON_INFO_RING_WORKING 0x15
/* SI tile mode array */
#define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16


struct drm_radeon_info {
Expand All @@ -985,4 +987,22 @@ struct drm_radeon_info {
uint64_t value;
};

/* Those correspond to the tile index to use, this is to explicitly state
* the API that is implicitly defined by the tile mode array.
*/
#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8
#define SI_TILE_MODE_COLOR_1D 13
#define SI_TILE_MODE_COLOR_1D_SCANOUT 9
#define SI_TILE_MODE_COLOR_2D_8BPP 14
#define SI_TILE_MODE_COLOR_2D_16BPP 15
#define SI_TILE_MODE_COLOR_2D_32BPP 16
#define SI_TILE_MODE_COLOR_2D_64BPP 17
#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11
#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12
#define SI_TILE_MODE_DEPTH_STENCIL_1D 4
#define SI_TILE_MODE_DEPTH_STENCIL_2D 0
#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3
#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3
#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2

#endif

0 comments on commit 64d7b8b

Please sign in to comment.