You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge commit 'dmaengine-3.13-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/dmaengine
Pull dmaengine changes from Dan 1/ Bartlomiej and Dan finalized a rework of the dma address unmap implementation. 2/ In the course of testing 1/ a collection of enhancements to dmatest fell out. Notably basic performance statistics, and fixed / enhanced test control through new module parameters 'run', 'wait', 'noverify', and 'verbose'. Thanks to Andriy and Linus for their review. 3/ Testing the raid related corner cases of 1/ triggered bugs in the recently added 16-source operation support in the ioatdma driver. 4/ Some minor fixes / cleanups to mv_xor and ioatdma. Conflicts: drivers/dma/dmatest.c Signed-off-by: Vinod Koul <vinod.koul@intel.com>
This commit is contained in:
+1
-269
@@ -801,218 +801,6 @@ static void ppc440spe_desc_set_link(struct ppc440spe_adma_chan *chan,
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ppc440spe_desc_get_src_addr - extract the source address from the descriptor
|
||||
*/
|
||||
static u32 ppc440spe_desc_get_src_addr(struct ppc440spe_adma_desc_slot *desc,
|
||||
struct ppc440spe_adma_chan *chan, int src_idx)
|
||||
{
|
||||
struct dma_cdb *dma_hw_desc;
|
||||
struct xor_cb *xor_hw_desc;
|
||||
|
||||
switch (chan->device->id) {
|
||||
case PPC440SPE_DMA0_ID:
|
||||
case PPC440SPE_DMA1_ID:
|
||||
dma_hw_desc = desc->hw_desc;
|
||||
/* May have 0, 1, 2, or 3 sources */
|
||||
switch (dma_hw_desc->opc) {
|
||||
case DMA_CDB_OPC_NO_OP:
|
||||
case DMA_CDB_OPC_DFILL128:
|
||||
return 0;
|
||||
case DMA_CDB_OPC_DCHECK128:
|
||||
if (unlikely(src_idx)) {
|
||||
printk(KERN_ERR "%s: try to get %d source for"
|
||||
" DCHECK128\n", __func__, src_idx);
|
||||
BUG();
|
||||
}
|
||||
return le32_to_cpu(dma_hw_desc->sg1l);
|
||||
case DMA_CDB_OPC_MULTICAST:
|
||||
case DMA_CDB_OPC_MV_SG1_SG2:
|
||||
if (unlikely(src_idx > 2)) {
|
||||
printk(KERN_ERR "%s: try to get %d source from"
|
||||
" DMA descr\n", __func__, src_idx);
|
||||
BUG();
|
||||
}
|
||||
if (src_idx) {
|
||||
if (le32_to_cpu(dma_hw_desc->sg1u) &
|
||||
DMA_CUED_XOR_WIN_MSK) {
|
||||
u8 region;
|
||||
|
||||
if (src_idx == 1)
|
||||
return le32_to_cpu(
|
||||
dma_hw_desc->sg1l) +
|
||||
desc->unmap_len;
|
||||
|
||||
region = (le32_to_cpu(
|
||||
dma_hw_desc->sg1u)) >>
|
||||
DMA_CUED_REGION_OFF;
|
||||
|
||||
region &= DMA_CUED_REGION_MSK;
|
||||
switch (region) {
|
||||
case DMA_RXOR123:
|
||||
return le32_to_cpu(
|
||||
dma_hw_desc->sg1l) +
|
||||
(desc->unmap_len << 1);
|
||||
case DMA_RXOR124:
|
||||
return le32_to_cpu(
|
||||
dma_hw_desc->sg1l) +
|
||||
(desc->unmap_len * 3);
|
||||
case DMA_RXOR125:
|
||||
return le32_to_cpu(
|
||||
dma_hw_desc->sg1l) +
|
||||
(desc->unmap_len << 2);
|
||||
default:
|
||||
printk(KERN_ERR
|
||||
"%s: try to"
|
||||
" get src3 for region %02x"
|
||||
"PPC440SPE_DESC_RXOR12?\n",
|
||||
__func__, region);
|
||||
BUG();
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR
|
||||
"%s: try to get %d"
|
||||
" source for non-cued descr\n",
|
||||
__func__, src_idx);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
return le32_to_cpu(dma_hw_desc->sg1l);
|
||||
default:
|
||||
printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
|
||||
__func__, dma_hw_desc->opc);
|
||||
BUG();
|
||||
}
|
||||
return le32_to_cpu(dma_hw_desc->sg1l);
|
||||
case PPC440SPE_XOR_ID:
|
||||
/* May have up to 16 sources */
|
||||
xor_hw_desc = desc->hw_desc;
|
||||
return xor_hw_desc->ops[src_idx].l;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ppc440spe_desc_get_dest_addr - extract the destination address from the
|
||||
* descriptor
|
||||
*/
|
||||
static u32 ppc440spe_desc_get_dest_addr(struct ppc440spe_adma_desc_slot *desc,
|
||||
struct ppc440spe_adma_chan *chan, int idx)
|
||||
{
|
||||
struct dma_cdb *dma_hw_desc;
|
||||
struct xor_cb *xor_hw_desc;
|
||||
|
||||
switch (chan->device->id) {
|
||||
case PPC440SPE_DMA0_ID:
|
||||
case PPC440SPE_DMA1_ID:
|
||||
dma_hw_desc = desc->hw_desc;
|
||||
|
||||
if (likely(!idx))
|
||||
return le32_to_cpu(dma_hw_desc->sg2l);
|
||||
return le32_to_cpu(dma_hw_desc->sg3l);
|
||||
case PPC440SPE_XOR_ID:
|
||||
xor_hw_desc = desc->hw_desc;
|
||||
return xor_hw_desc->cbtal;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ppc440spe_desc_get_src_num - extract the number of source addresses from
|
||||
* the descriptor
|
||||
*/
|
||||
static u32 ppc440spe_desc_get_src_num(struct ppc440spe_adma_desc_slot *desc,
|
||||
struct ppc440spe_adma_chan *chan)
|
||||
{
|
||||
struct dma_cdb *dma_hw_desc;
|
||||
struct xor_cb *xor_hw_desc;
|
||||
|
||||
switch (chan->device->id) {
|
||||
case PPC440SPE_DMA0_ID:
|
||||
case PPC440SPE_DMA1_ID:
|
||||
dma_hw_desc = desc->hw_desc;
|
||||
|
||||
switch (dma_hw_desc->opc) {
|
||||
case DMA_CDB_OPC_NO_OP:
|
||||
case DMA_CDB_OPC_DFILL128:
|
||||
return 0;
|
||||
case DMA_CDB_OPC_DCHECK128:
|
||||
return 1;
|
||||
case DMA_CDB_OPC_MV_SG1_SG2:
|
||||
case DMA_CDB_OPC_MULTICAST:
|
||||
/*
|
||||
* Only for RXOR operations we have more than
|
||||
* one source
|
||||
*/
|
||||
if (le32_to_cpu(dma_hw_desc->sg1u) &
|
||||
DMA_CUED_XOR_WIN_MSK) {
|
||||
/* RXOR op, there are 2 or 3 sources */
|
||||
if (((le32_to_cpu(dma_hw_desc->sg1u) >>
|
||||
DMA_CUED_REGION_OFF) &
|
||||
DMA_CUED_REGION_MSK) == DMA_RXOR12) {
|
||||
/* RXOR 1-2 */
|
||||
return 2;
|
||||
} else {
|
||||
/* RXOR 1-2-3/1-2-4/1-2-5 */
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
default:
|
||||
printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
|
||||
__func__, dma_hw_desc->opc);
|
||||
BUG();
|
||||
}
|
||||
case PPC440SPE_XOR_ID:
|
||||
/* up to 16 sources */
|
||||
xor_hw_desc = desc->hw_desc;
|
||||
return xor_hw_desc->cbc & XOR_CDCR_OAC_MSK;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ppc440spe_desc_get_dst_num - get the number of destination addresses in
|
||||
* this descriptor
|
||||
*/
|
||||
static u32 ppc440spe_desc_get_dst_num(struct ppc440spe_adma_desc_slot *desc,
|
||||
struct ppc440spe_adma_chan *chan)
|
||||
{
|
||||
struct dma_cdb *dma_hw_desc;
|
||||
|
||||
switch (chan->device->id) {
|
||||
case PPC440SPE_DMA0_ID:
|
||||
case PPC440SPE_DMA1_ID:
|
||||
/* May be 1 or 2 destinations */
|
||||
dma_hw_desc = desc->hw_desc;
|
||||
switch (dma_hw_desc->opc) {
|
||||
case DMA_CDB_OPC_NO_OP:
|
||||
case DMA_CDB_OPC_DCHECK128:
|
||||
return 0;
|
||||
case DMA_CDB_OPC_MV_SG1_SG2:
|
||||
case DMA_CDB_OPC_DFILL128:
|
||||
return 1;
|
||||
case DMA_CDB_OPC_MULTICAST:
|
||||
if (desc->dst_cnt == 2)
|
||||
return 2;
|
||||
else
|
||||
return 1;
|
||||
default:
|
||||
printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
|
||||
__func__, dma_hw_desc->opc);
|
||||
BUG();
|
||||
}
|
||||
case PPC440SPE_XOR_ID:
|
||||
/* Always only 1 destination */
|
||||
return 1;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ppc440spe_desc_get_link - get the address of the descriptor that
|
||||
* follows this one
|
||||
@@ -1705,43 +1493,6 @@ static void ppc440spe_adma_free_slots(struct ppc440spe_adma_desc_slot *slot,
|
||||
}
|
||||
}
|
||||
|
||||
static void ppc440spe_adma_unmap(struct ppc440spe_adma_chan *chan,
|
||||
struct ppc440spe_adma_desc_slot *desc)
|
||||
{
|
||||
u32 src_cnt, dst_cnt;
|
||||
dma_addr_t addr;
|
||||
|
||||
/*
|
||||
* get the number of sources & destination
|
||||
* included in this descriptor and unmap
|
||||
* them all
|
||||
*/
|
||||
src_cnt = ppc440spe_desc_get_src_num(desc, chan);
|
||||
dst_cnt = ppc440spe_desc_get_dst_num(desc, chan);
|
||||
|
||||
/* unmap destinations */
|
||||
if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
|
||||
while (dst_cnt--) {
|
||||
addr = ppc440spe_desc_get_dest_addr(
|
||||
desc, chan, dst_cnt);
|
||||
dma_unmap_page(chan->device->dev,
|
||||
addr, desc->unmap_len,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
/* unmap sources */
|
||||
if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
|
||||
while (src_cnt--) {
|
||||
addr = ppc440spe_desc_get_src_addr(
|
||||
desc, chan, src_cnt);
|
||||
dma_unmap_page(chan->device->dev,
|
||||
addr, desc->unmap_len,
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ppc440spe_adma_run_tx_complete_actions - call functions to be called
|
||||
* upon completion
|
||||
@@ -1765,26 +1516,7 @@ static dma_cookie_t ppc440spe_adma_run_tx_complete_actions(
|
||||
desc->async_tx.callback(
|
||||
desc->async_tx.callback_param);
|
||||
|
||||
/* unmap dma addresses
|
||||
* (unmap_single vs unmap_page?)
|
||||
*
|
||||
* actually, ppc's dma_unmap_page() functions are empty, so
|
||||
* the following code is just for the sake of completeness
|
||||
*/
|
||||
if (chan && chan->needs_unmap && desc->group_head &&
|
||||
desc->unmap_len) {
|
||||
struct ppc440spe_adma_desc_slot *unmap =
|
||||
desc->group_head;
|
||||
/* assume 1 slot per op always */
|
||||
u32 slot_count = unmap->slot_cnt;
|
||||
|
||||
/* Run through the group list and unmap addresses */
|
||||
for (i = 0; i < slot_count; i++) {
|
||||
BUG_ON(!unmap);
|
||||
ppc440spe_adma_unmap(chan, unmap);
|
||||
unmap = unmap->hw_next;
|
||||
}
|
||||
}
|
||||
dma_descriptor_unmap(&desc->async_tx);
|
||||
}
|
||||
|
||||
/* run dependent operations */
|
||||
|
||||
Reference in New Issue
Block a user