summaryrefslogtreecommitdiff
path: root/driver/xf86-video-amdgpu/src/amdgpu_probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/xf86-video-amdgpu/src/amdgpu_probe.c')
-rw-r--r--driver/xf86-video-amdgpu/src/amdgpu_probe.c258
1 files changed, 114 insertions, 144 deletions
diff --git a/driver/xf86-video-amdgpu/src/amdgpu_probe.c b/driver/xf86-video-amdgpu/src/amdgpu_probe.c
index 2dc934ff6..71304668b 100644
--- a/driver/xf86-video-amdgpu/src/amdgpu_probe.c
+++ b/driver/xf86-video-amdgpu/src/amdgpu_probe.c
@@ -33,6 +33,8 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
/*
* Authors:
@@ -48,12 +50,17 @@
#include "xf86.h"
#include "xf86drmMode.h"
-#include "dri.h"
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <xf86_OSproc.h>
#endif
+#ifdef X_PRIVSEP
+extern int priv_open_device(const char *);
+#else
+#define priv_open_device(n) open(n,O_RDWR|O_CLOEXEC)
+#endif
+
#include <xf86platformBus.h>
_X_EXPORT int gAMDGPUEntityIndex = -1;
@@ -75,36 +82,34 @@ static void AMDGPUIdentify(int flags)
xf86PrintChipsets(AMDGPU_NAME, "Driver for AMD Radeon", AMDGPUAny);
}
-static char *amdgpu_bus_id(ScrnInfoPtr pScrn, struct pci_device *dev)
+static Bool amdgpu_device_matches(const drmDevicePtr device,
+ const struct pci_device *dev)
{
- char *busid;
-
- XNFasprintf(&busid, "pci:%04x:%02x:%02x.%d",
- dev->domain, dev->bus, dev->dev, dev->func);
-
- if (!busid)
- xf86DrvMsgVerb(pScrn->scrnIndex, X_ERROR, 0,
- "AMDGPU: Failed to generate bus ID string\n");
-
- return busid;
+ 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, char *busIdString)
+static Bool amdgpu_kernel_mode_enabled(ScrnInfoPtr pScrn)
{
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+ AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
+ const char *busIdString = pAMDGPUEnt->busid;
int ret = drmCheckModesettingSupported(busIdString);
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if (ret) {
if (xf86LoadKernelModule("amdgpukms"))
ret = drmCheckModesettingSupported(busIdString);
}
-#endif
if (ret) {
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
"[KMS] drm report modesetting isn't supported.\n");
return FALSE;
}
+#endif
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
"[KMS] Kernel modesetting enabled.\n");
return TRUE;
@@ -112,42 +117,66 @@ static Bool amdgpu_kernel_mode_enabled(ScrnInfoPtr pScrn, char *busIdString)
static int amdgpu_kernel_open_fd(ScrnInfoPtr pScrn,
struct pci_device *pci_dev,
- struct xf86_platform_device *platform_dev)
+ struct xf86_platform_device *platform_dev,
+ AMDGPUEntPtr pAMDGPUEnt)
{
+#define MAX_DRM_DEVICES 64
+ drmDevicePtr devices[MAX_DRM_DEVICES];
struct pci_device *dev;
- char *busid;
- int fd;
+ const char *path;
+ int fd = -1, i, ret;
+
+ if (platform_dev)
+ dev = platform_dev->pdev;
+ else
+ dev = pci_dev;
+
+ XNFasprintf(&pAMDGPUEnt->busid, "pci:%04x:%02x:%02x.%u",
+ dev->domain, dev->bus, dev->dev, dev->func);
-#ifdef ODEV_ATTRIB_FD
if (platform_dev) {
+#ifdef ODEV_ATTRIB_FD
fd = xf86_get_platform_device_int_attrib(platform_dev,
ODEV_ATTRIB_FD, -1);
if (fd != -1)
return fd;
- }
#endif
- if (platform_dev)
- dev = platform_dev->pdev;
- else
- dev = pci_dev;
+#ifdef ODEV_ATTRIB_PATH
+ path = xf86_get_platform_device_attrib(platform_dev,
+ ODEV_ATTRIB_PATH);
- busid = amdgpu_bus_id(pScrn, dev);
- if (!busid)
+ fd = priv_open_device(path);
+ if (fd != -1)
+ return fd;
+#endif
+ }
+
+ if (!amdgpu_kernel_mode_enabled(pScrn))
return -1;
- if (!amdgpu_kernel_mode_enabled(pScrn, busid)) {
- free(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 = priv_open_device(path);
+ break;
+ }
+ }
+ drmFreeDevices(devices, ret);
- fd = drmOpen(NULL, busid);
if (fd == -1)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"[drm] Failed to open DRM device for %s: %s\n",
- busid, strerror(errno));
- free(busid);
+ pAMDGPUEnt->busid, strerror(errno));
return fd;
+#undef MAX_DRM_DEVICES
}
void amdgpu_kernel_close_fd(AMDGPUEntPtr pAMDGPUEnt)
@@ -156,32 +185,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);
+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;
}
@@ -189,16 +217,43 @@ static Bool amdgpu_open_drm_master(ScrnInfoPtr pScrn, AMDGPUEntPtr pAMDGPUEnt,
return TRUE;
}
-static Bool amdgpu_get_scrninfo(int entity_num, struct pci_device *pci_dev)
+static Bool amdgpu_device_setup(ScrnInfoPtr pScrn,
+ struct pci_device *pci_dev,
+ struct xf86_platform_device *platform_dev,
+ AMDGPUEntPtr pAMDGPUEnt)
+{
+ uint32_t major_version;
+ uint32_t minor_version;
+
+ pAMDGPUEnt->platform_dev = platform_dev;
+ if (!amdgpu_open_drm_master(pScrn, pci_dev, platform_dev,
+ pAMDGPUEnt))
+ return FALSE;
+
+ if (amdgpu_device_initialize(pAMDGPUEnt->fd,
+ &major_version,
+ &minor_version,
+ &pAMDGPUEnt->pDev)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "amdgpu_device_initialize failed\n");
+ goto error_amdgpu;
+ }
+
+ return TRUE;
+
+error_amdgpu:
+ amdgpu_kernel_close_fd(pAMDGPUEnt);
+ return FALSE;
+}
+
+static Bool
+amdgpu_probe(ScrnInfoPtr pScrn, int entity_num,
+ struct pci_device *pci_dev, struct xf86_platform_device *dev)
{
- ScrnInfoPtr pScrn = NULL;
EntityInfoPtr pEnt = NULL;
DevUnion *pPriv;
AMDGPUEntPtr pAMDGPUEnt;
- pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, NULL,
- NULL, NULL, NULL, NULL, NULL);
-
if (!pScrn)
return FALSE;
@@ -206,7 +261,6 @@ static Bool amdgpu_get_scrninfo(int entity_num, struct pci_device *pci_dev)
pScrn->driverName = AMDGPU_DRIVER_NAME;
pScrn->name = AMDGPU_NAME;
pScrn->Probe = NULL;
-
pScrn->PreInit = AMDGPUPreInit_KMS;
pScrn->ScreenInit = AMDGPUScreenInit_KMS;
pScrn->SwitchMode = AMDGPUSwitchMode_KMS;
@@ -229,27 +283,16 @@ static Bool amdgpu_get_scrninfo(int entity_num, struct pci_device *pci_dev)
pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex);
if (!pPriv->ptr) {
- uint32_t major_version;
- uint32_t minor_version;
-
pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1);
if (!pPriv->ptr)
goto error;
pAMDGPUEnt = pPriv->ptr;
- if (!amdgpu_open_drm_master(pScrn, pAMDGPUEnt, pci_dev))
+ if (!amdgpu_device_setup(pScrn, pci_dev, dev, pAMDGPUEnt))
goto error;
pAMDGPUEnt->fd_ref = 1;
- if (amdgpu_device_initialize(pAMDGPUEnt->fd,
- &major_version,
- &minor_version,
- &pAMDGPUEnt->pDev)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "amdgpu_device_initialize failed\n");
- goto error_amdgpu;
- }
} else {
pAMDGPUEnt = pPriv->ptr;
@@ -271,8 +314,6 @@ static Bool amdgpu_get_scrninfo(int entity_num, struct pci_device *pci_dev)
return TRUE;
-error_amdgpu:
- amdgpu_kernel_close_fd(pAMDGPUEnt);
error:
free(pEnt);
return FALSE;
@@ -282,7 +323,10 @@ static Bool
amdgpu_pci_probe(DriverPtr pDriver,
int entity_num, struct pci_device *device, intptr_t match_data)
{
- return amdgpu_get_scrninfo(entity_num, device);
+ ScrnInfoPtr pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+
+ return amdgpu_probe(pScrn, entity_num, device, NULL);
}
static Bool AMDGPUDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data)
@@ -311,9 +355,6 @@ amdgpu_platform_probe(DriverPtr pDriver,
{
ScrnInfoPtr pScrn;
int scr_flags = 0;
- EntityInfoPtr pEnt = NULL;
- DevUnion *pPriv;
- AMDGPUEntPtr pAMDGPUEnt;
if (!dev->pdev)
return FALSE;
@@ -326,78 +367,7 @@ amdgpu_platform_probe(DriverPtr pDriver,
xf86SetEntityShared(entity_num);
xf86AddEntityToScreen(pScrn, entity_num);
- pScrn->driverVersion = AMDGPU_VERSION_CURRENT;
- pScrn->driverName = AMDGPU_DRIVER_NAME;
- pScrn->name = AMDGPU_NAME;
- pScrn->Probe = NULL;
- pScrn->PreInit = AMDGPUPreInit_KMS;
- pScrn->ScreenInit = AMDGPUScreenInit_KMS;
- pScrn->SwitchMode = AMDGPUSwitchMode_KMS;
- pScrn->AdjustFrame = AMDGPUAdjustFrame_KMS;
- pScrn->EnterVT = AMDGPUEnterVT_KMS;
- pScrn->LeaveVT = AMDGPULeaveVT_KMS;
- pScrn->FreeScreen = AMDGPUFreeScreen_KMS;
- pScrn->ValidMode = AMDGPUValidMode;
-
- pEnt = xf86GetEntityInfo(entity_num);
-
- /* Create a AMDGPUEntity for all chips, even with old single head
- * Radeon, need to use pAMDGPUEnt for new monitor detection routines.
- */
- xf86SetEntitySharable(entity_num);
-
- if (gAMDGPUEntityIndex == -1)
- gAMDGPUEntityIndex = xf86AllocateEntityPrivateIndex();
-
- pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex);
-
- if (!pPriv->ptr) {
- uint32_t major_version;
- uint32_t minor_version;
-
- pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1);
- pAMDGPUEnt = pPriv->ptr;
- pAMDGPUEnt->platform_dev = dev;
- pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, NULL, dev);
- if (pAMDGPUEnt->fd < 0)
- goto error;
-
- pAMDGPUEnt->fd_ref = 1;
-
- if (amdgpu_device_initialize(pAMDGPUEnt->fd,
- &major_version,
- &minor_version,
- &pAMDGPUEnt->pDev)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "amdgpu_device_initialize failed\n");
- goto error_amdgpu;
- }
- } else {
- pAMDGPUEnt = pPriv->ptr;
-
- if (pAMDGPUEnt->fd_ref == ARRAY_SIZE(pAMDGPUEnt->scrn)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Only up to %u Zaphod instances supported\n",
- (unsigned)ARRAY_SIZE(pAMDGPUEnt->scrn));
- goto error;
- }
-
- pAMDGPUEnt->fd_ref++;
- }
-
- xf86SetEntityInstanceForScreen(pScrn, pEnt->index,
- xf86GetNumEntityInstances(pEnt->
- index)
- - 1);
- free(pEnt);
-
- return TRUE;
-
-error_amdgpu:
- amdgpu_kernel_close_fd(pAMDGPUEnt);
-error:
- free(pEnt);
- return FALSE;
+ return amdgpu_probe(pScrn, entity_num, NULL, dev);
}
#endif