drm/dp: Add DP MST helpers to atomically find and release vcpi slots
authorPandiyan, Dhinakaran <dhinakaran.pandiyan@intel.com>
Fri, 21 Apr 2017 05:51:32 +0000 (22:51 -0700)
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Thu, 4 May 2017 13:02:47 +0000 (15:02 +0200)
drm_dp_atomic_find_vcpi_slots() should be called from ->atomic_check() to
check there are sufficient vcpi slots for a mode and to add that to the
state. This should be followed by a call to drm_dp_mst_allocate_vcpi()
in ->atomic_commit() to initialize a struct vcpi for the port.

drm_dp_atomic_release_vcpi_slots() should be called from
->atomic_check() to release a port's vcpi slot allocation from the
state.

Drivers that do not make use of this atomic helper are expected to call
drm_dp_find_vcpi_slots() instead before calling
drm_dp_mst_allocate_vcpi().

v3: drm_dp_atomic_release_vcpi_slots() now needs to know how many slots
    to release as we may not have a valid reference to port.
v2:
Added checks for verifying the port reference is valid
Moved get_mst_topology_state() into the helpers (Daniel)
Changed find_vcpi_slots() to not depend on current allocation

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Archit Taneja <architt@codeaurora.org>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Harry Wentland <Harry.wentland@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1492753893-3748-4-git-send-email-dhinakaran.pandiyan@intel.com
drivers/gpu/drm/drm_dp_mst_topology.c
include/drm/drm_dp_mst_helper.h

index 0ad0baae5c7ef2c3e64b21dfdb75909f2676cbee..d1cbb9c8f806761d9c0879e8a13bf0ad57c2f6ad 100644 (file)
@@ -2497,6 +2497,81 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
        return 0;
 }
 
+/**
+ * drm_dp_atomic_find_vcpi_slots() - Find and add vcpi slots to the state
+ * @state: global atomic state
+ * @mgr: MST topology manager for the port
+ * @port: port to find vcpi slots for
+ * @pbn: bandwidth required for the mode in PBN
+ *
+ * RETURNS:
+ * Total slots in the atomic state assigned for this port or error
+ */
+int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
+                                 struct drm_dp_mst_topology_mgr *mgr,
+                                 struct drm_dp_mst_port *port, int pbn)
+{
+       struct drm_dp_mst_topology_state *topology_state;
+       int req_slots;
+
+       topology_state = drm_atomic_get_mst_topology_state(state, mgr);
+       if (topology_state == NULL)
+               return -ENOMEM;
+
+       port = drm_dp_get_validated_port_ref(mgr, port);
+       if (port == NULL)
+               return -EINVAL;
+       req_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
+       DRM_DEBUG_KMS("vcpi slots req=%d, avail=%d\n",
+                       req_slots, topology_state->avail_slots);
+
+       if (req_slots > topology_state->avail_slots) {
+               drm_dp_put_port(port);
+               return -ENOSPC;
+       }
+
+       topology_state->avail_slots -= req_slots;
+       DRM_DEBUG_KMS("vcpi slots avail=%d", topology_state->avail_slots);
+
+       drm_dp_put_port(port);
+       return req_slots;
+}
+EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots);
+
+/**
+ * drm_dp_atomic_release_vcpi_slots() - Release allocated vcpi slots
+ * @state: global atomic state
+ * @mgr: MST topology manager for the port
+ * @slots: number of vcpi slots to release
+ *
+ * RETURNS:
+ * 0 if @slots were added back to &drm_dp_mst_topology_state->avail_slots or
+ * negative error code
+ */
+int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
+                                    struct drm_dp_mst_topology_mgr *mgr,
+                                    int slots)
+{
+       struct drm_dp_mst_topology_state *topology_state;
+
+       topology_state = drm_atomic_get_mst_topology_state(state, mgr);
+       if (topology_state == NULL)
+               return -ENOMEM;
+
+       /* We cannot rely on port->vcpi.num_slots to update
+        * topology_state->avail_slots as the port may not exist if the parent
+        * branch device was unplugged. This should be fixed by tracking
+        * per-port slot allocation in drm_dp_mst_topology_state instead of
+        * depending on the caller to tell us how many slots to release.
+        */
+       topology_state->avail_slots += slots;
+       DRM_DEBUG_KMS("vcpi slots released=%d, avail=%d\n",
+                       slots, topology_state->avail_slots);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_dp_atomic_release_vcpi_slots);
+
 /**
  * drm_dp_mst_allocate_vcpi() - Allocate a virtual channel
  * @mgr: manager for this port
index 0b371dffed000bf66c19031bebcb0df604104d43..177ab6f868554c23169c654b7c97545ecf77de14 100644 (file)
@@ -615,5 +615,11 @@ void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
 int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
                                                                    struct drm_dp_mst_topology_mgr *mgr);
+int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
+                                 struct drm_dp_mst_topology_mgr *mgr,
+                                 struct drm_dp_mst_port *port, int pbn);
+int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
+                                    struct drm_dp_mst_topology_mgr *mgr,
+                                    int slots);
 
 #endif