Skip to content

Commit

Permalink
Check driver version to discover features
Browse files Browse the repository at this point in the history
Discover features and report errors based on the driver version, with
meaningful messages to the user, for diagnostic and bug reporting.
  • Loading branch information
trek00 committed Aug 14, 2019
1 parent 38c0c09 commit 256c910
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 48 deletions.
59 changes: 44 additions & 15 deletions amdgpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,39 +47,68 @@ static int getmclk_amdgpu(uint32_t *out) {
}
#endif

#define DRM_ATLEAST_VERSION(maj, min) \
(drm_major > maj || (drm_major == maj && drm_minor >= min))

void init_amdgpu(int fd) {
uint32_t drm_major, drm_minor;
uint32_t drm_major, drm_minor, out32;
uint64_t out64;
int ret;

if (amdgpu_device_initialize(fd, &drm_major, &drm_minor, &amdgpu_dev))
die(_("Can't initialize amdgpu driver"));
if (amdgpu_device_initialize(fd, &drm_major, &drm_minor, &amdgpu_dev)) {
fprintf(stderr, _("Failed to query amdgpu driver\n"));
return;
}

getgrbm = getgrbm_amdgpu;
if (!(ret = getgrbm_amdgpu(&out32)))
getgrbm = getgrbm_amdgpu;
else
drmError(ret, _("Failed to get GPU usage"));

#ifdef HAS_AMDGPU_QUERY_SENSOR_INFO
struct amdgpu_gpu_info gpu;

amdgpu_query_gpu_info(amdgpu_dev, &gpu);
sclk_max = gpu.max_engine_clk;
mclk_max = gpu.max_memory_clk;
getsclk = getsclk_amdgpu;
getmclk = getmclk_amdgpu;
if (DRM_ATLEAST_VERSION(3, 11)) {
struct amdgpu_gpu_info gpu;

amdgpu_query_gpu_info(amdgpu_dev, &gpu);
sclk_max = gpu.max_engine_clk;
mclk_max = gpu.max_memory_clk;

if (!(ret = getsclk_amdgpu(&out32)))
getsclk = getsclk_amdgpu;
else
drmError(ret, _("Failed to get shader clock"));

if (!(ret = getmclk_amdgpu(&out32)))
getmclk = getmclk_amdgpu;
else // memory clock reporting not available on APUs
if (!(gpu.ids_flags & AMDGPU_IDS_FLAGS_FUSION))
drmError(ret, _("Failed to get memory clock"));
} else
fprintf(stderr, _("Clock frenquency reporting is disabled (amdgpu kernel driver 3.11.0 required)\n"));
#else
printf(_("amdgpu DRM driver is used, but clock reporting is not enabled\n"));
fprintf(stderr, _("Clock frequency reporting is not compiled in (libdrm 2.4.79 required)\n"));
#endif

struct drm_amdgpu_info_vram_gtt vram_gtt;

if ((ret = amdgpu_query_info(amdgpu_dev, AMDGPU_INFO_VRAM_GTT,
sizeof(vram_gtt), &vram_gtt))) {
printf(_("Failed to get VRAM size, error %d\n"), ret);
drmError(ret, _("Failed to get VRAM size"));
return;
}

vramsize = vram_gtt.vram_size;
gttsize = vram_gtt.gtt_size;
getvram = getvram_amdgpu;
getgtt = getgtt_amdgpu;

if (!(ret = getvram_amdgpu(&out64)))
getvram = getvram_amdgpu;
else
drmError(ret, _("Failed to get VRAM usage"));

if (!(ret = getgtt_amdgpu(&out64)))
getgtt = getgtt_amdgpu;
else
drmError(ret, _("Failed to get GTT usage"));
}

void cleanup_amdgpu() {
Expand Down
31 changes: 4 additions & 27 deletions detect.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,11 @@ void init_pci(unsigned char *bus, unsigned int *device_id, const unsigned char f
#ifdef ENABLE_AMDGPU
init_amdgpu(drm_fd);
#else
printf(_("amdgpu DRM driver is used, but support is not compiled in\n"));
fprintf(stderr, _("amdgpu support is not compiled in (libdrm 2.4.63 required)\n"));
#endif
}

uint32_t rreg;
use_ioctl = !getgrbm(&rreg);
use_ioctl = (getgrbm != getuint32_null);
}

