[PATCH weston v2] compositor-drm: prefer PCI boot_vga GPU over other GPUs

Kristian Høgsberg hoegsberg at gmail.com
Mon Oct 29 13:27:37 PDT 2012


On Mon, Oct 29, 2012 at 07:21:16PM +0100, David Herrmann wrote:
> If we can find a boot_vga PCI GPU, we should prefer it over any other GPU
> that is connected to the system. The boot_vga flag tells us that this GPU
> is the primary system GPU.
> 
> This fixes problems on two-GPU-systems were the wrong GPU is used. It also
> fixes systems were DisplayLink GPUs are available with lower IDs than PCI
> GPUs (although, this seems unlikely).
> 
> Note that udev_enumerate guarantees that the entry-list is sorted. So for
> systems that have platform-GPUs, these should almost always be reported
> prior to hotpluggable (PCI, USB, ...) GPUs, as the kernel probes them
> first.

That looks good, definitely an improvement over what we have now.
If/when we start supporting multiple GPUs and/or DisplayLink devices,
we'll figure what the next step looks like.

Kristian

> Signed-off-by: David Herrmann <dh.herrmann at googlemail.com>
> ---
>  src/compositor-drm.c | 90 ++++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 62 insertions(+), 28 deletions(-)
> 
> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> index 3e75387..1730cb2 100644
> --- a/src/compositor-drm.c
> +++ b/src/compositor-drm.c
> @@ -2148,18 +2148,72 @@ switch_vt_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
>  	tty_activate_vt(ec->tty, key - KEY_F1 + 1);
>  }
>  
> +/*
> + * Find primary GPU
> + * Some systems may have multiple DRM devices attached to a single seat. This
> + * function loops over all devices and tries to find a PCI device with the
> + * boot_vga sysfs attribute set to 1.
> + * If no such device is found, the first DRM device reported by udev is used.
> + */
> +static struct udev_device*
> +find_primary_gpu(struct drm_compositor *ec, const char *seat)
> +{
> +	struct udev_enumerate *e;
> +	struct udev_list_entry *entry;
> +	const char *path, *device_seat, *id;
> +	struct udev_device *device, *drm_device, *pci;
> +
> +	e = udev_enumerate_new(ec->udev);
> +	udev_enumerate_add_match_subsystem(e, "drm");
> +	udev_enumerate_add_match_sysname(e, "card[0-9]*");
> +
> +	udev_enumerate_scan_devices(e);
> +	drm_device = NULL;
> +	udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
> +		path = udev_list_entry_get_name(entry);
> +		device = udev_device_new_from_syspath(ec->udev, path);
> +		if (!device)
> +			continue;
> +		device_seat = udev_device_get_property_value(device, "ID_SEAT");
> +		if (!device_seat)
> +			device_seat = default_seat;
> +		if (strcmp(device_seat, seat)) {
> +			udev_device_unref(device);
> +			continue;
> +		}
> +
> +		pci = udev_device_get_parent_with_subsystem_devtype(device,
> +								"pci", NULL);
> +		if (pci) {
> +			id = udev_device_get_sysattr_value(pci, "boot_vga");
> +			if (id && !strcmp(id, "1")) {
> +				if (drm_device)
> +					udev_device_unref(drm_device);
> +				drm_device = device;
> +				break;
> +			}
> +		}
> +
> +		if (!drm_device)
> +			drm_device = device;
> +		else
> +			udev_device_unref(device);
> +	}
> +
> +	udev_enumerate_unref(e);
> +	return drm_device;
> +}
> +
>  static struct weston_compositor *
>  drm_compositor_create(struct wl_display *display,
>  		      int connector, const char *seat, int tty,
>  		      int argc, char *argv[], const char *config_file)
>  {
>  	struct drm_compositor *ec;
> -	struct udev_enumerate *e;
> -	struct udev_list_entry *entry;
> -	struct udev_device *device, *drm_device;
> -	const char *path, *device_seat;
> +	struct udev_device *drm_device;
>  	struct wl_event_loop *loop;
>  	struct weston_seat *weston_seat, *next;
> +	const char *path;
>  	uint32_t key;
>  
>  	weston_log("initializing drm backend\n");
> @@ -2188,30 +2242,12 @@ drm_compositor_create(struct wl_display *display,
>  		goto err_udev;
>  	}
>  
> -	e = udev_enumerate_new(ec->udev);
> -	udev_enumerate_add_match_subsystem(e, "drm");
> -	udev_enumerate_add_match_sysname(e, "card[0-9]*");
> -
> -	udev_enumerate_scan_devices(e);
> -	drm_device = NULL;
> -	udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
> -		path = udev_list_entry_get_name(entry);
> -		device = udev_device_new_from_syspath(ec->udev, path);
> -		device_seat =
> -			udev_device_get_property_value(device, "ID_SEAT");
> -		if (!device_seat)
> -			device_seat = default_seat;
> -		if (strcmp(device_seat, seat) == 0) {
> -			drm_device = device;
> -			break;
> -		}
> -		udev_device_unref(device);
> -	}
> -
> +	drm_device = find_primary_gpu(ec, seat);
>  	if (drm_device == NULL) {
>  		weston_log("no drm device found\n");
> -		goto err_udev_enum;
> +		goto err_tty;
>  	}
> +	path = udev_device_get_syspath(drm_device);
>  
>  	if (init_egl(ec, drm_device) < 0) {
>  		weston_log("failed to initialize egl\n");
> @@ -2268,7 +2304,6 @@ drm_compositor_create(struct wl_display *display,
>  	}
>  
>  	udev_device_unref(drm_device);
> -	udev_enumerate_unref(e);
>  
>  	return &ec->base;
>  
> @@ -2289,8 +2324,7 @@ err_sprite:
>  	destroy_sprites(ec);
>  err_udev_dev:
>  	udev_device_unref(drm_device);
> -err_udev_enum:
> -	udev_enumerate_unref(e);
> +err_tty:
>  	tty_destroy(ec->tty);
>  err_udev:
>  	udev_unref(ec->udev);
> -- 
> 1.8.0
> 


More information about the wayland-devel mailing list