mmc: cmdq_hci: Fix ADMA error issue
The controller triggers an ADMA error when ADMA engine is configured and used in 32-bit mode. This is because the current code always writes 64-bit address to 32-bit address field of a transfer descriptor (bits [63:32]). This corrupts the first 32-bit value of the next transfer descriptor. Below scenario describes how ADMA error can happen - 1. Req#1 - uses slot 1, prepares it's descriptors, queues to the controller 2. Req#2 - uses slot 0, prepares max descriptors (cq_host->mmc->max_segs). 3. Req#1 gets ADMA error from the controller. At step 2, when it prepares the last transfer descriptor (max_segs), it overwrites the 32-bit address field with a 64-bit address and thus corrupts the first entry of slot 1 transfer descriptor. Change-Id: I3eb2dbb40c76ec77626f647d6ec24df4a0858fcb Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
This commit is contained in:
parent
17cc5c6354
commit
c3abdef6e0
|
@ -449,10 +449,9 @@ static int cmdq_dma_map(struct mmc_host *host, struct mmc_request *mrq)
|
|||
return sg_count;
|
||||
}
|
||||
|
||||
static void cmdq_set_tran_desc(u8 *desc,
|
||||
dma_addr_t addr, int len, bool end)
|
||||
static void cmdq_set_tran_desc(u8 *desc, dma_addr_t addr, int len,
|
||||
bool end, bool is_dma64)
|
||||
{
|
||||
__le64 *dataddr = (__le64 __force *)(desc + 4);
|
||||
__le32 *attr = (__le32 __force *)desc;
|
||||
|
||||
*attr = (VALID(1) |
|
||||
|
@ -461,7 +460,15 @@ static void cmdq_set_tran_desc(u8 *desc,
|
|||
ACT(0x4) |
|
||||
DAT_LENGTH(len));
|
||||
|
||||
dataddr[0] = cpu_to_le64(addr);
|
||||
if (is_dma64) {
|
||||
__le64 *dataddr = (__le64 __force *)(desc + 4);
|
||||
|
||||
dataddr[0] = cpu_to_le64(addr);
|
||||
} else {
|
||||
__le32 *dataddr = (__le32 __force *)(desc + 4);
|
||||
|
||||
dataddr[0] = cpu_to_le32(addr);
|
||||
}
|
||||
}
|
||||
|
||||
static int cmdq_prep_tran_desc(struct mmc_request *mrq,
|
||||
|
@ -490,7 +497,7 @@ static int cmdq_prep_tran_desc(struct mmc_request *mrq,
|
|||
|
||||
if ((i+1) == sg_count)
|
||||
end = true;
|
||||
cmdq_set_tran_desc(desc, addr, len, end);
|
||||
cmdq_set_tran_desc(desc, addr, len, end, cq_host->dma64);
|
||||
desc += cq_host->trans_desc_len;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue