Multi connector lease support 70/27270/2
authorDamian Hobson-Garcia <dhobsong@igel.co.jp>
Tue, 15 Mar 2022 07:46:49 +0000 (16:46 +0900)
committerDamian Hobson-Garcia <dhobsong@igel.co.jp>
Fri, 25 Mar 2022 07:33:36 +0000 (16:33 +0900)
Add support for having multiple connectors / CTRCs in a single lease.
The lease manager receives a list of lease configurations that
specify the name and list of connectors to include in each lease.

All DRM planes that are not shared between muliple CRTS are added
for each connector contained in the lease.

If the lease manager is initialized without a list of lease
configurations it will fall back to the previous 1 connector
per lease configuration.

Bug-AGL: SPEC-3815

Change-Id: I6699e7c8f426bab9fadbc64fe4ed242a834376bf
Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
drm-lease-manager/drm-lease.h
drm-lease-manager/lease-manager.c
drm-lease-manager/lease-manager.h

index a855054..223c347 100644 (file)
 
 #ifndef DRM_LEASE_H
 #define DRM_LEASE_H
+#include <stdint.h>
 
 struct lease_handle {
        char *name;
        void *user_data;
 };
+
+struct lease_config {
+       char *lease_name;
+
+       int ncids;
+       uint32_t *connector_ids;
+};
+
 #endif
index 5eeef16..9627f0d 100644 (file)
@@ -34,9 +34,9 @@
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 
-/* Number of resources, excluding planes, to be included in each DRM lease.
- * Each lease needs at least a CRTC and conector. */
-#define DRM_LEASE_MIN_RES (2)
+/* Number of resources, to be included in a DRM lease for each connector.
+ * Each connector needs both a CRTC and conector object:. */
+#define DRM_OBJECTS_PER_CONNECTOR (2)
 
 #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
 
@@ -90,7 +90,8 @@ static const char *const connector_type_names[] = {
     [DRM_MODE_CONNECTOR_WRITEBACK] = "Writeback",
 };
 
-static char *drm_create_lease_name(struct lm *lm, drmModeConnectorPtr connector)
+static char *drm_create_default_lease_name(struct lm *lm,
+                                          drmModeConnectorPtr connector)
 {
        uint32_t type = connector->connector_type;
        uint32_t id = connector->connector_type_id;
@@ -294,42 +295,67 @@ static void lease_free(struct lease *lease)
        free(lease);
 }
 
-static struct lease *lease_create(struct lm *lm, drmModeConnectorPtr connector)
+static struct lease *lease_create(struct lm *lm,
+                                 const struct lease_config *config)
 {
-       struct lease *lease = calloc(1, sizeof(struct lease));
+       struct lease *lease;
+
+       if (!config->lease_name) {
+               ERROR_LOG("Mising lease name\n");
+               return NULL;
+       }
+
+       lease = calloc(1, sizeof(struct lease));
        if (!lease) {
                DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno));
                return NULL;
        }
 
-       lease->base.name = drm_create_lease_name(lm, connector);
+       lease->base.name = strdup(config->lease_name);
        if (!lease->base.name) {
                DEBUG_LOG("Can't create lease name: %s\n", strerror(errno));
                goto err;
        }
 
-       int nobjects = lm->drm_plane_resource->count_planes + DRM_LEASE_MIN_RES;
+       int nobjects = lm->drm_plane_resource->count_planes +
+                      config->ncids * DRM_OBJECTS_PER_CONNECTOR;
+
        lease->object_ids = calloc(nobjects, sizeof(uint32_t));
        if (!lease->object_ids) {
                DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno));
                goto err;
        }
 
-       int crtc_index = drm_get_crtc_index(lm, connector);
-       if (crtc_index < 0) {
-               DEBUG_LOG("No crtc found for connector: %s\n",
-                         lease->base.name);
-               goto err;
-       }
+       for (int i = 0; i < config->ncids; i++) {
+               drmModeConnectorPtr connector =
+                   drmModeGetConnector(lm->drm_fd, config->connector_ids[i]);
 
-       if (!lease_add_planes(lm, lease, crtc_index))
-               goto err;
+               if (connector == NULL) {
+                       ERROR_LOG("Can't find connector id: %d\n",
+                                 config->connector_ids);
+                       goto err;
+               }
+
+               uint32_t connector_id = connector->connector_id;
+
+               int crtc_index = drm_get_crtc_index(lm, connector);
+
+               drmModeFreeConnector(connector);
 
-       uint32_t crtc_id = lm->drm_resource->crtcs[crtc_index];
-       lease->crtc_id = crtc_id;
-       lease->object_ids[lease->nobject_ids++] = crtc_id;
-       lease->object_ids[lease->nobject_ids++] = connector->connector_id;
+               if (crtc_index < 0) {
+                       DEBUG_LOG("No crtc found for connector: %d, lease %s\n",
+                                 connector_id, lease->base.name);
+                       goto err;
+               }
+
+               if (!lease_add_planes(lm, lease, crtc_index))
+                       goto err;
 
+               uint32_t crtc_id = lm->drm_resource->crtcs[crtc_index];
+               lease->crtc_id = crtc_id;
+               lease->object_ids[lease->nobject_ids++] = crtc_id;
+               lease->object_ids[lease->nobject_ids++] = connector_id;
+       }
        lease->is_granted = false;
        lease->lease_fd = -1;
 
@@ -340,7 +366,69 @@ err:
        return NULL;
 }
 
-struct lm *lm_create(const char *device)
+static void destroy_default_lease_configs(int num_configs,
+                                         struct lease_config *configs)
+{
+       for (int i = 0; i < num_configs; i++) {
+               free(configs[i].connector_ids);
+               free(configs[i].lease_name);
+       }
+
+       free(configs);
+}
+
+static int create_default_lease_configs(struct lm *lm,
+                                       struct lease_config **configs)
+{
+       struct lease_config *def_configs;
+       int num_configs = lm->drm_resource->count_connectors;
+
+       if (num_configs < 0)
+               return -1;
+
+       def_configs = calloc(num_configs, sizeof(*def_configs));
+       if (!def_configs) {
+               DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno));
+               return -1;
+       }
+
+       for (int i = 0; i < num_configs; i++) {
+               uint32_t cid = lm->drm_resource->connectors[i];
+
+               def_configs[i].connector_ids = malloc(sizeof(uint32_t));
+               if (!def_configs[i].connector_ids) {
+                       DEBUG_LOG("Memory allocation failed: %s\n",
+                                 strerror(errno));
+                       goto err;
+               }
+
+               drmModeConnectorPtr connector;
+               connector = drmModeGetConnector(lm->drm_fd, cid);
+               def_configs[i].lease_name =
+                   drm_create_default_lease_name(lm, connector);
+
+               if (!def_configs[i].lease_name) {
+                       DEBUG_LOG(
+                           "Can't create lease name for connector %d: %s\n",
+                           cid, strerror(errno));
+                       goto err;
+               }
+
+               drmModeFreeConnector(connector);
+
+               def_configs[i].connector_ids[0] = cid;
+               def_configs[i].ncids = 1;
+       }
+
+       *configs = def_configs;
+       return num_configs;
+
+err:
+       destroy_default_lease_configs(num_configs, def_configs);
+       return -1;
+}
+
+static struct lm *drm_device_get_resources(const char *device)
 {
        struct lm *lm = calloc(1, sizeof(struct lm));
        if (!lm) {
@@ -376,27 +464,25 @@ struct lm *lm_create(const char *device)
 
        lm->dev_id = st.st_rdev;
 
-       int num_leases = lm->drm_resource->count_connectors;
+       return lm;
+err:
+       lm_destroy(lm);
+       return NULL;
+}
 
+static int lm_create_leases(struct lm *lm, int num_leases,
+                           const struct lease_config *configs)
+{
        lm->leases = calloc(num_leases, sizeof(struct lease *));
        if (!lm->leases) {
                DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno));
-               goto err;
+               return -1;
        }
 
        drm_find_available_crtcs(lm);
 
        for (int i = 0; i < num_leases; i++) {
-               uint32_t connector_id = lm->drm_resource->connectors[i];
-               drmModeConnectorPtr connector =
-                   drmModeGetConnector(lm->drm_fd, connector_id);
-
-               if (!connector)
-                       continue;
-
-               struct lease *lease = lease_create(lm, connector);
-               drmModeFreeConnector(connector);
-
+               struct lease *lease = lease_create(lm, &configs[i]);
                if (!lease)
                        continue;
 
@@ -404,13 +490,43 @@ struct lm *lm_create(const char *device)
                lm->nleases++;
        }
        if (lm->nleases == 0)
-               goto err;
+               return -1;
+
+       return 0;
+}
+
+struct lm *lm_create_with_config(const char *device, int num_leases,
+                                struct lease_config *configs)
+{
+       struct lease_config *default_configs = NULL;
+       struct lm *lm = drm_device_get_resources(device);
+
+       if (!lm)
+               return NULL;
+
+       if (configs == NULL) {
+               num_leases = create_default_lease_configs(lm, &default_configs);
+               if (num_leases < 0) {
+                       lm_destroy(lm);
+                       ERROR_LOG("DRM connector enumeration failed\n");
+                       return NULL;
+               }
+               configs = default_configs;
+       }
 
+       if (lm_create_leases(lm, num_leases, configs) < 0) {
+               lm_destroy(lm);
+               lm = NULL;
+       }
+
+       if (default_configs)
+               destroy_default_lease_configs(num_leases, default_configs);
        return lm;
+}
 
-err:
-       lm_destroy(lm);
-       return NULL;
+struct lm *lm_create(const char *device)
+{
+       return lm_create_with_config(device, 0, NULL);
 }
 
 void lm_destroy(struct lm *lm)
index 55bf81e..d13ca43 100644 (file)
@@ -20,6 +20,9 @@
 struct lm;
 
 struct lm *lm_create(const char *path);
+struct lm *lm_create_with_config(const char *path, int leases,
+                                struct lease_config *configs);
+
 void lm_destroy(struct lm *lm);
 
 int lm_get_lease_handles(struct lm *lm, struct lease_handle ***lease_handles);