ALLOC_CACHE_ALIGN_BUFFER was called here in a way to alloc in stack a possible huge quantity of memory depending on data transer size.
Es: loading kernel 8MB from eMMC we have Transfer size: 0x800000 Block size: 0x200 Transfer blocks: 0x4000 struct size: 0x10 Stack allocation: ((0x200 / 8) + 1) * 0x10 = 0x8010 (~32KB) Since this allocation is done on stack, there is no current way to get an error on stack memory limit exceeded, overlapping heap space on environments with very strict stack + heap limits like TPL or SPL (where malloc size can be 16KB). Results are silent corruptions of heap on mmc transfer and random errors or CPU hang. Using malloc_cache_aligned() we will alloc slightly bigger buffers but we do have evidence about memory allocation failure allowing developer to recognize the issue and take actions. Signed-off-by: Alberto Panizzo <albe...@amarulasolutions.com> --- drivers/mmc/dw_mmc.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 13180fc..0126563 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -194,8 +194,9 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, { #endif struct dwmci_host *host = mmc->priv; - ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, - data ? DIV_ROUND_UP(data->blocks, 8) : 0); + struct dwmci_idmac *cur_idmac = + malloc_cache_aligned(sizeof(struct dwmci_idmac) * + (1 + (data ? DIV_ROUND_UP(data->blocks, 8) : 0))); int ret = 0, flags = 0, i; unsigned int timeout = 500; u32 retry = 100000; @@ -203,10 +204,18 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, ulong start = get_timer(0); struct bounce_buffer bbstate; + if (!cur_idmac) { + debug("%s: Cannot allocate 0x%x bytes\n", __func__, + sizeof(struct dwmci_idmac) * + (1 + (data ? DIV_ROUND_UP(data->blocks, 8) : 0))); + return -ENOMEM; + } + while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) { if (get_timer(start) > timeout) { debug("%s: Timeout on data busy\n", __func__); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + goto free_idmac; } } @@ -238,8 +247,10 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, if (data) flags = dwmci_set_transfer_mode(host, data); - if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) - return -1; + if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) { + ret = -EIO; + goto free_idmac; + } if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) flags |= DWMCI_CMD_ABORT_STOP; @@ -272,7 +283,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, if (i == retry) { debug("%s: Timeout.\n", __func__); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + goto free_idmac; } if (mask & DWMCI_INTMSK_RTO) { @@ -285,10 +297,12 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, * CMD8, please keep that in mind. */ debug("%s: Response Timeout.\n", __func__); - return -ETIMEDOUT; + ret = -ETIMEDOUT; + goto free_idmac; } else if (mask & DWMCI_INTMSK_RE) { debug("%s: Response Error.\n", __func__); - return -EIO; + ret = -EIO; + goto free_idmac; } @@ -317,6 +331,9 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, udelay(100); +free_idmac: + free(cur_idmac); + return ret; } -- 2.7.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot