xf86: allow DDX driver for GPU/PCI hot-plug
The current X server infrastructure sets modesetting driver as default driver to handle PCI-hotplug of a GPU device. This prevents the respective DDX driver (like AMDGPU DDX driver) to take control of the card. This patch: - Adds a few functions and fine-tunes the GPU hotplug infrastructure to allow the DDX driver to be loaded, if it is configured in the X config file options as "hotplug-driver". - Scans and updates the PCI device list before adding the new GPU device in platform, so that the association of the platform device and PCI device is in place (dev->pdev). - Adds documentation of this new option An example usage in the config file would look like: Section "OutputClass" Identifier "AMDgpu" MatchDriver "amdgpu" Driver "amdgpu" HotplugDriver "amdgpu" EndSection V2: Fixed typo in commit message (Martin) Added R-B from Adam. Added ACK from Alex and Martin. V3: Added an output class based approach for finding the DDX driver (Aaron) Rebase V4: Addressed review comment from Aaron: GPU hot-plug handling driver's name to be read from the DDX config file options. In this way only the DDX drivers interested in handling GPU hot-plug will be picked and loaded, for others modesetting driver will be used as usual. V5: Addressed review comments from Aaron: - X config option to be listed in CamelCase. - Indentation fix at one place. - Code readability related optimization. V6: Addressed review comments from Aaron: - Squash the doc in the same patch - Doc formatting changes Cc: Alex Deucher <alexander.deucher@amd.com> Suggested-by: Aaron Plattner aplattner@nvidia.com (v3) Acked-by: Martin Roukala martin.roukala@mupuf.org(v1) Acked-by: Alex Deucher alexander.deucher@amd.com (v1) Reviewed-by: Adam Jackson ajax@redhat.com(v1) Signed-off-by: Shashank Sharma shashank.sharma@amd.com
This commit is contained in:
parent
8c54d590cb
commit
82bf391c93
|
@ -272,6 +272,22 @@ xf86PlatformMatchDriver(XF86MatchedDrivers *md)
|
|||
}
|
||||
}
|
||||
|
||||
void xf86PlatformScanPciDev(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!xf86scanpci())
|
||||
return;
|
||||
|
||||
xf86Msg(X_CONFIG, "Scanning the platform PCI devices\n");
|
||||
for (i = 0; i < xf86_num_platform_devices; i++) {
|
||||
char *busid = xf86_platform_odev_attributes(i)->busid;
|
||||
|
||||
if (strncmp(busid, "pci:", 4) == 0)
|
||||
platform_find_pci_info(&xf86_platform_devices[i], busid);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
xf86platformProbe(void)
|
||||
{
|
||||
|
@ -613,31 +629,58 @@ xf86platformAddGPUDevices(DriverPtr drvp)
|
|||
return foundScreen;
|
||||
}
|
||||
|
||||
const char *
|
||||
xf86PlatformFindHotplugDriver(int dev_index)
|
||||
{
|
||||
XF86ConfOutputClassPtr cl;
|
||||
const char *hp_driver = NULL;
|
||||
struct xf86_platform_device *dev = &xf86_platform_devices[dev_index];
|
||||
|
||||
for (cl = xf86configptr->conf_outputclass_lst; cl; cl = cl->list.next) {
|
||||
if (!OutputClassMatches(cl, dev) || !cl->option_lst)
|
||||
continue;
|
||||
|
||||
hp_driver = xf86FindOptionValue(cl->option_lst, "HotplugDriver");
|
||||
if (hp_driver)
|
||||
xf86MarkOptionUsed(cl->option_lst);
|
||||
}
|
||||
|
||||
/* Return the first driver from the match list */
|
||||
xf86Msg(X_INFO, "matching hotplug-driver is %s\n",
|
||||
hp_driver ? hp_driver : "none");
|
||||
return hp_driver;
|
||||
}
|
||||
|
||||
int
|
||||
xf86platformAddDevice(int index)
|
||||
xf86platformAddDevice(const char *driver_name, int index)
|
||||
{
|
||||
int i, old_screens, scr_index, scrnum;
|
||||
DriverPtr drvp = NULL;
|
||||
screenLayoutPtr layout;
|
||||
static const char *hotplug_driver_name = "modesetting";
|
||||
|
||||
if (!xf86Info.autoAddGPU)
|
||||
return -1;
|
||||
|
||||
/* force load the driver for now */
|
||||
xf86LoadOneModule(hotplug_driver_name, NULL);
|
||||
/* Load modesetting driver if no driver given, or driver open failed */
|
||||
if (!driver_name || !xf86LoadOneModule(driver_name, NULL)) {
|
||||
driver_name = "modesetting";
|
||||
xf86LoadOneModule(driver_name, NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < xf86NumDrivers; i++) {
|
||||
if (!xf86DriverList[i])
|
||||
continue;
|
||||
|
||||
if (!strcmp(xf86DriverList[i]->driverName, hotplug_driver_name)) {
|
||||
if (!strcmp(xf86DriverList[i]->driverName, driver_name)) {
|
||||
drvp = xf86DriverList[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == xf86NumDrivers)
|
||||
|
||||
if (i == xf86NumDrivers) {
|
||||
ErrorF("can't find driver %s for hotplugged device\n", driver_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
old_screens = xf86NumGPUScreens;
|
||||
doPlatformProbe(&xf86_platform_devices[index], drvp, NULL,
|
||||
|
|
|
@ -44,6 +44,8 @@ int xf86platformProbe(void);
|
|||
int xf86platformProbeDev(DriverPtr drvp);
|
||||
int xf86platformAddGPUDevices(DriverPtr drvp);
|
||||
void xf86MergeOutputClassOptions(int entityIndex, void **options);
|
||||
void xf86PlatformScanPciDev(void);
|
||||
const char *xf86PlatformFindHotplugDriver(int dev_index);
|
||||
|
||||
extern int xf86_num_platform_devices;
|
||||
extern struct xf86_platform_device *xf86_platform_devices;
|
||||
|
@ -56,7 +58,7 @@ extern Bool
|
|||
xf86_get_platform_device_unowned(int index);
|
||||
|
||||
extern int
|
||||
xf86platformAddDevice(int index);
|
||||
xf86platformAddDevice(const char *driver_name, int index);
|
||||
extern void
|
||||
xf86platformRemoveDevice(int index);
|
||||
|
||||
|
|
|
@ -1296,7 +1296,20 @@ This option specifies that the matched device should be treated as the
|
|||
primary GPU, replacing the selection of the GPU used as output by the
|
||||
firmware. If multiple output devices match an OutputClass section with
|
||||
the PrimaryGPU option set, the first one enumerated becomes the primary GPU.
|
||||
.PP
|
||||
.TP 7
|
||||
.BI "Option \*qHotplugDriver\*q \*q" driver \*q
|
||||
This option specifies that the matched driver should be used to handle a
|
||||
hot-plugged GPU device.
|
||||
The module specified by
|
||||
.I driver
|
||||
will be loaded during setup of the GPU device.
|
||||
If loading of this module fails or there is no driver by that name, the
|
||||
modesetting driver will be used, which is the default behavior.
|
||||
If multiple output devices match an
|
||||
.B OutputClass
|
||||
section with the
|
||||
.B HotplugDriver
|
||||
option, the first one enumerated becomes the hotplug driver.
|
||||
A
|
||||
.B OutputClass
|
||||
Section may contain
|
||||
|
|
|
@ -125,7 +125,7 @@ xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs)
|
|||
xf86_remove_platform_device(index);
|
||||
return;
|
||||
}
|
||||
ret = xf86platformAddDevice(index);
|
||||
ret = xf86platformAddDevice(xf86PlatformFindHotplugDriver(index), index);
|
||||
if (ret == -1)
|
||||
xf86_remove_platform_device(index);
|
||||
}
|
||||
|
@ -173,6 +173,8 @@ void NewGPUDeviceRequest(struct OdevAttributes *attribs)
|
|||
{
|
||||
int old_num = xf86_num_platform_devices;
|
||||
int ret;
|
||||
const char *driver_name;
|
||||
|
||||
xf86PlatformDeviceProbe(attribs);
|
||||
|
||||
if (old_num == xf86_num_platform_devices)
|
||||
|
@ -181,7 +183,11 @@ void NewGPUDeviceRequest(struct OdevAttributes *attribs)
|
|||
if (xf86_get_platform_device_unowned(xf86_num_platform_devices - 1) == TRUE)
|
||||
return;
|
||||
|
||||
ret = xf86platformAddDevice(xf86_num_platform_devices-1);
|
||||
/* Scan and update PCI devices before adding new platform device */
|
||||
xf86PlatformScanPciDev();
|
||||
driver_name = xf86PlatformFindHotplugDriver(xf86_num_platform_devices - 1);
|
||||
|
||||
ret = xf86platformAddDevice(driver_name, xf86_num_platform_devices-1);
|
||||
if (ret == -1)
|
||||
xf86_remove_platform_device(xf86_num_platform_devices-1);
|
||||
|
||||
|
|
Loading…
Reference in New Issue