Skip to content

Commit b50cf4b

Browse files
ambarusvinodkoul
authored andcommitted
dmaengine: at_hdmac: Introduce atc_get_llis_residue()
Introduce a method to get the residue for a hardware linked list transfer. It makes the code easier to read. Signed-off-by: Tudor Ambarus <[email protected]> Acked-by: Nicolas Ferre <[email protected]> Link: https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 91617bf commit b50cf4b

File tree

1 file changed

+110
-111
lines changed

1 file changed

+110
-111
lines changed

drivers/dma/at_hdmac.c

Lines changed: 110 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,109 @@ static inline u32 atc_calc_bytes_left(u32 current_len, u32 ctrla)
307307
return current_len - (btsize << src_width);
308308
}
309309

310+
/**
311+
* atc_get_llis_residue - Get residue for a hardware linked list transfer
312+
*
313+
* Calculate the residue by removing the length of the child descriptors already
314+
* transferred from the total length. To get the current child descriptor we can
315+
* use the value of the channel's DSCR register and compare it against the value
316+
* of the hardware linked list structure of each child descriptor.
317+
*
318+
* The CTRLA register provides us with the amount of data already read from the
319+
* source for the current child descriptor. So we can compute a more accurate
320+
* residue by also removing the number of bytes corresponding to this amount of
321+
* data.
322+
*
323+
* However, the DSCR and CTRLA registers cannot be read both atomically. Hence a
324+
* race condition may occur: the first read register may refer to one child
325+
* descriptor whereas the second read may refer to a later child descriptor in
326+
* the list because of the DMA transfer progression inbetween the two reads.
327+
*
328+
* One solution could have been to pause the DMA transfer, read the DSCR and
329+
* CTRLA then resume the DMA transfer. Nonetheless, this approach presents some
330+
* drawbacks:
331+
* - If the DMA transfer is paused, RX overruns or TX underruns are more likey
332+
* to occur depending on the system latency. Taking the USART driver as an
333+
* example, it uses a cyclic DMA transfer to read data from the Receive
334+
* Holding Register (RHR) to avoid RX overruns since the RHR is not protected
335+
* by any FIFO on most Atmel SoCs. So pausing the DMA transfer to compute the
336+
* residue would break the USART driver design.
337+
* - The atc_pause() function masks interrupts but we'd rather avoid to do so
338+
* for system latency purpose.
339+
*
340+
* Then we'd rather use another solution: the DSCR is read a first time, the
341+
* CTRLA is read in turn, next the DSCR is read a second time. If the two
342+
* consecutive read values of the DSCR are the same then we assume both refers
343+
* to the very same child descriptor as well as the CTRLA value read inbetween
344+
* does. For cyclic tranfers, the assumption is that a full loop is "not so
345+
* fast". If the two DSCR values are different, we read again the CTRLA then the
346+
* DSCR till two consecutive read values from DSCR are equal or till the
347+
* maximum trials is reach. This algorithm is very unlikely not to find a stable
348+
* value for DSCR.
349+
* @atchan: pointer to an atmel hdmac channel.
350+
* @desc: pointer to the descriptor for which the residue is calculated.
351+
* @residue: residue to be set to dma_tx_state.
352+
* Returns 0 on success, -errno otherwise.
353+
*/
354+
static int atc_get_llis_residue(struct at_dma_chan *atchan,
355+
struct at_desc *desc, u32 *residue)
356+
{
357+
struct at_desc *child;
358+
u32 len, ctrla, dscr;
359+
unsigned int i;
360+
361+
len = desc->total_len;
362+
dscr = channel_readl(atchan, DSCR);
363+
rmb(); /* ensure DSCR is read before CTRLA */
364+
ctrla = channel_readl(atchan, CTRLA);
365+
for (i = 0; i < ATC_MAX_DSCR_TRIALS; ++i) {
366+
u32 new_dscr;
367+
368+
rmb(); /* ensure DSCR is read after CTRLA */
369+
new_dscr = channel_readl(atchan, DSCR);
370+
371+
/*
372+
* If the DSCR register value has not changed inside the DMA
373+
* controller since the previous read, we assume that both the
374+
* dscr and ctrla values refers to the very same descriptor.
375+
*/
376+
if (likely(new_dscr == dscr))
377+
break;
378+
379+
/*
380+
* DSCR has changed inside the DMA controller, so the previouly
381+
* read value of CTRLA may refer to an already processed
382+
* descriptor hence could be outdated. We need to update ctrla
383+
* to match the current descriptor.
384+
*/
385+
dscr = new_dscr;
386+
rmb(); /* ensure DSCR is read before CTRLA */
387+
ctrla = channel_readl(atchan, CTRLA);
388+
}
389+
if (unlikely(i == ATC_MAX_DSCR_TRIALS))
390+
return -ETIMEDOUT;
391+
392+
/* For the first descriptor we can be more accurate. */
393+
if (desc->lli.dscr == dscr) {
394+
*residue = atc_calc_bytes_left(len, ctrla);
395+
return 0;
396+
}
397+
398+
len -= desc->len;
399+
list_for_each_entry(child, &desc->tx_list, desc_node) {
400+
if (child->lli.dscr == dscr)
401+
break;
402+
len -= child->len;
403+
}
404+
405+
/*
406+
* For the current descriptor in the chain we can calculate the
407+
* remaining bytes using the channel's register.
408+
*/
409+
*residue = atc_calc_bytes_left(len, ctrla);
410+
return 0;
411+
}
412+
310413
/**
311414
* atc_get_residue - get the number of bytes residue for a cookie.
312415
* The residue is passed by address and updated on success.
@@ -321,8 +424,7 @@ static int atc_get_residue(struct dma_chan *chan, dma_cookie_t cookie,
321424
struct at_dma_chan *atchan = to_at_dma_chan(chan);
322425
struct at_desc *desc_first = atc_first_active(atchan);
323426
struct at_desc *desc;
324-
u32 len, ctrla, dscr;
325-
unsigned int i;
427+
u32 len, ctrla;
326428

327429
/*
328430
* If the cookie doesn't match to the currently running transfer then
@@ -335,117 +437,14 @@ static int atc_get_residue(struct dma_chan *chan, dma_cookie_t cookie,
335437
else if (desc != desc_first)
336438
return desc->total_len;
337439

338-
/* cookie matches to the currently running transfer */
339-
len = desc_first->total_len;
340-
341-
if (desc_first->lli.dscr) {
440+
if (desc_first->lli.dscr)
342441
/* hardware linked list transfer */
442+
return atc_get_llis_residue(atchan, desc_first, residue);
343443

344-
/*
345-
* Calculate the residue by removing the length of the child
346-
* descriptors already transferred from the total length.
347-
* To get the current child descriptor we can use the value of
348-
* the channel's DSCR register and compare it against the value
349-
* of the hardware linked list structure of each child
350-
* descriptor.
351-
*
352-
* The CTRLA register provides us with the amount of data
353-
* already read from the source for the current child
354-
* descriptor. So we can compute a more accurate residue by also
355-
* removing the number of bytes corresponding to this amount of
356-
* data.
357-
*
358-
* However, the DSCR and CTRLA registers cannot be read both
359-
* atomically. Hence a race condition may occur: the first read
360-
* register may refer to one child descriptor whereas the second
361-
* read may refer to a later child descriptor in the list
362-
* because of the DMA transfer progression inbetween the two
363-
* reads.
364-
*
365-
* One solution could have been to pause the DMA transfer, read
366-
* the DSCR and CTRLA then resume the DMA transfer. Nonetheless,
367-
* this approach presents some drawbacks:
368-
* - If the DMA transfer is paused, RX overruns or TX underruns
369-
* are more likey to occur depending on the system latency.
370-
* Taking the USART driver as an example, it uses a cyclic DMA
371-
* transfer to read data from the Receive Holding Register
372-
* (RHR) to avoid RX overruns since the RHR is not protected
373-
* by any FIFO on most Atmel SoCs. So pausing the DMA transfer
374-
* to compute the residue would break the USART driver design.
375-
* - The atc_pause() function masks interrupts but we'd rather
376-
* avoid to do so for system latency purpose.
377-
*
378-
* Then we'd rather use another solution: the DSCR is read a
379-
* first time, the CTRLA is read in turn, next the DSCR is read
380-
* a second time. If the two consecutive read values of the DSCR
381-
* are the same then we assume both refers to the very same
382-
* child descriptor as well as the CTRLA value read inbetween
383-
* does. For cyclic tranfers, the assumption is that a full loop
384-
* is "not so fast".
385-
* If the two DSCR values are different, we read again the CTRLA
386-
* then the DSCR till two consecutive read values from DSCR are
387-
* equal or till the maxium trials is reach.
388-
* This algorithm is very unlikely not to find a stable value for
389-
* DSCR.
390-
*/
391-
392-
dscr = channel_readl(atchan, DSCR);
393-
rmb(); /* ensure DSCR is read before CTRLA */
394-
ctrla = channel_readl(atchan, CTRLA);
395-
for (i = 0; i < ATC_MAX_DSCR_TRIALS; ++i) {
396-
u32 new_dscr;
397-
398-
rmb(); /* ensure DSCR is read after CTRLA */
399-
new_dscr = channel_readl(atchan, DSCR);
400-
401-
/*
402-
* If the DSCR register value has not changed inside the
403-
* DMA controller since the previous read, we assume
404-
* that both the dscr and ctrla values refers to the
405-
* very same descriptor.
406-
*/
407-
if (likely(new_dscr == dscr))
408-
break;
409-
410-
/*
411-
* DSCR has changed inside the DMA controller, so the
412-
* previouly read value of CTRLA may refer to an already
413-
* processed descriptor hence could be outdated.
414-
* We need to update ctrla to match the current
415-
* descriptor.
416-
*/
417-
dscr = new_dscr;
418-
rmb(); /* ensure DSCR is read before CTRLA */
419-
ctrla = channel_readl(atchan, CTRLA);
420-
}
421-
if (unlikely(i == ATC_MAX_DSCR_TRIALS))
422-
return -ETIMEDOUT;
423-
424-
/* for the first descriptor we can be more accurate */
425-
if (desc_first->lli.dscr == dscr) {
426-
*residue = atc_calc_bytes_left(len, ctrla);
427-
return 0;
428-
}
429-
430-
len -= desc_first->len;
431-
list_for_each_entry(desc, &desc_first->tx_list, desc_node) {
432-
if (desc->lli.dscr == dscr)
433-
break;
434-
435-
len -= desc->len;
436-
}
437-
438-
/*
439-
* For the current descriptor in the chain we can calculate
440-
* the remaining bytes using the channel's register.
441-
*/
442-
*residue = atc_calc_bytes_left(len, ctrla);
443-
} else {
444-
/* single transfer */
445-
ctrla = channel_readl(atchan, CTRLA);
446-
*residue = atc_calc_bytes_left(len, ctrla);
447-
}
448-
444+
/* single transfer */
445+
len = desc_first->total_len;
446+
ctrla = channel_readl(atchan, CTRLA);
447+
*residue = atc_calc_bytes_left(len, ctrla);
449448
return 0;
450449
}
451450

0 commit comments

Comments
 (0)