diff options
Diffstat (limited to 'driver/xf86-video-amdgpu/src/amdgpu_probe.c')
-rw-r--r-- | driver/xf86-video-amdgpu/src/amdgpu_probe.c | 258 |
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 |