aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_dp_mst_topology.c
diff options
context:
space:
mode:
authorPandiyan, Dhinakaran <dhinakaran.pandiyan@intel.com>2017-04-21 01:51:31 -0400
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2017-05-04 09:02:46 -0400
commit3f3353b7e1218d208507bc52688cacb4ff893c28 (patch)
tree9b2a15c0805f4e384885afcc6d58e819580ed505 /drivers/gpu/drm/drm_dp_mst_topology.c
parentb430c27a7de3ccfb51b7e07b2dceba981df279ef (diff)
drm/dp: Introduce MST topology state to track available link bandwidth
Link bandwidth is shared between multiple display streams in DP MST configurations. The DP MST topology manager structure maintains the shared link bandwidth for a primary link directly connected to the GPU. For atomic modesetting drivers, checking if there is sufficient link bandwidth for a mode needs to be done during the atomic_check phase to avoid failed modesets. Let's encapsulate the available link bw information in a private state structure so that bw can be allocated and released atomically for each of the ports sharing the primary link. v3: WARN_ON() if connection_mutex is not held (Archit) v2: Included kernel doc, moved state initialization and switched to kmemdup() for allocation (Daniel) 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: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Harry Wentland <harry.wentland@amd.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-3-git-send-email-dhinakaran.pandiyan@intel.com
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index d3fc7e4e85b7..0ad0baae5c7e 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2936,6 +2936,69 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
2936 (*mgr->cbs->hotplug)(mgr); 2936 (*mgr->cbs->hotplug)(mgr);
2937} 2937}
2938 2938
2939void *drm_dp_mst_duplicate_state(struct drm_atomic_state *state, void *obj)
2940{
2941 struct drm_dp_mst_topology_mgr *mgr = obj;
2942 struct drm_dp_mst_topology_state *new_mst_state;
2943
2944 if (WARN_ON(!mgr->state))
2945 return NULL;
2946
2947 new_mst_state = kmemdup(mgr->state, sizeof(*new_mst_state), GFP_KERNEL);
2948 if (new_mst_state)
2949 new_mst_state->state = state;
2950 return new_mst_state;
2951}
2952
2953void drm_dp_mst_swap_state(void *obj, void **obj_state_ptr)
2954{
2955 struct drm_dp_mst_topology_mgr *mgr = obj;
2956 struct drm_dp_mst_topology_state **topology_state_ptr;
2957
2958 topology_state_ptr = (struct drm_dp_mst_topology_state **)obj_state_ptr;
2959
2960 mgr->state->state = (*topology_state_ptr)->state;
2961 swap(*topology_state_ptr, mgr->state);
2962 mgr->state->state = NULL;
2963}
2964
2965void drm_dp_mst_destroy_state(void *obj_state)
2966{
2967 kfree(obj_state);
2968}
2969
2970static const struct drm_private_state_funcs mst_state_funcs = {
2971 .duplicate_state = drm_dp_mst_duplicate_state,
2972 .swap_state = drm_dp_mst_swap_state,
2973 .destroy_state = drm_dp_mst_destroy_state,
2974};
2975
2976/**
2977 * drm_atomic_get_mst_topology_state: get MST topology state
2978 *
2979 * @state: global atomic state
2980 * @mgr: MST topology manager, also the private object in this case
2981 *
2982 * This function wraps drm_atomic_get_priv_obj_state() passing in the MST atomic
2983 * state vtable so that the private object state returned is that of a MST
2984 * topology object. Also, drm_atomic_get_private_obj_state() expects the caller
2985 * to care of the locking, so warn if don't hold the connection_mutex.
2986 *
2987 * RETURNS:
2988 *
2989 * The MST topology state or error pointer.
2990 */
2991struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
2992 struct drm_dp_mst_topology_mgr *mgr)
2993{
2994 struct drm_device *dev = mgr->dev;
2995
2996 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
2997 return drm_atomic_get_private_obj_state(state, mgr,
2998 &mst_state_funcs);
2999}
3000EXPORT_SYMBOL(drm_atomic_get_mst_topology_state);
3001
2939/** 3002/**
2940 * drm_dp_mst_topology_mgr_init - initialise a topology manager 3003 * drm_dp_mst_topology_mgr_init - initialise a topology manager
2941 * @mgr: manager struct to initialise 3004 * @mgr: manager struct to initialise
@@ -2980,6 +3043,15 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
2980 if (test_calc_pbn_mode() < 0) 3043 if (test_calc_pbn_mode() < 0)
2981 DRM_ERROR("MST PBN self-test failed\n"); 3044 DRM_ERROR("MST PBN self-test failed\n");
2982 3045
3046 mgr->state = kzalloc(sizeof(*mgr->state), GFP_KERNEL);
3047 if (mgr->state == NULL)
3048 return -ENOMEM;
3049 mgr->state->mgr = mgr;
3050
3051 /* max. time slots - one slot for MTP header */
3052 mgr->state->avail_slots = 63;
3053 mgr->funcs = &mst_state_funcs;
3054
2983 return 0; 3055 return 0;
2984} 3056}
2985EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init); 3057EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init);
@@ -3000,6 +3072,9 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
3000 mutex_unlock(&mgr->payload_lock); 3072 mutex_unlock(&mgr->payload_lock);
3001 mgr->dev = NULL; 3073 mgr->dev = NULL;
3002 mgr->aux = NULL; 3074 mgr->aux = NULL;
3075 kfree(mgr->state);
3076 mgr->state = NULL;
3077 mgr->funcs = NULL;
3003} 3078}
3004EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy); 3079EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy);
3005 3080