[PATCH 00/17] prepare for atomic/nuclear modeset/pageflip
Daniel Vetter
daniel at ffwll.ch
Mon May 26 10:36:37 PDT 2014
On Mon, May 26, 2014 at 6:12 PM, Rob Clark <robdclark at gmail.com> wrote:
> On Mon, May 26, 2014 at 11:24 AM, Daniel Vetter <daniel at ffwll.ch> wrote:
>> On Mon, May 26, 2014 at 08:48:52AM -0400, Rob Clark wrote:
>>> On Mon, May 26, 2014 at 6:40 AM, Daniel Vetter <daniel at ffwll.ch> wrote:
>>> > On Sat, May 24, 2014 at 02:30:09PM -0400, Rob Clark wrote:
>>> >> One more time, with feeling..
>>> >>
>>> >> Previous revision of series:
>>> >> http://lists.freedesktop.org/archives/dri-devel/2014-March/055806.html
>>> >>
>>> >> And if you prefer, in git form:
>>> >> http://cgit.freedesktop.org/~robclark/linux/log/?h=cold-fusion
>>> >> git://people.freedesktop.org/~robclark/linux cold-fusion
>>> >>
>>> >> This series does not include the actual atomic ioctl, but it does
>>> >> include all the needed infrastructure changes.
>>> >>
>>> >> Compared to previous revision, I've split out drm_modeset_acquire_ctx
>>> >> from drm_atomic_state, so that we can ww acquire mode_config and crtc
>>> >> locks outside of atomic transactions. (Which keeps lockdep happy wrt.
>>> >> drm_modeset_lock_all().) I also got to the point in juggling things
>>> >> around where I wanted to let the compiler type checking do it's job,
>>> >> so 's/void *state/struct drm_atomic_state *state/g'.
>>> >>
>>> >> At this point, I've tested this on i915 (few different generation
>>> >> laptops), radeon, and msm. And of course w/ ww debug (deadlock in-
>>> >> jection) enabled. So I think all the locking related paths should
>>> >> be covered.
>>> >>
>>> >> I believe Thierry has tested a slighly older revision on tegra. I
>>> >> would of course appreciate more testing on other drivers for which I
>>> >> don't have the hw. But I think it is pretty much ready to go. I do
>>> >> still owe some docs updates, I will send some patches for that in
>>> >> the near future, but didn't want to hold up giving others a chance
>>> >> to start banging on this.
>>> >
>>> > Ok, I've done a fairly cursory look at this only and tried to concentrate
>>> > on grasping the high-level details. Patches contain a bunch of comments on
>>> > the details, but here is the big stuff.
>>> >
>>> > First things first there's a bunch of prep work and refactoring sprinkled
>>> > throughout the series. Imo we should pick those out and rebase them on top
>>> > of drm-next asap to get them in before the actual interfaces. I hope I've
>>> > catched them all and commented everywhere about what imo is still missing
>>> > for merging. With that out of the way the real atomic review below.
>>> >
>>> > I like the overall design. It will be a royal pain to convert i915 over to
>>> > this since thus far we've simply tucked away the staged state into
>>> > obj->new_foo pointers. Which means we get to change the entire driver
>>> > again ;-)
>>> >
>>> > But I think the interfaces to driver and overall api design need some good
>>> > polish:
>>> >
>>> > - Imo way too much is done in driver callbacks, which then again call
>>> > helpers. Parsing of the core properties for plane/crtcs should be done
>>> > in the core imo. This way drivers only need to register ->set_prop
>>> > callbacks if there's a driver-specific property they support.
>>>
>>> Pretty universally, the approach I took was to provide default fxns
>>> (for ->atomic_xyz(), ->set_property(), ->create_state(), etc), and let
>>> drivers wrap them as needed. We might need to tweak
>>> drm_atomic_begin() a bit for the first driver that needs to wrap
>>> drm_atomic_state, but I guess we can tackle that as the need arises.
>>>
>>> > - Imo those obj->set_prop callbacks should take the object-specific
>>> > drm_obj_state object, not the global atomic state structure. Will lead
>>> > to _much_ less lookup code duplicated all over the place. If we then
>>> > also add a state->obj pointer we could also ditch that parameter. Ofc
>>> > obj would be specific to the state at hand.
>>>
>>> The problem is if those callbacks need to take other driver shared
>>> locks.. that plus initially I was trying to keep state as opaque as
>>> possible (in case sooner or later i915 decided to re-implement :-P)
>>>
>>> Eventually I decided keeping state opaque was too much pita, and that
>>> if driver wanted to do something different, it should instead
>>> subclass. So I guess these days they could chase [pc]state->state to
>>> get back at the global state.
>>
>> I don't think keeping state opaque is a feature. Imo we _want_ to have
>> some common structures to track the common set of properties, for
>> otherwise insanity will rule. Drivers can add whatever they whish by
>> subclassing the existing state structs and add whatever they need to track
>> their state. I don't have any intentions to implement something
>> newfangled/different for i915, but instead want to port our current
>> infrastructure over to this.
>>
>> Having clear prepare&check (we call it compute) and commit semantics is
>> imo the right way to do kms. Think of i915 as the poc vehicle that gets to
>> pay the bill of rewriting the driver twice.
>>
>> So I'm advocating to move even further avoid from void* everywhere than
>> you've moved already.
>>
>> Wrt helpers I think at least for modeset operations we can pimp the crtc
>> helpers and mostly reuse the hooks we already have, maybe augmented with
>> per-object ->check hooks. But for nuclear pageflips I really don't see a
>> chance but a single driver-gloabl ->commit (and fwiw check) hook. Maybe
>> per-crtc at best, but that will already run into planes changing crtcs.
>
> The per-object hooks will work with at least three display controller
> blocks that I know of (two in msm, and omapdrm), so I guess it is not
> *that* uncommon.
>
> We'll need to split up an existing fxn or two so that other drivers
> can do an all-at-once commit more easily. That seems like a fairly
> small tweak, and I think it would be ok to merge along w/ i915 atomic
> support.
I'm working on a reply to your msm patch. I think it's better we'll
move that discussion over there, where we have more context with
actual code.
>>> > - One downside of that is that drivers won't be able to interfere the
>>> > allocation step any more. I think we'd need an additional
>>> > ->alloc_atomic_state call so that drivers can still easily subclass some
>>> > objects with their own type.
>>>
>>> the ->create_state() is already split out as a vfunc for planes and
>>> crtcs. Which I think should be enough to cover most of what drivers
>>> need. If driver needs to subclass global state too, then we need to
>>> split up drm_atomic_begin(), but I guess that should be a relatively
>>> small change that we can make when it becomes needed.
>>
>> I guess i915 will need it, to keep track of shared resources like plls.
>> Atm we carry them around in dev_priv, without any precompute/commit
>> semantics. Still something that needs to be fixed ...
>
> it would seem tempting to put in i915_atomic_state, but then how does
> it work with multiple parallel but independent atomic updates, or
> should that not be allowed?
Once we've entered the check/commit hooks all locks should have been
acquired (or will get acquired at the beginning of the check hook), so
there's no bothersome parallelism I think. Wrt the i915 implementation
I think the approach I'll try is:
1. In the set_prop stage _only_ store data in the <obj>_state
structures and nowhere else, not touching any data reachable from a
2nd thread.
2. In the check hook put all the state into <obj>->new_state pointers.
At that point we hold all the locks so can do that.
3. Run the ->compute_config hooks over all relevant objects. We need
to change all the code from directly looking into its object's
structure to go through the new_state indirection (e.g. for figuring
out whether we should enable hdmi audio or similar stuff).
4. Bail out and undo al new_foo pointer changes when only checking,
run the full hw commit code when doing a real atomic update.
That approach should hug the current implementation closely wrt the
->new_foo handling, but still tightly integrate with the free-floating
state construction atomic wants. The conversion will not be pretty
though :(
>> Wrt ->create_state: I simply missed that in all the patches. But if you
>> have that I don't quite understand why the various ->set_property
>> callbacks have checks whether the object-specific state exists already and
>> allocate it if not through the get_plane_state and similar functions. Imo
>> that kind of stuff should be handled in the core. Error handling code is
>> really hard to get correct ime, and we depend upon it's correctness here
>> (at least with the current locking scheme) for ww mutexes to work.
>
> Well, the current approach gave the driver more flexibility about what
> locks to grab, etc.. although I suppose some of this might be less
> needed now with primary planes. Formerly I had to fwd some properties
> from crtc to my own internal primary plane, which required the
> flexibility that the current approach gives.
I think if there's any private ww mutex locks drivers need to acquire,
they should do that in their check/commit hook. Not while parsing
properties. From that point on it's all under the control of the
driver, so might not even need a full ww mutex, but a plain lock that
nests within all the kms ww mutexes might be good enough.
>>> > - There's imo a bit a confusion between what's helper and what's driver
>>> > api. My big gripe here is with the set_prop stuff which imo really
>>> > should be core and not helpers. The default ->commit/check
>>> > implementations otoh should be more clearly delineated as helper
>>> > implementations that drivers can/should overwrite. I think we should
>>> > split drm_atomic.c into drm_atomic.c (with the official pieces) and
>>> > drm_atomic_helper.c (with the suggested standard/transitional
>>> > implemenations for commit/check). Helper functions should have the
>>> > drm_atomic_helper_ prefix.
>>>
>>> Hmm, I think nearly *everything* could be overridden.. maybe it could
>>> be more clear what to override vs outright replace. But otoh I'm not
>>> quite sure yet what drivers will need to override (other than some
>>> obvious ones, which are already broken out into vfuncs, like
>>> {plane,crtc}->create_state() to handle driver custom properties).
>>
>> Like I've said above we should imo try to unify the world a bit more
>> again. And for the state tracking that should be possible, so I don't see
>> a need to hand drivers too much rope.
>>
>> The check/commit stuff otoh should be fully overrideable, since i915 will
>> need that.
>>
>>> So I expect some tweaks as other drivers start adding native atomic
>>> support. I basically added what I needed for msm, and what I thought
>>> was pretty safe bet that other drivers would need. This at least
>>> gives us something other drivers could start trying to use. Then see
>>> what is missing and add it as we go. At least that was my line of
>>> thinking.
>>
>> Like I've said I don't think there's much value beyong making crtc helpers
>> atomic capable for modeset changes. Atomic pageflips pretty much need
>> driver-specific magic (less so if there's a "GO" bit like on sane
>> hardware).
>
> right, there is a very tiny bit of driver magic in msm_atomic_commit()..
>
> anyways, I don't disagree that we probably need to add something for
> some drivers to be able to hook in to ->atomic_commit() after locking
> magic but before loop over planes/crtcs. I think that would simply be
> addition to the api, ie. new fxn ptr a driver could populate. I
> wouldn't need it for msm.
If you mean new functions for the atomic helper, I agree (and don't
really care). If you mean new functions for the core->driver interface
(i.e. what i915 gets to implement on it's own) then if the
check/commit hooks really should carry all the information we need. In
the end this boils down to my request to more clearly separate
core->driver interface from helper code.
>>> > - I also think we should split the vfuncs like we do with the crtc
>>> > helpers. Imo the core interface should just be an ->alloc_state and
>>> > ->set_prop on all kms objects, plus a global ->prep/check/commit at the
>>> > driver level. The object-specific ->check/commit hooks otoh should be
>>> > part of the atomic helper library and in some separate
>>> > atomic_helper_funcs structure.
>>>
>>> this is in fact the way it is, although 'struct drm_atomic_funcs'
>>> maybe should have "helper" in the name.
>>
>> Yeah, I'm mostly just asking for sprinkling helper all over the stuff that
>> clearly is helper code. And moving everything else into the core and
>> making it non-overrideable.
>>
>>> > Imo we could either extend the sturcture
>>> > used by the crtc helpers (hackish imo) or change the type of that to
>>> > make it clear it's for the crtc helpers and add a new pointer for atomic
>>> > helpers. E.g. in i915 I expect that we'll implement our very own
>>> > ->check/commit hooks using our own compute_config infrastructure. Maybe
>>> > we could switch to the ->check hooks of the atomic helper eventually,
>>> > but that will be a lot of work. And in any case we won't ever switch to
>>> > the ->commit hook as you have it in your helpers since for truly atomic
>>> > flips/modesets we need to interleave all the updates of all objects in
>>> > various phases.
>>>
>>> not sure if it would work for you, but in msm I have a per-crtc "don't
>>> actually commit yet" bit, which gets set for each crtc involved in
>>> atomic update. Although in my case it is mainly a matter of not
>>> touching the "GO" bits until everything is setup..
>>>
>>> If not, I guess it shouldn't be a big deal to, for example, split up
>>> atomic_commit() into part that did the locking dance and then call
>>> vfunc ->atomic_apply_state() or something like that.
>>>
>>> Basically figure out where you need to hook in for i915 as you add
>>> native atomic support. By the time you and maybe one or two other
>>> drivers have added atomic support we should have it pretty well nailed
>>> down. But until then, there might be some small adjustments
>>> here/there.
>>
>> For modeset changes we need to munge everything through the full state
>> precompute and then commit to hw machinery. Not yet fully there (since the
>> shared dpll stuff doesn't work yet). For nuclear pageflips we're only just
>> starting to merge all of Ville's infrastructure, but will probably be the
>> same. So imo the only hand-off point between the core and drm is the
>> single, global ->commit. ->check would be the identical code, except for
>> the final commit.
>>
>> All the ->set_prop callbacks would do nothing else but store data into
>> structures.
>
> I suspect I'll want to see which core properties change eventually..
> when I have a chance to implement YUV and scaling, I'd want to flag
> that scaling/csc coefficients need updating, etc.
Hm, my idea was that drivers would implement any state diffing in
their ->check hooks. Only then we
- hold all the locks, so know nothing relevant will change
- have the entire picture of all states (and the often depend on each
another in funny ways).
So imo all the set_prop code should _only_ deal with creating the
in-kernel representation of the desired state, not with checking it or
computing a whole lot of derived date (like which parts need to be
updated in hw).
> It doesn't seem unreasonable to pass plane/crtc state rather than
> global state. (Although we would need connector_state.. which is
> something I've not found a good use for yet.) But other than that,
> I'd kinda like to leave the ->set_property() as it is.
Oh, we'll need that definitely. At least on i915 we have a pile of
connector properties which we need to track somehow, and most of those
need a full modeset to put them into the hw (mostly disable display
pipe, frob hw, reenable display pipe with the same state).
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
More information about the dri-devel
mailing list