Re: [PATCH v3 2/6] dmaengine: Add interleaved cyclic transaction type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Vinod,

On Mon, Mar 02, 2020 at 09:17:35AM +0530, Vinod Koul wrote:
> On 26-02-20, 18:30, Laurent Pinchart wrote:
> > On Wed, Feb 19, 2020 at 02:55:14PM +0530, Vinod Koul wrote:
> >> On 17-02-20, 12:00, Peter Ujfalusi wrote:
> >>> On 14/02/2020 18.22, Laurent Pinchart wrote:
> >>>>>> It does, but I really wonder why we need a new terminate operation that
> >>>>>> would terminate a single transfer. If we call issue_pending at step B.3,
> >>>>>> when the new txn submitted, we can terminate the current transfer at the
> >>>>>> point. It changes the semantics of issue_pending, but only for cyclic
> >>>>>> transfers (this whole discussions it only about cyclic transfers). As a
> >>>>>> cyclic transfer will be repeated forever until terminated, there's no
> >>>>>> use case for issuing a new transfer without terminating the one in
> >>>>>> progress. I thus don't think we need a new terminate operation: the only
> >>>>>> thing that makes sense to do when submitting a new cyclic transfer is to
> >>>>>> terminate the current one and switch to the new one, and we already have
> >>>>>> all the APIs we need to enable this behaviour.
> >>>>>
> >>>>> The issue_pending() is a NOP when engine is already running.
> >>>> 
> >>>> That's not totally right. issue_pending() still moves submitted but not
> >>>> issued transactions from the submitted queue to the issued queue. The
> >>>> DMA engine only considers the issued queue, so issue_pending()
> >>>> essentially tells the DMA engine to consider the submitted transaction
> >>>> for processing after the already issued transactions complete (in the
> >>>> non-cyclic case).
> >>> 
> >>> Vinod's point is for the cyclic case at the current state. It is NOP
> >>> essentially as we don't have way to not kill the whole channel.
> >> 
> >> Or IOW there is no descriptor movement to hardware..
> >> 
> >>> Just a sidenote: it is not even that clean cut for slave transfers
> >>> either as the slave_config must _not_ change between the issued
> >>> transfers. Iow, you can not switch between 16bit and 32bit word lengths
> >>> with some DMA. EDMA, sDMA can do that, but UDMA can not for example...
> >>> 
> >>>>> The design of APIs is that we submit a txn to pending_list and then the
> >>>>> pending_list is started when issue_pending() is called.
> >>>>> Or if the engine is already running, it will take next txn from
> >>>>> pending_list() when current txn completes.
> >>>>>
> >>>>> The only consideration here in this case is that the cyclic txn never
> >>>>> completes. Do we really treat a new txn submission as an 'indication' of
> >>>>> completeness? That is indeed a point to ponder upon.
> >>>> 
> >>>> The reason why I think we should is two-fold:
> >>>> 
> >>>> 1. I believe it's semantically aligned with the existing behaviour of
> >>>> issue_pending(). As explained above, the operation tells the DMA engine
> >>>> to consider submitted transactions for processing when the current (and
> >>>> other issued) transactions complete. If we extend the definition of
> >>>> complete to cover cyclic transactions, I think it's a good match.
> >>> 
> >>> We will end up with different behavior between cyclic and non cyclic
> >>> transfers and the new behavior should be somehow supported by existing
> >>> drivers.
> >>> Yes, issue_pending is moving the submitted tx to the issued queue to be
> >>> executed on HW when the current transfer finished.
> >>> We only needed this for non cyclic uses so far. Some DMA hw can replace
> >>> the current transfer with a new one (re-trigger to fetch the new
> >>> configuration, like your's), but some can not (none of the system DMAs
> >>> on TI platforms can).
> >>> If we say that this is the behavior the DMA drivers must follow then we
> >>> will have non compliant DMA drivers. You can not move simply to other
> >>> DMA or can not create generic DMA code shared by drivers.
> >> 
> >> That is very important point for API. We want no implicit behaviour, so
> >> if we want an behaviour let us do that explicitly.
> > 
> > As I've just explained in my reply to Peter, there's nothing implicit in
> > my proposal :-) It's however missing a flag to report if the DMA engine
> > driver supports this feature, put apart from that, it makes the API
> > *more* consistent by making issue_pending() cover *all* transfer types
> > with the *same* semantics.
> 
> I would be more comfortable in calling an API to do so :)
> The flow I am thinking is:
> 
> - prep cyclic1 txn
> - submit cyclic1 txn
> - call issue_pending() (cyclic one starts)
> 
> - prep cyclic2 txn
> - submit cyclic2 txn
> - signal_cyclic1_txn aka terminate_cookie()
> - cyclic1 completes, switch to cyclic2 (dmaengine driver)
> - get callback for cyclic1 (optional)
> 
> To check if hw supports terminate_cookie() or not we can check if the
> callback support is implemented

