kms-device-impl: Implement leasing, revoking and listing leases

The lease_objects function takes connectors, CRTCs and planes which are
turned into a drm lease. The resulting lease can be revoked with
revoke_lease. With list_lessees the currently active leases can be
queried.

Co-authored-by: Sebastian Wick <sebastian.wick@redhat.com>
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3746>
This commit is contained in:
Jonas Ådahl
2022-01-03 17:24:12 +01:00
committed by Marge Bot
parent 498310ec7c
commit aaa8cefc25
4 changed files with 355 additions and 56 deletions

View File

@ -423,6 +423,145 @@ meta_kms_device_handle_flush (MetaKmsDevice *device,
return needs_flush;
}
typedef struct
{
MetaKmsDevice *device;
GList *connectors;
GList *crtcs;
GList *planes;
int fd;
uint32_t lessee_id;
} LeaseRequestData;
static gpointer
lease_objects_in_impl (MetaThreadImpl *thread_impl,
gpointer user_data,
GError **error)
{
LeaseRequestData *data = user_data;
MetaKmsImplDevice *impl_device =
meta_kms_device_get_impl_device (data->device);
uint32_t lessee_id;
int fd;
if (!meta_kms_impl_device_lease_objects (impl_device,
data->connectors,
data->crtcs,
data->planes,
&fd,
&lessee_id,
error))
return GINT_TO_POINTER (FALSE);
data->fd = fd;
data->lessee_id = lessee_id;
return GINT_TO_POINTER (TRUE);
}
gboolean
meta_kms_device_lease_objects (MetaKmsDevice *device,
GList *connectors,
GList *crtcs,
GList *planes,
int *out_fd,
uint32_t *out_lessee_id,
GError **error)
{
LeaseRequestData data = {};
data.device = device;
data.connectors = connectors;
data.crtcs = crtcs;
data.planes = planes;
if (!meta_kms_run_impl_task_sync (device->kms, lease_objects_in_impl, &data,
error))
return FALSE;
*out_fd = data.fd;
*out_lessee_id = data.lessee_id;
return TRUE;
}
typedef struct
{
MetaKmsDevice *device;
uint32_t lessee_id;
} RevokeLeaseData;
static gpointer
revoke_lease_in_impl (MetaThreadImpl *thread_impl,
gpointer user_data,
GError **error)
{
LeaseRequestData *data = user_data;
MetaKmsImplDevice *impl_device =
meta_kms_device_get_impl_device (data->device);
if (!meta_kms_impl_device_revoke_lease (impl_device, data->lessee_id, error))
return GINT_TO_POINTER (FALSE);
else
return GINT_TO_POINTER (TRUE);
}
gboolean
meta_kms_device_revoke_lease (MetaKmsDevice *device,
uint32_t lessee_id,
GError **error)
{
LeaseRequestData data = {};
data.device = device;
data.lessee_id = lessee_id;
return !!meta_kms_run_impl_task_sync (device->kms, revoke_lease_in_impl, &data,
error);
}
typedef struct
{
MetaKmsDevice *device;
uint32_t **out_lessee_ids;
int *out_num_lessee_ids;
} ListLesseesData;
static gpointer
list_lessees_in_impl (MetaThreadImpl *thread_impl,
gpointer user_data,
GError **error)
{
ListLesseesData *data = user_data;
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (data->device);
if (!meta_kms_impl_device_list_lessees (impl_device,
data->out_lessee_ids,
data->out_num_lessee_ids,
error))
return GINT_TO_POINTER (FALSE);
else
return GINT_TO_POINTER (TRUE);
}
gboolean
meta_kms_device_list_lessees (MetaKmsDevice *device,
uint32_t **out_lessee_ids,
int *out_num_lessee_ids,
GError **error)
{
ListLesseesData data = {};
data.device = device;
data.out_lessee_ids = out_lessee_ids;
data.out_num_lessee_ids = out_num_lessee_ids;
return !!meta_kms_run_impl_task_sync (device->kms,
list_lessees_in_impl,
&data,
error);
}
typedef struct _CreateImplDeviceData
{
MetaKmsDevice *device;

View File

@ -86,6 +86,23 @@ gboolean meta_kms_device_handle_flush (MetaKmsDevice *device,
META_EXPORT_TEST
void meta_kms_device_disable (MetaKmsDevice *device);
gboolean meta_kms_device_lease_objects (MetaKmsDevice *device,
GList *connectors,
GList *crtcs,
GList *planes,
int *out_fd,
uint32_t *out_lessee_id,
GError **error);
gboolean meta_kms_device_revoke_lease (MetaKmsDevice *device,
uint32_t lessee_id,
GError **error);
gboolean meta_kms_device_list_lessees (MetaKmsDevice *device,
uint32_t **out_lessee_ids,
int *out_num_lessee_ids,
GError **error);
MetaKmsDevice * meta_kms_device_new (MetaKms *kms,
const char *path,
MetaKmsDeviceFlag flags,

View File

@ -264,6 +264,188 @@ meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device)
return priv->path;
}
static MetaDeviceFile *
meta_kms_impl_device_open_device_file (MetaKmsImplDevice *impl_device,
const char *path,
GError **error)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
return klass->open_device_file (impl_device, priv->path, error);
}
static gpointer
kms_event_dispatch_in_impl (MetaThreadImpl *impl,
gpointer user_data,
GError **error)
{
MetaKmsImplDevice *impl_device = user_data;
gboolean ret;
ret = meta_kms_impl_device_dispatch (impl_device, error);
return GINT_TO_POINTER (ret);
}
static gboolean
ensure_device_file (MetaKmsImplDevice *impl_device,
GError **error)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
MetaDeviceFile *device_file;
if (priv->device_file)
return TRUE;
device_file = meta_kms_impl_device_open_device_file (impl_device,
priv->path,
error);
if (!device_file)
return FALSE;
priv->device_file = device_file;
if (!(priv->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING))
{
priv->fd_source =
meta_thread_impl_register_fd (META_THREAD_IMPL (priv->impl),
meta_device_file_get_fd (device_file),
kms_event_dispatch_in_impl,
impl_device);
g_source_set_priority (priv->fd_source, G_PRIORITY_HIGH);
}
return TRUE;
}
gboolean
meta_kms_impl_device_lease_objects (MetaKmsImplDevice *impl_device,
GList *connectors,
GList *crtcs,
GList *planes,
int *out_fd,
uint32_t *out_lessee_id,
GError **error)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
uint32_t *object_ids;
int n_object_ids;
GList *l;
int retval;
uint32_t lessee_id;
int i = 0;
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
if (!ensure_device_file (impl_device, error))
return FALSE;
meta_kms_impl_device_hold_fd (impl_device);
n_object_ids = (g_list_length (connectors) +
g_list_length (crtcs) +
g_list_length (planes));
object_ids = g_alloca (sizeof (uint32_t) * n_object_ids);
for (l = connectors; l; l = l->next)
{
MetaKmsConnector *connector = l->data;
object_ids[i++] = meta_kms_connector_get_id (connector);
}
for (l = crtcs; l; l = l->next)
{
MetaKmsCrtc *crtc = l->data;
object_ids[i++] = meta_kms_crtc_get_id (crtc);
}
for (l = planes; l; l = l->next)
{
MetaKmsPlane *plane = l->data;
object_ids[i++] = meta_kms_plane_get_id (plane);
}
retval = drmModeCreateLease (meta_kms_impl_device_get_fd (impl_device),
object_ids, n_object_ids, 0,
&lessee_id);
if (retval < 0)
{
meta_kms_impl_device_unhold_fd (impl_device);
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-retval),
"Failed to create lease: %s", g_strerror (-retval));
return FALSE;
}
*out_fd = retval;
*out_lessee_id = lessee_id;
return TRUE;
}
gboolean
meta_kms_impl_device_revoke_lease (MetaKmsImplDevice *impl_device,
uint32_t lessee_id,
GError **error)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
int retval;
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
retval = drmModeRevokeLease (meta_kms_impl_device_get_fd (impl_device),
lessee_id);
meta_kms_impl_device_unhold_fd (impl_device);
if (retval != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-retval),
"Failed to revoke lease: %s", g_strerror (-retval));
return FALSE;
}
return TRUE;
}
gboolean
meta_kms_impl_device_list_lessees (MetaKmsImplDevice *impl_device,
uint32_t **out_lessee_ids,
int *out_num_lessee_ids,
GError **error)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
drmModeLesseeListRes *list;
int i;
uint32_t *lessee_ids;
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
list = drmModeListLessees (meta_kms_impl_device_get_fd (impl_device));
if (!list)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to list lessees");
return FALSE;
}
lessee_ids = g_new0 (uint32_t, list->count);
for (i = 0; i < list->count; i++)
lessee_ids[i] = list->lessees[i];
*out_lessee_ids = lessee_ids;
*out_num_lessee_ids = list->count;
return TRUE;
}
gboolean
meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device,
GError **error)
@ -314,18 +496,6 @@ meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device,
return TRUE;
}
static gpointer
kms_event_dispatch_in_impl (MetaThreadImpl *impl,
gpointer user_data,
GError **error)
{
MetaKmsImplDevice *impl_device = user_data;
gboolean ret;
ret = meta_kms_impl_device_dispatch (impl_device, error);
return GINT_TO_POINTER (ret);
}
drmModePropertyPtr
meta_kms_impl_device_find_property (MetaKmsImplDevice *impl_device,
drmModeObjectProperties *props,
@ -890,50 +1060,6 @@ init_fallback_modes (MetaKmsImplDevice *impl_device)
priv->fallback_modes = g_list_reverse (modes);
}
static MetaDeviceFile *
meta_kms_impl_device_open_device_file (MetaKmsImplDevice *impl_device,
const char *path,
GError **error)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
return klass->open_device_file (impl_device, priv->path, error);
}
static gboolean
ensure_device_file (MetaKmsImplDevice *impl_device,
GError **error)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
MetaDeviceFile *device_file;
if (priv->device_file)
return TRUE;
device_file = meta_kms_impl_device_open_device_file (impl_device,
priv->path,
error);
if (!device_file)
return FALSE;
priv->device_file = device_file;
if (!(priv->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING))
{
priv->fd_source =
meta_thread_impl_register_fd (META_THREAD_IMPL (priv->impl),
meta_device_file_get_fd (device_file),
kms_event_dispatch_in_impl,
impl_device);
g_source_set_priority (priv->fd_source, G_PRIORITY_HIGH);
}
return TRUE;
}
static void
ensure_latched_fd_hold (MetaKmsImplDevice *impl_device)
{

View File

@ -132,6 +132,23 @@ const char * meta_kms_impl_device_get_driver_description (MetaKmsImplDevice *imp
const char * meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device);
gboolean meta_kms_impl_device_lease_objects (MetaKmsImplDevice *impl_device,
GList *connectors,
GList *crtcs,
GList *planes,
int *out_fd,
uint32_t *out_lessee_id,
GError **error);
gboolean meta_kms_impl_device_revoke_lease (MetaKmsImplDevice *impl_device,
uint32_t lessee_id,
GError **error);
gboolean meta_kms_impl_device_list_lessees (MetaKmsImplDevice *impl_device,
uint32_t **out_lessee_ids,
int *out_num_lessee_ids,
GError **error);
gboolean meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device,
GError **error);