in ppc4xx/adma.c [2830:3013]
static void ppc440spe_adma_pq_set_dest(struct ppc440spe_adma_desc_slot *sw_desc,
dma_addr_t *addrs, unsigned long flags)
{
struct ppc440spe_adma_desc_slot *iter;
struct ppc440spe_adma_chan *chan;
dma_addr_t paddr, qaddr;
dma_addr_t addr = 0, ppath, qpath;
int index = 0, i;
chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
if (flags & DMA_PREP_PQ_DISABLE_P)
paddr = 0;
else
paddr = addrs[0];
if (flags & DMA_PREP_PQ_DISABLE_Q)
qaddr = 0;
else
qaddr = addrs[1];
if (!paddr || !qaddr)
addr = paddr ? paddr : qaddr;
switch (chan->device->id) {
case PPC440SPE_DMA0_ID:
case PPC440SPE_DMA1_ID:
/* walk through the WXOR source list and set P/Q-destinations
* for each slot:
*/
if (!test_bit(PPC440SPE_DESC_RXOR, &sw_desc->flags)) {
/* This is WXOR-only chain; may have 1/2 zero descs */
if (test_bit(PPC440SPE_ZERO_P, &sw_desc->flags))
index++;
if (test_bit(PPC440SPE_ZERO_Q, &sw_desc->flags))
index++;
iter = ppc440spe_get_group_entry(sw_desc, index);
if (addr) {
/* one destination */
list_for_each_entry_from(iter,
&sw_desc->group_list, chain_node)
ppc440spe_desc_set_dest_addr(iter, chan,
DMA_CUED_XOR_BASE, addr, 0);
} else {
/* two destinations */
list_for_each_entry_from(iter,
&sw_desc->group_list, chain_node) {
ppc440spe_desc_set_dest_addr(iter, chan,
DMA_CUED_XOR_BASE, paddr, 0);
ppc440spe_desc_set_dest_addr(iter, chan,
DMA_CUED_XOR_BASE, qaddr, 1);
}
}
if (index) {
/* To clear destinations update the descriptor
* (1st,2nd, or both depending on flags)
*/
index = 0;
if (test_bit(PPC440SPE_ZERO_P,
&sw_desc->flags)) {
iter = ppc440spe_get_group_entry(
sw_desc, index++);
ppc440spe_adma_pq_zero_op(iter, chan,
paddr);
}
if (test_bit(PPC440SPE_ZERO_Q,
&sw_desc->flags)) {
iter = ppc440spe_get_group_entry(
sw_desc, index++);
ppc440spe_adma_pq_zero_op(iter, chan,
qaddr);
}
return;
}
} else {
/* This is RXOR-only or RXOR/WXOR mixed chain */
/* If we want to include destination into calculations,
* then make dest addresses cued with mult=1 (XOR).
*/
ppath = test_bit(PPC440SPE_ZERO_P, &sw_desc->flags) ?
DMA_CUED_XOR_HB :
DMA_CUED_XOR_BASE |
(1 << DMA_CUED_MULT1_OFF);
qpath = test_bit(PPC440SPE_ZERO_Q, &sw_desc->flags) ?
DMA_CUED_XOR_HB :
DMA_CUED_XOR_BASE |
(1 << DMA_CUED_MULT1_OFF);
/* Setup destination(s) in RXOR slot(s) */
iter = ppc440spe_get_group_entry(sw_desc, index++);
ppc440spe_desc_set_dest_addr(iter, chan,
paddr ? ppath : qpath,
paddr ? paddr : qaddr, 0);
if (!addr) {
/* two destinations */
iter = ppc440spe_get_group_entry(sw_desc,
index++);
ppc440spe_desc_set_dest_addr(iter, chan,
qpath, qaddr, 0);
}
if (test_bit(PPC440SPE_DESC_WXOR, &sw_desc->flags)) {
/* Setup destination(s) in remaining WXOR
* slots
*/
iter = ppc440spe_get_group_entry(sw_desc,
index);
if (addr) {
/* one destination */
list_for_each_entry_from(iter,
&sw_desc->group_list,
chain_node)
ppc440spe_desc_set_dest_addr(
iter, chan,
DMA_CUED_XOR_BASE,
addr, 0);
} else {
/* two destinations */
list_for_each_entry_from(iter,
&sw_desc->group_list,
chain_node) {
ppc440spe_desc_set_dest_addr(
iter, chan,
DMA_CUED_XOR_BASE,
paddr, 0);
ppc440spe_desc_set_dest_addr(
iter, chan,
DMA_CUED_XOR_BASE,
qaddr, 1);
}
}
}
}
break;
case PPC440SPE_XOR_ID:
/* DMA2 descriptors have only 1 destination, so there are
* two chains - one for each dest.
* If we want to include destination into calculations,
* then make dest addresses cued with mult=1 (XOR).
*/
ppath = test_bit(PPC440SPE_ZERO_P, &sw_desc->flags) ?
DMA_CUED_XOR_HB :
DMA_CUED_XOR_BASE |
(1 << DMA_CUED_MULT1_OFF);
qpath = test_bit(PPC440SPE_ZERO_Q, &sw_desc->flags) ?
DMA_CUED_XOR_HB :
DMA_CUED_XOR_BASE |
(1 << DMA_CUED_MULT1_OFF);
iter = ppc440spe_get_group_entry(sw_desc, 0);
for (i = 0; i < sw_desc->descs_per_op; i++) {
ppc440spe_desc_set_dest_addr(iter, chan,
paddr ? ppath : qpath,
paddr ? paddr : qaddr, 0);
iter = list_entry(iter->chain_node.next,
struct ppc440spe_adma_desc_slot,
chain_node);
}
if (!addr) {
/* Two destinations; setup Q here */
iter = ppc440spe_get_group_entry(sw_desc,
sw_desc->descs_per_op);
for (i = 0; i < sw_desc->descs_per_op; i++) {
ppc440spe_desc_set_dest_addr(iter,
chan, qpath, qaddr, 0);
iter = list_entry(iter->chain_node.next,
struct ppc440spe_adma_desc_slot,
chain_node);
}
}
break;
}
}