Two questions though:

- Where is .issue_pending() called for cyclic2 in your above sequence ?
  Surely it should be called somewhere, as the DMA engine API requires
  .issue_pending() to be called for a transfer to be executed, otherwise
  it stays in the submitted but not pending queue.

- With the introduction of a new .terminate_cookie() operation, we need
  to specify that operation for all transfer types. What's its
  envisioned semantics for non-cyclic transfers ? And how do DMA engine
  drivers report that they support .terminate_cookie() for cyclic
  transfers but not for other transfer types (the counterpart of
  reporting, in my proposition, that .issue_pending() isn't supported
  replace the current cyclic transfer) ?

> >>>> 2. There's really nothing else we could do with cyclic transactions.
> >>>> They never complete today and have to be terminated manually with
> >>>> terminate_all(). Using issue_pending() to move to a next cyclic
> >>>> transaction doesn't change the existing behaviour by replacing a useful
> >>>> (and used) feature, as issue_pending() is currently a no-op for cyclic
> >>>> transactions. The newly issued transaction is never considered, and
> >>>> calling terminate_all() will cancel the issued transactions. By
> >>>> extending the behaviour of issue_pending(), we're making a new use case
> >>>> possible, without restricting any other feature, and without "stealing"
> >>>> issue_pending() and preventing it from implementing another useful
> >>>> behaviour.
> >>> 
> >>> But at the same time we make existing drivers non compliant...
> >>> 
> >>> Imo a new callback to 'kill' / 'terminate' / 'replace' / 'abort' an
> >>> issued cookie would be cleaner.
> >>> 
> >>> cookie1 = dmaengine_issue_pending();
> >>> // will start the transfer
> >>> cookie2 = dmaengine_issue_pending();
> >>> // cookie1 still runs, cookie2 is waiting to be executed
> >>> dmaengine_abort_tx(chan);
> >>> // will kill cookie1 and executes cookie2
> >> 
> >> Right and we need a kill mode which kills the cookie1 at the end of
> >> transfer (conditional to hw supporting that)
> >> 
> >> I think it should be generic API and usable in both the cyclic and
> >> non-cyclic case
> > 
> > I have no issue with an API that can abort ongoing transfers without
> > killing the whole queue of pending transfers, but that's not what I'm
> > after, it's not my use case. Again, as explained in my reply to Peter,
> > I'm not looking for a way to abort a transfer immediately, but to move
> > to the next transfer at the end of the current one. It's very different,
> > and the DMA engine API already supports this for all transfers but
> > cyclic transfers. I'd go as far as saying that my proposal is fixing a
> > bug in the current implementation :-)
> > 
> >>> dmaengine_abort_tx() could take a cookie as parameter if we wish, so you
> >>> can say selectively which issued tx you want to remove, if it is the
> >>> running one, then stop it and move to the next one.
> >>> In place of the cookie parameter a 0 could imply that I don't know the
> >>> cookie, but kill the running one.
> >>> 
> >>> We would preserve what issue_pending does atm and would give us a
> >>> generic flow of how other drivers should handle such cases.
> >>> 
> >>> Note that this is not only useful for cyclic cases. Any driver which
> >>> currently uses brute-force termination can be upgraded.
> >>> Prime example is UART RX. We issue an RX buffer to receive data, but it
> >>> is not guarantied that the remote will send data which would fill the
> >>> buffer and we hit a timeout waiting. We could issue the next buffer and
> >>> kill the stale transfer to reclaim the received data.
> >>> 
> >>> I think this can be even implemented for DMAs which can not do the same
> >>> thing as your DMA can.
> >>> 
> >>>> In a nutshell, an important reason why I like using issue_pending() for
> >>>> this purpose is because it makes cyclic and non-cyclic transactions
> >>>> behave more similarly, which I think is good from an API consistency
> >>>> point of view.
> >>>> 
> >>>>> Also, we need to keep in mind that the dmaengine wont stop a cyclic
> >>>>> txn. It would be running and start next transfer (in this case do
> >>>>> from start) while it also gives you an interrupt. Here we would be
> >>>>> required to stop it and then start a new one...
> >>>> 
> >>>> We wouldn't be required to stop it in the middle, the expected behaviour
> >>>> is for the DMA engine to complete the cyclic transaction until the end
> >>>> of the cycle and then replace it by the new one. That's exactly what
> >>>> happens for non-cyclic transactions when you call issue_pending(), which
> >>>> makes me like this solution.
> >>> 
> >>> Right, so we have two different use cases. Replace the current transfers
> >>> with the next issued one and abort the current transfer now and arm the
> >>> next issued one.
> >>> dmaengine_abort_tx(chan, cookie, forced) ?
> >>> forced == false: replace it at cyclic boundary
> >>> forced == true: right away (as HW allows), do not wait for cyclic round
> >>> 
> >>>>> Or perhaps remove the cyclic setting from the txn when a new one
> >>>>> arrives and that behaviour IMO is controller dependent, not sure if
> >>>>> all controllers support it..
> >>>> 
> >>>> At the very least I would assume controllers to be able to stop a cyclic
> >>>> transaction forcefully, otherwise terminate_all() could never be
> >>>> implemented. This may not lead to a gracefully switch from one cyclic
> >>>> transaction to another one if the hardware doesn't allow doing so. In
> >>>> that case I think tx_submit() could return an error, or we could turn
> >>>> issue_pending() into an int operation to signal the error. Note that
> >>>> there's no need to mass-patch drivers here, if a DMA engine client
> >>>> issues a second cyclic transaction while one is in progress, the second
> >>>> transaction won't be considered today. Signalling an error is in my
> >>>> opinion a useful feature, but not doing so in DMA engine drivers can't
> >>>> be a regression. We could also add a flag to tell whether this mode of
> >>>> operation is supported.
> >>> 
> >>> My problems is that it is changing the behavior of issue_pending() for
> >>> cyclic. If we document this than all existing DMA drivers are broken
> >>> (not complaint with the API documentation) as they don't do this.
> >>> 
> >>> 
> >>>>>>> That would be a clean way to handle it. We were missing this API for a
> >>>>>>> long time to be able to cancel the ongoing transfer (whether it is
> >>>>>>> cyclic or slave_sg, or memcpy) and move to the next one if there is one
> >>>>>>> pending.
> >>>>>>
> >>>>>> Note that this new terminate API wouldn't terminate the ongoing transfer
> >>>>>> immediately, it would complete first, until the end of the cycle for
> >>>>>> cyclic transfers, and until the end of the whole transfer otherwise.
> >>>>>> This new operation would thus essentially be a no-op for non-cyclic
> >>>>>> transfers. I don't see how it would help :-) Do you have any particular
> >>>>>> use case in mind ?
> >>>>>
> >>>>> Yeah that is something more to think about. Do we really abort here or
> >>>>> wait for the txn to complete. I think Peter needs the former and your
> >>>>> falls in the latter category
> >>>> 
> >>>> I definitely need the latter, otherwise the display will flicker (or
> >>>> completely misoperate) every time a new frame is displayed, which isn't
> >>>> a good idea :-)
> >>> 
> >>> Sure, and it is a great feature.
> >>> 
> >>>> I'm not sure about Peter's use cases, but it seems to me
> >>>> that aborting a transaction immediately is racy in most cases, unless
> >>>> the DMA engine supports byte-level residue reporting.
> >>> 
> >>> Sort of yes. With EDMA, sDMA I can just kill the channel and set up a
> >>> new one right away.
> >>> UDMA on the other hand is not that forgiving... I would need to kill the
> >>> channel, wait for the termination to complete, reconfigure the channel
> >>> and execute the new transfer.
> >>> 
> >>> But with a separate callback API at least there will be an entry point
> >>> when this can be initiated and handled.
> >>> Fwiw, I think it should be simple to add this functionality to them, the
> >>> code is kind of handling it in other parts, but implementing it in the
> >>> issue_pending() is not really a clean solution.
> >>> 
> >>> In a channel you can run slave_sg transfers followed by cyclic if you
> >>> wish. A slave channel is what it is, slave channel which can be capable
> >>> to execute slave_sg and/or cyclic (and/or interleaved).
> >>> If issue_pending() is to take care then we need to check if the current
> >>> transfer is cyclic or not and decide based on that.
> >>> 
> >>> With a separate callback we in the DMA driver just need to do what the
> >>> client is asking for and no need to think.
> >>> 
> >>>> One non-intrusive
> >>>> option would be to add a flag to signal that a newly issued transaction
> >>>> should interrupt the current transaction immediately.

-- 
Regards,

Laurent Pinchart



[Index of Archives]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux PCI]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux