From edb1ed1ab7d314e114de84003f763da34c0f34c0 Mon Sep 17 00:00:00 2001 From: "Pandiyan, Dhinakaran" Date: Thu, 20 Apr 2017 22:51:32 -0700 Subject: [PATCH] drm/dp: Add DP MST helpers to atomically find and release vcpi slots 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 Cc: Maarten Lankhorst Cc: Archit Taneja Cc: Chris Wilson Cc: Harry Wentland Reviewed-by: Harry Wentland Reviewed-by: Maarten Lankhorst Signed-off-by: Dhinakaran Pandiyan Signed-off-by: Maarten Lankhorst 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 | 75 +++++++++++++++++++++++++++ include/drm/drm_dp_mst_helper.h | 6 +++ 2 files changed, 81 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 0ad0baae5c7e..d1cbb9c8f806 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -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 diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 0b371dffed00..177ab6f86855 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -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 -- 2.20.1