if (forcemem) {
Expand All @@ -147,8 +146,6 @@ void init_pci(unsigned char *bus, unsigned int *device_id, const unsigned char f
getgrbm = getgrbm_mem;
}

bits.vram = 0;
bits.gtt = 0;
if (drm_fd < 0) {
printf(_("Failed to open DRM node, no VRAM support.\n"));
} else {
Expand All @@ -160,30 +157,10 @@ void init_pci(unsigned char *bus, unsigned int *device_id, const unsigned char f
ver->version_patchlevel,
ver->name);*/

// No version indicator, so we need to test once
// We use different codepaths for radeon and amdgpu
// We store vram_size and check below if the ret value is sane
uint64_t out64;

ret = getvram(&out64);
if (ret) {
printf(_("Failed to get VRAM usage, kernel likely too old\n"));
goto out;
}

bits.vram = 1;

ret = getgtt(&out64);
if (ret) {
printf(_("Failed to get GTT usage, kernel likely too old\n"));
goto out;
}

bits.gtt = 1;
bits.vram = (getvram != getuint64_null);
bits.gtt = (getgtt != getuint64_null);
}

out:

*bus = gpu_device->bus;
*device_id = gpu_device->device_id;
pci_system_cleanup();
Expand Down
49 changes: 43 additions & 6 deletions radeon.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ static int radeon_get_drm_value(int fd, unsigned request, uint32_t *out) {
return drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
}

#ifdef RADEON_INFO_READ_REG
static int getgrbm_radeon(uint32_t *out) {
*out = GRBM_STATUS;
return radeon_get_drm_value(drm_fd, RADEON_INFO_READ_REG, out);
}
#endif

#ifdef RADEON_INFO_VRAM_USAGE
static int getvram_radeon(uint64_t *out) {
return radeon_get_drm_value(drm_fd, RADEON_INFO_VRAM_USAGE,
(uint32_t *) out);
Expand All @@ -44,30 +47,64 @@ static int getgtt_radeon(uint64_t *out) {
return radeon_get_drm_value(drm_fd, RADEON_INFO_GTT_USAGE,
(uint32_t *) out);
}
#endif

#define DRM_ATLEAST_VERSION(maj, min) \
(drm_major > maj || (drm_major == maj && drm_minor >= min))

void init_radeon(int fd) {
int drm_major, drm_minor, ret;
uint32_t out32;
uint64_t out64;
drmVersionPtr ver = drmGetVersion(fd);

if (!ver) {
perror(_("Failed to query driver version"));
return;
}

drm_fd = fd;
drm_major = ver->version_major;
drm_minor = ver->version_minor;
drmFreeVersion(ver);
getgrbm = getgrbm_radeon;

if (drm_major > 2 || (drm_major == 2 && drm_minor >= 36)) {
#ifdef RADEON_INFO_READ_REG
if (DRM_ATLEAST_VERSION(2, 42)) {
if (!(ret = getgrbm_radeon(&out32)))
getgrbm = getgrbm_radeon;
else
drmError(ret, _("Failed to get GPU usage"));
} else
fprintf(stderr, _("GPU usage reporting is disabled (radeon kernel driver 2.42.0 required)\n"));
#else
fprintf(stderr, _("GPU usage reporting is not compiled in (libdrm 2.4.71 required)\n"));
#endif

#ifdef RADEON_INFO_VRAM_USAGE
if (DRM_ATLEAST_VERSION(2, 39)) {
struct drm_radeon_gem_info gem;

if ((ret = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO,
&gem, sizeof(gem)))) {
printf(_("Failed to get VRAM size, error %d\n"), ret);
drmError(ret, _("Failed to get VRAM size"));
return;
}

vramsize = gem.vram_size;
gttsize = gem.gart_size;
getvram = getvram_radeon;
getgtt = getgtt_radeon;

if (!(ret = getvram_radeon(&out64)))
getvram = getvram_radeon;
else
drmError(ret, _("Failed to get VRAM usage"));

if (!(ret = getgtt_radeon(&out64)))
getgtt = getgtt_radeon;
else
drmError(ret, _("Failed to get GTT usage"));
} else
printf(_("Kernel too old for VRAM reporting.\n"));
fprintf(stderr, _("Memory usage reporting is disabled (radeon kernel driver 2.39.0 required)\n"));
#else
fprintf(stderr, _("Memory usage reporting is not compiled in (libdrm 2.4.53 required)\n"));
#endif
}

0 comments on commit 256c910

Please sign in to comment.