tu: Gather UBWC config

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26578>
This commit is contained in:
Connor Abbott 2023-11-21 14:17:07 +01:00 committed by Marge Bot
parent 3df6c19a22
commit 66bdb50736
5 changed files with 156 additions and 6 deletions

View file

@ -1311,6 +1311,20 @@ tu_physical_device_init(struct tu_physical_device *device,
device->memory.type_count++;
}
/* Provide fallback UBWC config values if the kernel doesn't support
* providing them. This should match what the kernel programs.
*/
if (!device->ubwc_config.highest_bank_bit) {
device->ubwc_config.highest_bank_bit = info.highest_bank_bit;
}
if (device->ubwc_config.bank_swizzle_levels == ~0) {
device->ubwc_config.bank_swizzle_levels = info.ubwc_swizzle;
}
if (device->ubwc_config.macrotile_mode == FDL_MACROTILE_INVALID) {
device->ubwc_config.macrotile_mode =
(enum fdl_macrotile_mode) info.macrotile_mode;
}
fd_get_driver_uuid(device->driver_uuid);
fd_get_device_uuid(device->device_uuid, &device->dev_id);

View file

@ -124,6 +124,8 @@ struct tu_physical_device
bool has_cached_non_coherent_memory;
uintptr_t level1_dcache_size;
struct fdl_ubwc_config ubwc_config;
bool has_preemption;
struct {

View file

@ -149,6 +149,39 @@ tu_drm_get_priorities(const struct tu_physical_device *dev)
return val;
}
static uint32_t
tu_drm_get_highest_bank_bit(const struct tu_physical_device *dev)
{
uint64_t value;
int ret = tu_drm_get_param(dev->local_fd, MSM_PARAM_HIGHEST_BANK_BIT, &value);
if (ret)
return 0;
return value;
}
static enum fdl_macrotile_mode
tu_drm_get_macrotile_mode(const struct tu_physical_device *dev)
{
uint64_t value;
int ret = tu_drm_get_param(dev->local_fd, MSM_PARAM_MACROTILE_MODE, &value);
if (ret)
return FDL_MACROTILE_INVALID;
return (enum fdl_macrotile_mode) value;
}
static uint32_t
tu_drm_get_ubwc_swizzle(const struct tu_physical_device *dev)
{
uint64_t value;
int ret = tu_drm_get_param(dev->local_fd, MSM_PARAM_UBWC_SWIZZLE, &value);
if (ret)
return ~0;
return value;
}
static bool
tu_drm_is_memory_type_supported(int fd, uint32_t flags)
{
@ -1274,6 +1307,10 @@ tu_knl_drm_msm_load(struct tu_instance *instance,
device->submitqueue_priority_count = tu_drm_get_priorities(device);
device->ubwc_config.highest_bank_bit = tu_drm_get_highest_bank_bit(device);
device->ubwc_config.bank_swizzle_levels = tu_drm_get_ubwc_swizzle(device);
device->ubwc_config.macrotile_mode = tu_drm_get_macrotile_mode(device);
device->syncobj_type = vk_drm_syncobj_get_type(fd);
/* we don't support DRM_CAP_SYNCOBJ_TIMELINE, but drm-shim does */
if (!(device->syncobj_type.features & VK_SYNC_FEATURE_TIMELINE))

View file

@ -87,7 +87,7 @@ struct tu_virtio_device {
struct u_vector zombie_vmas_stage_2;
};
static int tu_drm_get_param(struct tu_device *dev, uint32_t param, uint64_t *value);
static int tu_drm_get_param(struct vdrm_device *vdrm, uint32_t param, uint64_t *value);
/**
* Helper for simple pass-thru ioctls
@ -149,7 +149,7 @@ query_faults(struct tu_device *dev, uint64_t *value)
if (vdrm_shmem_has_field(vdev->shmem, global_faults)) {
global_faults = vdev->shmem->global_faults;
} else {
int ret = tu_drm_get_param(dev, MSM_PARAM_FAULTS, &global_faults);
int ret = tu_drm_get_param(vdev->vdrm, MSM_PARAM_FAULTS, &global_faults);
if (ret)
return ret;
}
@ -256,7 +256,7 @@ virtio_device_finish(struct tu_device *dev)
}
static int
tu_drm_get_param(struct tu_device *dev, uint32_t param, uint64_t *value)
tu_drm_get_param(struct vdrm_device *vdrm, uint32_t param, uint64_t *value)
{
/* Technically this requires a pipe, but the kernel only supports one pipe
* anyway at the time of writing and most of these are clearly pipe
@ -266,7 +266,7 @@ tu_drm_get_param(struct tu_device *dev, uint32_t param, uint64_t *value)
.param = param,
};
int ret = virtio_simple_ioctl(dev->vdev->vdrm, DRM_IOCTL_MSM_GET_PARAM, &req);
int ret = virtio_simple_ioctl(vdrm, DRM_IOCTL_MSM_GET_PARAM, &req);
if (ret)
return ret;
@ -275,16 +275,49 @@ tu_drm_get_param(struct tu_device *dev, uint32_t param, uint64_t *value)
return 0;
}
static uint32_t
tu_drm_get_highest_bank_bit(struct vdrm_device *vdrm)
{
uint64_t value;
int ret = tu_drm_get_param(vdrm, MSM_PARAM_HIGHEST_BANK_BIT, &value);
if (ret)
return 0;
return value;
}
static enum fdl_macrotile_mode
tu_drm_get_macrotile_mode(struct vdrm_device *vdrm)
{
uint64_t value;
int ret = tu_drm_get_param(vdrm, MSM_PARAM_MACROTILE_MODE, &value);
if (ret)
return FDL_MACROTILE_INVALID;
return (enum fdl_macrotile_mode) value;
}
static uint32_t
tu_drm_get_ubwc_swizzle(struct vdrm_device *vdrm)
{
uint64_t value;
int ret = tu_drm_get_param(vdrm, MSM_PARAM_UBWC_SWIZZLE, &value);
if (ret)
return ~0;
return value;
}
static int
virtio_device_get_gpu_timestamp(struct tu_device *dev, uint64_t *ts)
{
return tu_drm_get_param(dev, MSM_PARAM_TIMESTAMP, ts);
return tu_drm_get_param(dev->vdev->vdrm, MSM_PARAM_TIMESTAMP, ts);
}
static int
virtio_device_get_suspend_count(struct tu_device *dev, uint64_t *suspend_count)
{
int ret = tu_drm_get_param(dev, MSM_PARAM_SUSPENDS, suspend_count);
int ret = tu_drm_get_param(dev->vdev->vdrm, MSM_PARAM_SUSPENDS, suspend_count);
return ret;
}
@ -1335,6 +1368,15 @@ tu_knl_drm_virtio_load(struct tu_instance *instance,
*/
bool has_preemption = virtio_has_preemption(vdrm);
/* If virglrenderer is too old, we may need another round-trip to get this.
*/
if (caps.u.msm.highest_bank_bit == 0)
caps.u.msm.highest_bank_bit = tu_drm_get_highest_bank_bit(vdrm);
/* TODO add these to the caps struct */
uint32_t bank_swizzle_levels = tu_drm_get_ubwc_swizzle(vdrm);
enum fdl_macrotile_mode macrotile_mode = tu_drm_get_macrotile_mode(vdrm);
vdrm_device_close(vdrm);
mesa_logd("wire_format_version: %u", caps.wire_format_version);
@ -1349,6 +1391,7 @@ tu_knl_drm_virtio_load(struct tu_instance *instance,
mesa_logd("gmem_base: 0x%0" PRIx64, caps.u.msm.gmem_base);
mesa_logd("chip_id: 0x%0" PRIx64, caps.u.msm.chip_id);
mesa_logd("max_freq: %u", caps.u.msm.max_freq);
mesa_logd("highest_bank_bit: %u", caps.u.msm.highest_bank_bit);
if (caps.wire_format_version != 2) {
return vk_startup_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
@ -1389,9 +1432,13 @@ tu_knl_drm_virtio_load(struct tu_instance *instance,
device->gmem_base = caps.u.msm.gmem_base;
device->va_start = caps.u.msm.va_start;
device->va_size = caps.u.msm.va_size;
device->ubwc_config.highest_bank_bit = caps.u.msm.highest_bank_bit;
device->has_set_iova = true;
device->has_preemption = has_preemption;
device->ubwc_config.bank_swizzle_levels = bank_swizzle_levels;
device->ubwc_config.macrotile_mode = macrotile_mode;
device->gmem_size = debug_get_num_option("TU_GMEM", device->gmem_size);
device->has_cached_coherent_memory = caps.u.msm.has_cached_coherent;

View file

@ -1561,6 +1561,17 @@ tu_knl_kgsl_load(struct tu_instance *instance, int fd)
if (get_kgsl_prop(fd, KGSL_PROP_UCHE_GMEM_VADDR, &gmem_iova, sizeof(gmem_iova)))
goto fail;
uint32_t highest_bank_bit;
if (get_kgsl_prop(fd, KGSL_PROP_HIGHEST_BANK_BIT, &highest_bank_bit,
sizeof(highest_bank_bit)))
goto fail;
uint32_t ubwc_version;
if (get_kgsl_prop(fd, KGSL_PROP_UBWC_MODE, &ubwc_version,
sizeof(ubwc_version)))
goto fail;
/* kgsl version check? */
device->instance = instance;
@ -1599,6 +1610,45 @@ tu_knl_kgsl_load(struct tu_instance *instance, int fd)
/* preemption is always supported on kgsl */
device->has_preemption = true;
device->ubwc_config.highest_bank_bit = highest_bank_bit;
/* The other config values can be partially inferred from the UBWC version,
* but kgsl also hardcodes overrides for specific a6xx versions that we
* have to follow here. Yuck.
*/
switch (ubwc_version) {
case KGSL_UBWC_1_0:
device->ubwc_config.bank_swizzle_levels = 0x7;
device->ubwc_config.macrotile_mode = FDL_MACROTILE_4_CHANNEL;
break;
case KGSL_UBWC_2_0:
device->ubwc_config.bank_swizzle_levels = 0x6;
device->ubwc_config.macrotile_mode = FDL_MACROTILE_4_CHANNEL;
break;
case KGSL_UBWC_3_0:
device->ubwc_config.bank_swizzle_levels = 0x6;
device->ubwc_config.macrotile_mode = FDL_MACROTILE_4_CHANNEL;
break;
case KGSL_UBWC_4_0:
device->ubwc_config.bank_swizzle_levels = 0x6;
device->ubwc_config.macrotile_mode = FDL_MACROTILE_8_CHANNEL;
break;
default:
return vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
"unknown UBWC version 0x%x", ubwc_version);
}
/* kgsl unfortunately hardcodes some settings for certain GPUs and doesn't
* expose them in the uAPI so hardcode them here to match.
*/
if (device->dev_id.gpu_id == 663 || device->dev_id.gpu_id == 680) {
device->ubwc_config.macrotile_mode = FDL_MACROTILE_8_CHANNEL;
}
if (device->dev_id.gpu_id == 663) {
/* level2_swizzling_dis = 1 */
device->ubwc_config.bank_swizzle_levels = 0x4;
}
instance->knl = &kgsl_knl_funcs;
result = tu_physical_device_init(device, instance);