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
|
int
|
||||||
xf86platformProbe(void)
|
xf86platformProbe(void)
|
||||||
{
|
{
|
||||||
|
@ -613,31 +629,58 @@ xf86platformAddGPUDevices(DriverPtr drvp)
|
||||||
return foundScreen;
|
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
|
int
|
||||||
xf86platformAddDevice(int index)
|
xf86platformAddDevice(const char *driver_name, int index)
|
||||||
{
|
{
|
||||||
int i, old_screens, scr_index, scrnum;
|
int i, old_screens, scr_index, scrnum;
|
||||||
DriverPtr drvp = NULL;
|
DriverPtr drvp = NULL;
|
||||||
screenLayoutPtr layout;
|
screenLayoutPtr layout;
|
||||||
static const char *hotplug_driver_name = "modesetting";
|
|
||||||
|
|
||||||
if (!xf86Info.autoAddGPU)
|
if (!xf86Info.autoAddGPU)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* force load the driver for now */
|
/* Load modesetting driver if no driver given, or driver open failed */
|
||||||
xf86LoadOneModule(hotplug_driver_name, NULL);
|
if (!driver_name || !xf86LoadOneModule(driver_name, NULL)) {
|
||||||
|
driver_name = "modesetting";
|
||||||
|
xf86LoadOneModule(driver_name, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < xf86NumDrivers; i++) {
|
for (i = 0; i < xf86NumDrivers; i++) {
|
||||||
if (!xf86DriverList[i])
|
if (!xf86DriverList[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!strcmp(xf86DriverList[i]->driverName, hotplug_driver_name)) {
|
if (!strcmp(xf86DriverList[i]->driverName, driver_name)) {
|
||||||
drvp = xf86DriverList[i];
|
drvp = xf86DriverList[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i == xf86NumDrivers)
|
|
||||||
|
if (i == xf86NumDrivers) {
|
||||||
|
ErrorF("can't find driver %s for hotplugged device\n", driver_name);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
old_screens = xf86NumGPUScreens;
|
old_screens = xf86NumGPUScreens;
|
||||||
doPlatformProbe(&xf86_platform_devices[index], drvp, NULL,
|
doPlatformProbe(&xf86_platform_devices[index], drvp, NULL,
|
||||||
|
|
|
@ -44,6 +44,8 @@ int xf86platformProbe(void);
|
||||||
int xf86platformProbeDev(DriverPtr drvp);
|
int xf86platformProbeDev(DriverPtr drvp);
|
||||||
int xf86platformAddGPUDevices(DriverPtr drvp);
|
int xf86platformAddGPUDevices(DriverPtr drvp);
|
||||||
void xf86MergeOutputClassOptions(int entityIndex, void **options);
|
void xf86MergeOutputClassOptions(int entityIndex, void **options);
|
||||||
|
void xf86PlatformScanPciDev(void);
|
||||||
|
const char *xf86PlatformFindHotplugDriver(int dev_index);
|
||||||
|
|
||||||
extern int xf86_num_platform_devices;
|
extern int xf86_num_platform_devices;
|
||||||
extern struct xf86_platform_device *xf86_platform_devices;
|
extern struct xf86_platform_device *xf86_platform_devices;
|
||||||
|
@ -56,7 +58,7 @@ extern Bool
|
||||||
xf86_get_platform_device_unowned(int index);
|
xf86_get_platform_device_unowned(int index);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
xf86platformAddDevice(int index);
|
xf86platformAddDevice(const char *driver_name, int index);
|
||||||
extern void
|
extern void
|
||||||
xf86platformRemoveDevice(int index);
|
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
|
primary GPU, replacing the selection of the GPU used as output by the
|
||||||
firmware. If multiple output devices match an OutputClass section with
|
firmware. If multiple output devices match an OutputClass section with
|
||||||
the PrimaryGPU option set, the first one enumerated becomes the primary GPU.
|
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
|
A
|
||||||
.B OutputClass
|
.B OutputClass
|
||||||
Section may contain
|
Section may contain
|
||||||
|
|
|
@ -125,7 +125,7 @@ xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs)
|
||||||
xf86_remove_platform_device(index);
|
xf86_remove_platform_device(index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ret = xf86platformAddDevice(index);
|
ret = xf86platformAddDevice(xf86PlatformFindHotplugDriver(index), index);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
xf86_remove_platform_device(index);
|
xf86_remove_platform_device(index);
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,8 @@ void NewGPUDeviceRequest(struct OdevAttributes *attribs)
|
||||||
{
|
{
|
||||||
int old_num = xf86_num_platform_devices;
|
int old_num = xf86_num_platform_devices;
|
||||||
int ret;
|
int ret;
|
||||||
|
const char *driver_name;
|
||||||
|
|
||||||
xf86PlatformDeviceProbe(attribs);
|
xf86PlatformDeviceProbe(attribs);
|
||||||
|
|
||||||
if (old_num == xf86_num_platform_devices)
|
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)
|
if (xf86_get_platform_device_unowned(xf86_num_platform_devices - 1) == TRUE)
|
||||||
return;
|
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)
|
if (ret == -1)
|
||||||
xf86_remove_platform_device(xf86_num_platform_devices-1);
|
xf86_remove_platform_device(xf86_num_platform_devices-1);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue