[Intel-gfx] [PATCH 4/6] drm/dp: Introduce DP MST topology manager state to track DP link bw

Daniel Vetter daniel at ffwll.ch
Wed Jan 11 08:08:08 UTC 2017


On Sat, Jan 07, 2017 at 12:35:36AM +0000, Pandiyan, Dhinakaran wrote:
> On Thu, 2017-01-05 at 09:24 +0100, Daniel Vetter wrote:
> > On Thu, Jan 05, 2017 at 03:54:54AM +0000, Pandiyan, Dhinakaran wrote:
> > > On Wed, 2017-01-04 at 19:20 +0000, Pandiyan, Dhinakaran wrote:
> > > > On Wed, 2017-01-04 at 10:33 +0100, Daniel Vetter wrote:
> > > > > On Tue, Jan 03, 2017 at 01:01:49PM -0800, Dhinakaran Pandiyan wrote:
> > > > > > 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 encsapsulate the available link bw information in a state
> > > > > > structure so that bw can be allocated and released atomically for each of
> > > > > > the ports sharing the primary link.
> > > > > > 
> > > > > > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan at intel.com>
> > > > > 
> > > > > Overall issue with the patch is that dp helpers now have 2 places where
> > > > > available_slots is stored: One for atomic drivers in ->state, and the
> > > > > legacy one. I think it'd be good to rework the legacy codepaths (i.e.
> > > > > drm_dp_find_vcpi_slots) to use mgr->state->avail_slots, and remove
> > > > > mgr->avail_slots entirely.
> > > > 
> > > > PATCH 2/6 does that. mgr->avail_slots is not updated in the legacy code
> > > > path, so the check turns out to be against mgr->total_slots. So, I did
> > > > just that, albeit explicitly. 
> > 
> > Ah right, I missed that.
> > 
> > > > > > diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
> > > > > > index fd2d971..7ac5ed6 100644
> > > > > > --- a/include/drm/drm_atomic.h
> > > > > > +++ b/include/drm/drm_atomic.h
> > > > > > @@ -153,6 +153,11 @@ struct __drm_connnectors_state {
> > > > > >  	struct drm_connector_state *state;
> > > > > >  };
> > > > > >  
> > > > > > +struct __drm_dp_mst_topology_state {
> > > > > > +	struct drm_dp_mst_topology_mgr *ptr;
> > > > > > +	struct drm_dp_mst_topology_state *state;
> > > > > 
> > > > > One way to fix that control inversion I mentioned above is to use void*
> > > > > pionters here, and then have callbacks for atomic_destroy and swap_state
> > > > > on top. A bit more shuffling, but we could then use that for other driver
> > > > > private objects.
> > > > > 
> > > > > Other option is to stuff it into intel_atomic_state.
> > > 
> > > Hmm... I think I understand what you are saying. The core atomic
> > > functions like swap_state should not be able alter the topology
> > > manager's current state?
> > > 
> > > Did you mean something like this - https://paste.ubuntu.com/23743485/ ?
> > 
> > Not quite yet, here's what I had in mind as a sketch:
> > 
> > diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
> > index 2e28fdca9c3d..6ce704b1e900 100644
> > --- a/include/drm/drm_atomic.h
> > +++ b/include/drm/drm_atomic.h
> > @@ -154,6 +154,17 @@ struct __drm_connnectors_state {
> >  	struct drm_connector_state *state;
> >  };
> >  
> > +struct drm_private_state_funcs {
> > +	void (*swap)(void *obj, void *state);
> > +	void (*destroy_state)(void *state);
> > +};
> > +
> > +struct __drm_private_obj_state {
> > +	struct obj *ptr;
> > +	struct obj_state *state;
> 
> Thanks for the sketch Daniel, I have a couple of questions.
> Should this be void *obj and void *obj_state? 

Yes :-)

> 
> > +	struct drm_private_state_funcs *funcs;
> > +}
> > +
> >  /**
> >   * struct drm_atomic_state - the global state object for atomic updates
> >   * @ref: count of all references to this state (will not be freed until zero)
> > @@ -178,6 +189,8 @@ struct drm_atomic_state {
> >  	struct __drm_crtcs_state *crtcs;
> >  	int num_connector;
> >  	struct __drm_connnectors_state *connectors;
> > +	int num_private_objs;
> > +	struct __drm_private_obj_state *private_objs;
> >  
> >  	struct drm_modeset_acquire_ctx *acquire_ctx;
> >  
> > @@ -414,6 +427,19 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
> >  	     (__i)++)							\
> >  		for_each_if (plane_state)
> >  
> > +/* The magic here is that if obj and obj_state have the right type, then this
> > + * will automatically cast to the right type. Since we allow any kind of private
> > + * object mixed into the same array, runtime type casting is done using the
> > + * funcs pointer.
> > + */
> > +#define for_each_private_obj(__state, obj, obj_state, __i, funcs)
> > +	for ((__i) = 0;							\
> > +	     (__i) < (__state)->num_private_objs &&				\
> > +	     ((obj) = (__state)->private_objs[__i].ptr,			\
> > +	     (obj_state) = (__state)->private_objs[__i].state, 1); 	\
> > +	     (__i)++)							\
> > +		for_each_if ((__state)->private_objs[__i].funcs == (funcs))
> > +
> 
> So, this macro iterates through a specific type of private obj in the
> array. You are not implying that drm_atomic_helper_swap_state is
> expected to use this, right? If we don't do
> "((__state)->private_objs[__i].funcs == (funcs))", we could swap the
> state for all private objs.

Yes, swap state should go through all of them and not filter for a
specific funcs. Probably best to have an internal/dangerous version with

#define __drm_for_each_private_obj(__state, obj, obj_state, __i, __funcs)
	for ((__i) = 0;							\
	     (__i) < (__state)->num_private_objs &&			\
	     ((obj) = (__state)->private_objs[__i].ptr,			\
	     (__funcs) =	(__state)->private_objs[__i].funcs,	\
	     (obj_state) = (__state)->private_objs[__i].state, 1); 	\
	     (__i)++)							\
		for_each_if (__funcs)

i.e. instead of filtering for funcs, assign the provided funcs pointer.
Then swap_states and the cleanup functions could use that.


> 
> 
> 
> >  /**
> >   * drm_atomic_crtc_needs_modeset - compute combined modeset need
> >   * @state: &drm_crtc_state for the CRTC
> > 
> > I didn't sketch helper functions for looking up/inserting objects, and ofc
> > we'd need the boilerplat for cleanup/swap, but I hope that part is clear.
> > 
> > If we add a duplicate_state callback to drm_private_state_funcs then we
> > might even be able to abstract away the entire lookup-or-dupliocate logic
> > into a helper, and all that's left for a specific implementation would be
> > 
> > struct drm_dp_mst_topology_state*
> > drm_dp_mst_get_atomic_state(struct drm_atomic_state *state,
> > 			    struct dp_mst_topology_mgr *mgr)
> > {
> > 	return drm_atomic_get_private_state(state, mgr, mgr->state,
> > 					    &dp_mst_state_funcs);
> > }
> > 
> 
> I like this idea, except for the part we have to do a linear search for
> lookups.

That's not an issue, since there's very few objects. And if it ever
becomes an issue, we can easily add a hashtable or something for the void
* -> entry lookup to speed it up.

But a good thing to note, please add a comment to the commit message.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the Intel-gfx mailing list