xfree86: Fix autoconfig secondary GPU devices

The code path added by commit 69e4b8e6 (xfree86: attempt to autoconfig
gpu slave devices (v3)) assumes that it will only be run if the primary
device on the screen is the first device in xf86configptr->conf_device_lst.
While this is true most of the time, there are two specific cases where
this assumption fails.

First, if the first device in conf_device_lst is assigned to a different
seat than the running X server, it will be skipped by the previous
FIND_SUITABLE macro usage. Second, if the primary device was explicitly
assigned to the screen but auto_gpu_device is still set and no secondary
devices were explicitly listed, that device may not be the first device
in conf_device_lst.

When the first device in conf_device_lst is not the primary device
assigned to the screen, two problems emerge. First, the first device in
conf_device_lst will never be assigned to the screen as a secondary
device. Second, the primary device is additionally assigned to the
screen as a secondary device. The combination of these problems causes
certain otherwise valid configurations to be invalid. For example, if a
primary device is assigned to a screen and a secondary device is listed
in the config but not explicitly assigned to the screen, then one order
of the device sections results in a usable PRIME or Reverse PRIME setup
and the other order does not.

This commit removes the assumption that the primary device is the first
device in conf_device_lst by starting the loop from the start of
conf_device_lst and skipping the primary device when it is encountered.

Signed-off-by: Jacob Cherry <jcherry@nvidia.com>
This commit is contained in:
Jacob Cherry 2021-03-03 17:50:31 +00:00 committed by Aaron Plattner
parent 97ed0048e4
commit a5367face1
1 changed files with 22 additions and 3 deletions

View File

@ -1738,15 +1738,34 @@ configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum,
if (auto_gpu_device && conf_screen->num_gpu_devices == 0 &&
xf86configptr->conf_device_lst) {
XF86ConfDevicePtr sdevice = xf86configptr->conf_device_lst->list.next;
/* Loop through the entire device list and skip the primary device
* assigned to the screen. This is important because there are two
* cases where the assigned primary device is not the first device in
* the device list. Firstly, if the first device in the list is assigned
* to a different seat than this X server, it will not have been picked
* by the previous FIND_SUITABLE. Secondly, if the device was explicitly
* assigned in the config but there is still only one screen, this code
* path is executed but the explicitly assigned device may not be the
* first device in the list. */
XF86ConfDevicePtr ptmp, sdevice = xf86configptr->conf_device_lst;
for (i = 0; i < MAX_GPUDEVICES; i++) {
if (!sdevice)
break;
FIND_SUITABLE (XF86ConfDevicePtr, sdevice, conf_screen->scrn_gpu_devices[i]);
if (!conf_screen->scrn_gpu_devices[i])
FIND_SUITABLE (XF86ConfDevicePtr, sdevice, ptmp);
if (!ptmp)
break;
/* skip the primary device on the screen */
if (ptmp != conf_screen->scrn_device) {
conf_screen->scrn_gpu_devices[i] = ptmp;
} else {
sdevice = ptmp->list.next;
i--; /* run the next iteration with the same index */
continue;
}
screenp->gpu_devices[i] = xnfcalloc(1, sizeof(GDevRec));
if (configDevice(screenp->gpu_devices[i], conf_screen->scrn_gpu_devices[i], TRUE, TRUE)) {
screenp->gpu_devices[i]->myScreenSection = screenp;