Commit 5faf23ec authored by Karen Xie's avatar Karen Xie

XDMA: increase nxt_adj to 0x3F (max. allowed) and fixed nxt_adj setting when...

XDMA: increase nxt_adj to 0x3F (max. allowed) and fixed nxt_adj setting when last descriptor does not fall on the page boundary
parent 7500f76f
...@@ -549,14 +549,13 @@ static int xdma_engine_stop(struct xdma_engine *engine) ...@@ -549,14 +549,13 @@ static int xdma_engine_stop(struct xdma_engine *engine)
} else { } else {
w |= (u32)XDMA_CTRL_IE_DESC_STOPPED; w |= (u32)XDMA_CTRL_IE_DESC_STOPPED;
w |= (u32)XDMA_CTRL_IE_DESC_COMPLETED; w |= (u32)XDMA_CTRL_IE_DESC_COMPLETED;
} }
dbg_tfr("Stopping SG DMA %s engine; writing 0x%08x to 0x%p.\n", dbg_tfr("Stopping SG DMA %s engine; writing 0x%08x to 0x%p.\n",
engine->name, w, (u32 *)&engine->regs->control); engine->name, w, (u32 *)&engine->regs->control);
write_register(w, &engine->regs->control, write_register(w, &engine->regs->control,
(unsigned long)(&engine->regs->control) - (unsigned long)(&engine->regs->control) -
(unsigned long)(&engine->regs)); (unsigned long)(&engine->regs));
/* dummy read of status register to flush all previous writes */ /* dummy read of status register to flush all previous writes */
dbg_tfr("%s(%s) done\n", __func__, engine->name); dbg_tfr("%s(%s) done\n", __func__, engine->name);
return 0; return 0;
...@@ -2438,9 +2437,6 @@ static int transfer_desc_init(struct xdma_transfer *transfer, int count) ...@@ -2438,9 +2437,6 @@ static int transfer_desc_init(struct xdma_transfer *transfer, int count)
struct xdma_desc *desc_virt = transfer->desc_virt; struct xdma_desc *desc_virt = transfer->desc_virt;
dma_addr_t desc_bus = transfer->desc_bus; dma_addr_t desc_bus = transfer->desc_bus;
int i; int i;
int adj = count - 1;
int extra_adj;
u32 temp_control;
if (count > XDMA_TRANSFER_MAX_DESC) { if (count > XDMA_TRANSFER_MAX_DESC) {
pr_err("Engine cannot transfer more than %d descriptors\n", pr_err("Engine cannot transfer more than %d descriptors\n",
...@@ -2457,31 +2453,14 @@ static int transfer_desc_init(struct xdma_transfer *transfer, int count) ...@@ -2457,31 +2453,14 @@ static int transfer_desc_init(struct xdma_transfer *transfer, int count)
desc_virt[i].next_lo = cpu_to_le32(PCI_DMA_L(desc_bus)); desc_virt[i].next_lo = cpu_to_le32(PCI_DMA_L(desc_bus));
desc_virt[i].next_hi = cpu_to_le32(PCI_DMA_H(desc_bus)); desc_virt[i].next_hi = cpu_to_le32(PCI_DMA_H(desc_bus));
desc_virt[i].bytes = cpu_to_le32(0); desc_virt[i].bytes = cpu_to_le32(0);
desc_virt[i].control = cpu_to_le32(DESC_MAGIC);
/* any adjacent descriptors? */
if (adj > 0) {
extra_adj = adj - 1;
if (extra_adj > MAX_EXTRA_ADJ)
extra_adj = MAX_EXTRA_ADJ;
adj--;
} else {
extra_adj = 0;
}
temp_control = DESC_MAGIC | (extra_adj << 8);
desc_virt[i].control = cpu_to_le32(temp_control);
} }
/* { i = number - 1 } */ /* { i = number - 1 } */
/* zero the last descriptor next pointer */ /* zero the last descriptor next pointer */
desc_virt[i].next_lo = cpu_to_le32(0); desc_virt[i].next_lo = cpu_to_le32(0);
desc_virt[i].next_hi = cpu_to_le32(0); desc_virt[i].next_hi = cpu_to_le32(0);
desc_virt[i].bytes = cpu_to_le32(0); desc_virt[i].bytes = cpu_to_le32(0);
desc_virt[i].control = cpu_to_le32(DESC_MAGIC);
temp_control = DESC_MAGIC;
desc_virt[i].control = cpu_to_le32(temp_control);
return 0; return 0;
} }
...@@ -2528,27 +2507,14 @@ static void xdma_desc_link(struct xdma_desc *first, struct xdma_desc *second, ...@@ -2528,27 +2507,14 @@ static void xdma_desc_link(struct xdma_desc *first, struct xdma_desc *second,
/* xdma_desc_adjacent -- Set how many descriptors are adjacent to this one */ /* xdma_desc_adjacent -- Set how many descriptors are adjacent to this one */
static void xdma_desc_adjacent(struct xdma_desc *desc, int next_adjacent) static void xdma_desc_adjacent(struct xdma_desc *desc, int next_adjacent)
{ {
int extra_adj = 0;
/* remember reserved and control bits */ /* remember reserved and control bits */
u32 control = le32_to_cpu(desc->control) & 0x0000f0ffUL; u32 control = le32_to_cpu(desc->control) & 0xffffc0ffUL;
u32 max_adj_4k = 0;
if (next_adjacent > 0) { if (next_adjacent)
extra_adj = next_adjacent - 1; next_adjacent = next_adjacent - 1;
if (extra_adj > MAX_EXTRA_ADJ) if (next_adjacent > MAX_EXTRA_ADJ)
extra_adj = MAX_EXTRA_ADJ; next_adjacent = MAX_EXTRA_ADJ;
max_adj_4k = control |= (next_adjacent << 8);
(0x1000 - ((le32_to_cpu(desc->next_lo)) & 0xFFF)) / 32 -
1;
if (extra_adj > max_adj_4k)
extra_adj = max_adj_4k;
if (extra_adj < 0) {
pr_warn("extra_adj<0, converting it to 0\n");
extra_adj = 0;
}
}
/* merge adjacent and control field */
control |= 0xAD4B0000UL | (extra_adj << 8);
/* write control and next_adjacent */ /* write control and next_adjacent */
desc->control = cpu_to_le32(control); desc->control = cpu_to_le32(control);
} }
...@@ -3226,14 +3192,12 @@ static int transfer_init(struct xdma_engine *engine, struct xdma_request_cb *req ...@@ -3226,14 +3192,12 @@ static int transfer_init(struct xdma_engine *engine, struct xdma_request_cb *req
dbg_sg("xfer= %p transfer->desc_bus = 0x%llx.\n",xfer, (u64)xfer->desc_bus); dbg_sg("xfer= %p transfer->desc_bus = 0x%llx.\n",xfer, (u64)xfer->desc_bus);
transfer_build(engine, req, xfer , desc_max); transfer_build(engine, req, xfer , desc_max);
/* Contiguous descriptors cannot cross PAGE boundry. Adjust max accordingly */ /* Contiguous descriptors cannot cross PAGE boundry
desc_align = engine->desc_idx + desc_max - 1; * The 1st descriptor may start in the middle of the page,
desc_align = desc_align % 128; * calculate the 1st block of adj desc accordingly */
if (desc_align < (desc_max - 1)) { desc_align = 128 - (engine->desc_idx % 128) - 1;
desc_align = desc_max - desc_align - 1; if (desc_align > (desc_max - 1))
} desc_align = desc_max - 1;
else
desc_align = desc_max;
xfer->desc_adjacent = desc_align; xfer->desc_adjacent = desc_align;
...@@ -3250,7 +3214,10 @@ static int transfer_init(struct xdma_engine *engine, struct xdma_request_cb *req ...@@ -3250,7 +3214,10 @@ static int transfer_init(struct xdma_engine *engine, struct xdma_request_cb *req
engine->desc_used += desc_max ; engine->desc_used += desc_max ;
/* fill in adjacent numbers */ /* fill in adjacent numbers */
for (i = 0; i < xfer->desc_num; i++) for (i = 0; i < xfer->desc_num && desc_align; i++, desc_align--)
xdma_desc_adjacent(xfer->desc_virt + i, desc_align);
for (; i < xfer->desc_num; i++)
xdma_desc_adjacent(xfer->desc_virt + i, xfer->desc_num - i - 1); xdma_desc_adjacent(xfer->desc_virt + i, xfer->desc_num - i - 1);
spin_unlock_irqrestore(&engine->lock, flags); spin_unlock_irqrestore(&engine->lock, flags);
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
* .REG_IRQ_OUT (reg_irq_from_ch[(channel*2) +: 2]), * .REG_IRQ_OUT (reg_irq_from_ch[(channel*2) +: 2]),
*/ */
#define XDMA_ENG_IRQ_NUM (1) #define XDMA_ENG_IRQ_NUM (1)
#define MAX_EXTRA_ADJ (15) #define MAX_EXTRA_ADJ 0x3F
#define RX_STATUS_EOP (1) #define RX_STATUS_EOP (1)
/* Target internal components on XDMA control BAR */ /* Target internal components on XDMA control BAR */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment