summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmil Velikov <emil.velikov@collabora.com>2018-03-31 14:27:52 +0100
committerEmil Velikov <emil.l.velikov@gmail.com>2020-03-16 14:25:26 +0000
commit1c9742e304f4d198628cdc9487049cde472c7285 (patch)
treeba71990bed83b543fb791a37a4b0d52b63766003
parent2dd730784e632056c75a0fd62b33206b5fc01602 (diff)
Kill off drmOpen/Close/drmSetInterfaceVersion in favour of drmDevices
The former has very subtle semantics (see the implementation in libdrm for details) which were required in the UMS days. With drmDevices around, we have enough information to build our heuristics and avoid drmOpen all together. In the odd case drmGetDevices2() can take a few extra cycles, so use a reasonably sized local array. v2: - Rebase - Rework now that amdgpu_kernel_mode_enabled() is staying - Keep amdgpu_bus_id() - Use local drmDevice array. v3: - Correct error handling (Michel) - Preserve the "am I master" check (Michel) - Always initialise the fd variable v4: - Don't print "-1" on drmGetDevices2 failure (Michel) - Use uppercase DRM (Michel) v5: - Rebase on top of amdgpu_bus_id() rework - Pass both pci and platform dev to amdgpu_kernel_open_fd() (Michel) - Indent local_drmIsMaster() with tabs (Michel) Signed-off-by: Emil Velikov <emil.velikov@collabora.com> Acked-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--src/amdgpu_probe.c70
1 files changed, 48 insertions, 22 deletions
diff --git a/src/amdgpu_probe.c b/src/amdgpu_probe.c
index ebd2aa7..a59b4ff 100644
--- a/src/amdgpu_probe.c
+++ b/src/amdgpu_probe.c
@@ -77,6 +77,16 @@ static void AMDGPUIdentify(int flags)
xf86PrintChipsets(AMDGPU_NAME, "Driver for AMD Radeon", AMDGPUAny);
}
+static Bool amdgpu_device_matches(const drmDevicePtr device,
+ const struct pci_device *dev)
+{
+ return (device->bustype == DRM_BUS_PCI &&
+ device->businfo.pci->domain == dev->domain &&
+ device->businfo.pci->bus == dev->bus &&
+ device->businfo.pci->dev == dev->dev &&
+ device->businfo.pci->func == dev->func);
+}
+
static Bool amdgpu_kernel_mode_enabled(ScrnInfoPtr pScrn)
{
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -105,9 +115,11 @@ static int amdgpu_kernel_open_fd(ScrnInfoPtr pScrn,
struct xf86_platform_device *platform_dev,
AMDGPUEntPtr pAMDGPUEnt)
{
+#define MAX_DRM_DEVICES 64
+ drmDevicePtr devices[MAX_DRM_DEVICES];
struct pci_device *dev;
const char *path;
- int fd;
+ int fd = -1, i, ret;
if (platform_dev)
dev = platform_dev->pdev;
@@ -138,12 +150,28 @@ static int amdgpu_kernel_open_fd(ScrnInfoPtr pScrn,
if (!amdgpu_kernel_mode_enabled(pScrn))
return -1;
- fd = drmOpen(NULL, pAMDGPUEnt->busid);
+ ret = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
+ if (ret == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[drm] Failed to retrieve DRM devices information.\n");
+ return -1;
+ }
+ for (i = 0; i < ret; i++) {
+ if (amdgpu_device_matches(devices[i], dev) &&
+ devices[i]->available_nodes & (1 << DRM_NODE_PRIMARY)) {
+ path = devices[i]->nodes[DRM_NODE_PRIMARY];
+ fd = open(path, O_RDWR | O_CLOEXEC);
+ break;
+ }
+ }
+ drmFreeDevices(devices, ret);
+
if (fd == -1)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"[drm] Failed to open DRM device for %s: %s\n",
pAMDGPUEnt->busid, strerror(errno));
return fd;
+#undef MAX_DRM_DEVICES
}
void amdgpu_kernel_close_fd(AMDGPUEntPtr pAMDGPUEnt)
@@ -152,32 +180,31 @@ void amdgpu_kernel_close_fd(AMDGPUEntPtr pAMDGPUEnt)
if (!(pAMDGPUEnt->platform_dev &&
pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
#endif
- drmClose(pAMDGPUEnt->fd);
+ close(pAMDGPUEnt->fd);
pAMDGPUEnt->fd = -1;
}
-static Bool amdgpu_open_drm_master(ScrnInfoPtr pScrn, AMDGPUEntPtr pAMDGPUEnt,
- struct pci_device *pci_dev)
+/* Pull a local version of the helper. It's available since 2.4.98 yet
+ * it may be too new for some distributions.
+ */
+static int local_drmIsMaster(int fd)
{
- drmSetVersion sv;
- int err;
+ return drmAuthMagic(fd, 0) != -EACCES;
+}
- pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, pci_dev, NULL, pAMDGPUEnt);
+static Bool amdgpu_open_drm_master(ScrnInfoPtr pScrn,
+ struct pci_device *pci_dev,
+ struct xf86_platform_device *platform_dev,
+ AMDGPUEntPtr pAMDGPUEnt)
+{
+ pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, pci_dev, platform_dev, pAMDGPUEnt);
if (pAMDGPUEnt->fd == -1)
return FALSE;
- /* Check that what we opened was a master or a master-capable FD,
- * by setting the version of the interface we'll use to talk to it.
- * (see DRIOpenDRMMaster() in DRI1)
- */
- sv.drm_di_major = 1;
- sv.drm_di_minor = 1;
- sv.drm_dd_major = -1;
- sv.drm_dd_minor = -1;
- err = drmSetInterfaceVersion(pAMDGPUEnt->fd, &sv);
- if (err != 0) {
+ /* Check that what we opened is a master or a master-capable FD */
+ if (!local_drmIsMaster(pAMDGPUEnt->fd)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "[drm] failed to set drm interface version.\n");
+ "[drm] device is not DRM master.\n");
amdgpu_kernel_close_fd(pAMDGPUEnt);
return FALSE;
}
@@ -233,7 +260,7 @@ static Bool amdgpu_get_scrninfo(int entity_num, struct pci_device *pci_dev)
goto error;
pAMDGPUEnt = pPriv->ptr;
- if (!amdgpu_open_drm_master(pScrn, pAMDGPUEnt, pci_dev))
+ if (!amdgpu_open_drm_master(pScrn, pci_dev, NULL, pAMDGPUEnt))
goto error;
pAMDGPUEnt->fd_ref = 1;
@@ -354,8 +381,7 @@ amdgpu_platform_probe(DriverPtr pDriver,
pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1);
pAMDGPUEnt = pPriv->ptr;
pAMDGPUEnt->platform_dev = dev;
- pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, NULL, dev, pAMDGPUEnt);
- if (pAMDGPUEnt->fd < 0)
+ if (!amdgpu_open_drm_master(pScrn, NULL, dev, pAMDGPUEnt))
goto error;
pAMDGPUEnt->fd_ref = 1;