diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c index 33a6336aa..8bd29795f 100644 --- a/hw/xfree86/common/xf86Bus.c +++ b/hw/xfree86/common/xf86Bus.c @@ -655,3 +655,225 @@ xf86GetEntityPrivate(int entityIndex, int privIndex) return &(xf86Entities[entityIndex]->entityPrivates[privIndex]); } + +/* + * Check if the slot requested is free. If it is already in use, return FALSE. + */ + +Bool +xf86CheckSlot(const void *ptr, BusType type) +{ + int i; + +#ifdef XSERVER_LIBPCIACCESS + const struct pci_device *pci_ptr = (type == BUS_PCI ? + (const struct pci_device *)ptr : NULL); +#endif + +#ifdef XSERVER_PLATFORM_BUS + const struct xf86_platform_device *plat_ptr = (type == BUS_PLATFORM ? + (const struct xf86_platform_device *)ptr : NULL); +#endif + + GDevPtr fb_ptr = (type == BUS_NONE ? + (GDevPtr)ptr : NULL); + const char *msPath = NULL; + const char *fbPath = NULL; + + if (ptr == NULL) { + return FALSE; + } + +#ifdef XSERVER_PLATFORM_BUS + /* XSERVER_PLATFORM_BUS assumes XSERVER_LIBPCIACCESS */ + if (plat_ptr) { + pci_ptr = plat_ptr->pdev; + msPath = plat_ptr->attribs->path; + } +#endif + + if (type == BUS_NONE) { + if (!strcasecmp(fb_ptr->driver, "modesetting")) { + /* + * If xf86ClaimFbSlot() is called by modesetting driver, + * busID has not been set and the device name was not specified + * via "kmsdev" option, the default "/dev/dri/card0" is used. + * + * We have to check whether a platform device has previously + * grabbed the device we are going to claim. + */ + msPath = xf86FindOptionValue(fb_ptr->options, "kmsdev"); + if (msPath == NULL) { + /* Autoconfigured */ + msPath = "/dev/dri/card0"; + } + } + else + if (!strcasecmp(fb_ptr->driver, "fbdev")) { + /* + * fbdev driver can also call xf86ClaimFbSlot() for + * an autoconfigured device, or the device name can be set + * via "fbdev" option. + */ + fbPath = xf86FindOptionValue(fb_ptr->options, "fbdev"); + if (fbPath == NULL) { + /* Autoconfigured */ + fbPath = ""; + } + } + } + + /* + * Having prepared all data about a candidate, we walk + * through all previous entities to check for a collision. + */ + + for (i = 0; i < xf86NumEntities; i++) { + const EntityPtr pent = xf86Entities[i]; +#ifdef XSERVER_LIBPCIACCESS + struct pci_device *pci_other; +#endif + const char *msOther = NULL; + const char *fbOther = NULL; + + if (pent->numInstances <= 0) { + /* All devices are unclaimed, ignore this entity */ + continue; + } + + if ((fbPath != NULL) && (*fbPath == '\0')) { + /* Autoconfigured fbdev device is incompatible with anything */ + LogMessageVerb(X_INFO, 1, + "\"%s\" must be the only device, but \"%s\" is present.\n", + fb_ptr->identifier, pent->devices[0]->identifier); + return FALSE; + } + +#ifdef XSERVER_LIBPCIACCESS + pci_other = xf86GetPciInfoForEntity(i); + /* First compare PCI addresses */ + if (pci_ptr && pci_other) { + if (MATCH_PCI_DEVICES(pci_other, pci_ptr)) { + /* This PCI slot has been claimed, fail */ + if (msPath) { + LogMessageVerb(X_INFO, 1, + " Platform device \"%s\" skipped because\n", + msPath); + } + else { + LogMessageVerb(X_INFO, 1, + " PCI device skipped because\n"); + } + LogMessageVerb(X_INFO, 1, + " PCI bus id %u@%u:%u:%u has already been claimed by \"%s\".\n", + pci_ptr->domain, pci_ptr->bus, pci_ptr->dev, pci_ptr->func, + pent->devices[0]->identifier); + return FALSE; + } + else + /* This is another device, skip */ + continue; + } + + if (pent->bus.type == BUS_PCI) { + /* No other means to compare, accept */ + continue; + } +#endif + + if (pent->bus.type == BUS_NONE) { + if (!strcasecmp(pent->driver->driverName, "fbdev")) { + if ((type != BUS_NONE) || (fbPath == NULL)) { + /* fbdev without busID is incompatible with other types */ + LogMessageVerb(X_INFO, 1, + " Only fbdev without PCI bus id can be claimed after \"%s\".\n", + pent->devices[0]->identifier); + return FALSE; + } + /* Examine the first device only */ + fbOther = xf86FindOptionValue(pent->devices[0]->options, "fbdev"); + if (fbOther == NULL) { + /* Autoconfigured, reject */ + LogMessageVerb(X_INFO, 1, + " Can\'t claim anything after \"%s\".\n", + pent->devices[0]->identifier); + return FALSE; + } + if (strcmp(fbPath, fbOther)) { + /* No conflict */ + continue; + } + else { + /* This framebuffer device has been claimed already */ + LogMessageVerb(X_INFO, 1, + " Framebuffer device \"%s\" has already been claimed by \"%s\".\n", + fbPath, pent->devices[0]->identifier); + return FALSE; + } + } + } + +#ifdef XSERVER_PLATFORM_BUS + if (pent->bus.type == BUS_PLATFORM) { + msOther = pent->bus.id.plat->attribs->path; + } else +#endif + if (pent->bus.type == BUS_NONE) { + if (!strcasecmp(pent->driver->driverName, "modesetting")) { + /* Examine the first device only */ + msOther = xf86FindOptionValue(pent->devices[0]->options, "kmsdev"); + if ((msOther == NULL) && (pci_other == NULL)) { + /* Autoconfigured */ + msOther = "/dev/dri/card0"; + } + } + } + + if ((msPath != NULL) && (msOther != NULL) && !strcmp(msPath, msOther)) { + /* This DRI device has been claimed already */ + LogMessageVerb(X_INFO, 1, + " DRI device \"%s\" has already been claimed by \"%s\".\n", + msPath, pent->devices[0]->identifier); + return FALSE; + } + } + +#ifdef XSERVER_PLATFORM_BUS + if (type == BUS_PLATFORM) { + if (pci_ptr) + LogMessageVerb(X_INFO, 1, + " Platform device \"%s\" at %u@%u:%u:%u can be claimed.\n", + msPath, pci_ptr->domain, pci_ptr->bus, pci_ptr->dev, pci_ptr->func); + else + LogMessageVerb(X_INFO, 1, + " Platform device \"%s\" can be claimed.\n", + msPath); + } + else +#endif +#ifdef XSERVER_LIBPCIACCESS + if (type == BUS_PCI) { + LogMessageVerb(X_INFO, 1, + " PCI device %u@%u:%u:%u can be claimed.\n", + pci_ptr->domain, pci_ptr->bus, pci_ptr->dev, pci_ptr->func); + } + else +#endif + if (type == BUS_NONE) { + if (msPath) + LogMessageVerb(X_INFO, 1, + "\"%s\" can be claimed by modesetting driver as \"%s\".\n", + msPath, fb_ptr->identifier); + else + if (fbPath) + LogMessageVerb(X_INFO, 1, + "\"%s\" can be claimed by fbdev driver as \"%s\".\n", + fbPath, fb_ptr->identifier); + else + LogMessageVerb(X_INFO, 1, + "\"%s\" can be claimed.\n", + fb_ptr->identifier); + } + + return TRUE; +} diff --git a/hw/xfree86/common/xf86Bus.h b/hw/xfree86/common/xf86Bus.h index d8e8bf3e2..933bef492 100644 --- a/hw/xfree86/common/xf86Bus.h +++ b/hw/xfree86/common/xf86Bus.h @@ -83,4 +83,5 @@ void xf86RemoveDevFromEntity(int entityIndex, GDevPtr dev); Bool xf86CallDriverProbe(struct _DriverRec *drv, Bool detect_only); +Bool xf86CheckSlot(const void *ptr, BusType type); #endif /* _XF86_BUS_H */ diff --git a/hw/xfree86/common/xf86fbBus.c b/hw/xfree86/common/xf86fbBus.c index 22825d8ae..7dbd5ac2c 100644 --- a/hw/xfree86/common/xf86fbBus.c +++ b/hw/xfree86/common/xf86fbBus.c @@ -50,14 +50,18 @@ xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active) EntityPtr p; int num; - num = xf86AllocateEntity(); - p = xf86Entities[num]; - p->driver = drvp; - p->chipset = 0; - p->bus.type = BUS_NONE; - p->active = active; - p->inUse = FALSE; - xf86AddDevToEntity(num, dev); + if (xf86CheckSlot(dev, BUS_NONE)) { + num = xf86AllocateEntity(); + p = xf86Entities[num]; + p->driver = drvp; + p->chipset = 0; + p->bus.type = BUS_NONE; + p->active = active; + p->inUse = FALSE; + xf86AddDevToEntity(num, dev); - return num; + return num; + } else { + return -1; + } } diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c index 62648efaf..9e697146e 100644 --- a/hw/xfree86/common/xf86pciBus.c +++ b/hw/xfree86/common/xf86pciBus.c @@ -411,23 +411,7 @@ xf86CheckPciMemBase(struct pci_device *pPci, memType base) Bool xf86CheckPciSlot(const struct pci_device *d) { - int i; - - for (i = 0; i < xf86NumEntities; i++) { - const EntityPtr p = xf86Entities[i]; - - if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { - return FALSE; - } -#ifdef XSERVER_PLATFORM_BUS - if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat->pdev)) { - struct pci_device *ud = p->bus.id.plat->pdev; - if (MATCH_PCI_DEVICES(ud, d)) - return FALSE; - } -#endif - } - return TRUE; + return xf86CheckSlot(d, BUS_PCI); } #define END_OF_MATCHES(m) \ diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c index e8cf44178..1fd4514a3 100644 --- a/hw/xfree86/common/xf86platformBus.c +++ b/hw/xfree86/common/xf86platformBus.c @@ -155,25 +155,6 @@ platform_find_pci_info(struct xf86_platform_device *pd, char *busid) pci_iterator_destroy(iter); } -static Bool -xf86_check_platform_slot(const struct xf86_platform_device *pd) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) { - const EntityPtr u = xf86Entities[i]; - - if (pd->pdev && u->bus.type == BUS_PCI && - MATCH_PCI_DEVICES(pd->pdev, u->bus.id.pci)) { - return FALSE; - } - if ((u->bus.type == BUS_PLATFORM) && (pd == u->bus.id.plat)) { - return FALSE; - } - } - return TRUE; -} - static Bool OutputClassMatches(const XF86ConfOutputClassPtr oclass, struct xf86_platform_device *dev) @@ -465,7 +446,7 @@ xf86ClaimPlatformSlot(struct xf86_platform_device * d, DriverPtr drvp, EntityPtr p = NULL; int num; - if (xf86_check_platform_slot(d)) { + if (xf86CheckSlot(d, BUS_PLATFORM)) { num = xf86AllocateEntity(); p = xf86Entities[num]; p->driver = drvp; @@ -511,27 +492,29 @@ static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp, Bool foundScreen = FALSE; int entity; - if (gdev && gdev->screen == 0 && !xf86_check_platform_slot(dev)) - return FALSE; - entity = xf86ClaimPlatformSlot(dev, drvp, 0, gdev, gdev ? gdev->active : 0); - if ((entity == -1) && gdev && (gdev->screen > 0)) { - unsigned nent; + if ((entity == -1) && gdev) { + if (gdev->screen == 0) + return FALSE; + else { /* gdev->screen > 0 */ + unsigned nent; - for (nent = 0; nent < xf86NumEntities; nent++) { - EntityPtr pEnt = xf86Entities[nent]; + for (nent = 0; nent < xf86NumEntities; nent++) { + EntityPtr pEnt = xf86Entities[nent]; - if (pEnt->bus.type != BUS_PLATFORM) - continue; - if (pEnt->bus.id.plat == dev) { - entity = nent; - xf86AddDevToEntity(nent, gdev); - break; + if (pEnt->bus.type != BUS_PLATFORM) + continue; + if (pEnt->bus.id.plat == dev) { + entity = nent; + xf86AddDevToEntity(nent, gdev); + break; + } } } } + if (entity != -1) { if ((dev->flags & XF86_PDEV_SERVER_FD) && (!drvp->driverFunc || !drvp->driverFunc(NULL, SUPPORTS_SERVER_FDS, NULL))) {