Patch "mmc: sdhci: fix dma memory leak in sdhci_pre_req()" has been added to the 4.1-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
mmc: sdhci: fix dma memory leak in sdhci_pre_req()
to the 4.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch
and it can be found in the queue-4.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
d31911b9374a76560d2c8ea4aa6ce5781621e81dMon Sep 17 00:00:00 2001
From: Haibo Chen <[email protected]>
Date: Tue, 25 Aug 2015 10:02:11 +0800
Subject: mmc: sdhci: fix dma memory leak in sdhci_pre_req()
From: Haibo Chen <[email protected]>
commit d31911b9374a76560d2c8ea4aa6ce5781621e81d upstream.
Currently one mrq->data maybe execute dma_map_sg() twice when mmc subsystem prepare over one new request, and the following log show up:
sdhci[sdhci_pre_dma_transfer] invalid cookie: 24, next-cookie 25
In this condition, mrq->date map a dma-memory(1) in sdhci_pre_req for the first time, and map another dma-memory(2) in sdhci_prepare_data for the second time. But driver only unmap the dma-memory(2), and dma-memory(1) never unmapped, which cause the dma memory leak issue.
This patch use another method to map the dma memory for the mrq->data which can fix this dma memory leak issue.
--- drivers/mmc/host/sdhci.c | 67 +++++++++++++++++------------------------------ drivers/mmc/host/sdhci.h | 8 ++--- include/linux/mmc/core.h | 1 3 files changed, 30 insertions(+), 46 deletions(-)
drivers/mmc/host/sdhci.c +25 -42
@@ -55,8 +55,7 @@ static int sdhci_execute_tuning(struct mstatic void sdhci_tuning_timer (unsigned long data);static void sdhci_enable_preset_value (struct sdhci_host *host,bool enable);static int sdhci_pre_dma_transfer (struct sdhci_host *host, -struct mmc_data *data, -struct sdhci_host_next *next); +struct mmc_data *data);static int sdhci_do_get_cd (struct sdhci_host *host);#ifdef CONFIG_PM
@@ -510,7 +509,7 @@ static int sdhci_adma_table_pre(struct s goto fail;BUG_ON (host->align_addr & host->align_mask); - host->sg_count =sdhci_pre_dma_transfer (host, data,NULL ); + host->sg_count =sdhci_pre_dma_transfer (host, data);if (host->sg_count <0 ) goto unmap_align;
@@ -649,9 +648,11 @@ static void sdhci_adma_table_post(struct } } -if (!data->host_cookie) +if (data->host_cookie ==COOKIE_MAPPED ) {dma_unmap_sg (mmc_dev (host->mmc), data->sg, data->sg_len, direction); + data->host_cookie =COOKIE_UNMAPPED ; + } }static u8 sdhci_calc_timeout (struct sdhci_host *host,struct mmc_command *cmd)
@@ -847,7 +848,7 @@ static void sdhci_prepare_data(struct sd }else {int sg_cnt; - sg_cnt =sdhci_pre_dma_transfer (host, data,NULL ); + sg_cnt =sdhci_pre_dma_transfer (host, data);if (sg_cnt <=0 ) {/* * This only happens when someone fed
@@ -963,11 +964,13 @@ static void sdhci_finish_data(struct sdhif (host->flags &SDHCI_USE_ADMA )sdhci_adma_table_post (host, data);else { -if (!data->host_cookie) +if (data->host_cookie ==COOKIE_MAPPED ) {dma_unmap_sg (mmc_dev (host->mmc), data->sg, data->sg_len, (data->flags &MMC_DATA_READ ) ?DMA_FROM_DEVICE :DMA_TO_DEVICE ); + data->host_cookie =COOKIE_UNMAPPED ; + } } }
@@ -2131,49 +2134,36 @@ static void sdhci_post_req(struct mmc_hostruct mmc_data *data = mrq->data;if (host->flags &SDHCI_REQ_USE_DMA ) { -if (data->host_cookie) +if (data->host_cookie ==COOKIE_GIVEN || + data->host_cookie ==COOKIE_MAPPED )dma_unmap_sg (mmc_dev (host->mmc), data->sg, data->sg_len, data->flags &MMC_DATA_WRITE ?DMA_TO_DEVICE :DMA_FROM_DEVICE ); - mrq->data->host_cookie =0 ; + data->host_cookie =COOKIE_UNMAPPED ; } }static int sdhci_pre_dma_transfer (struct sdhci_host *host, -struct mmc_data *data, -struct sdhci_host_next *next) +struct mmc_data *data) {int sg_count; -if (!next && data->host_cookie && - data->host_cookie != host->next_data.cookie) { -pr_debug (DRIVER_NAME "[%s] invalid cookie: %d, next-cookie %d\n" , - __func__, data->host_cookie, host->next_data.cookie); - data->host_cookie =0 ; +if (data->host_cookie ==COOKIE_MAPPED ) { + data->host_cookie =COOKIE_GIVEN ; +return data->sg_count; } -/* Check if next job is already prepared */ -if (next || - (!next && data->host_cookie != host->next_data.cookie)) { - sg_count =dma_map_sg (mmc_dev (host->mmc), data->sg, - data->sg_len, - data->flags &MMC_DATA_WRITE ? -DMA_TO_DEVICE :DMA_FROM_DEVICE ); - - }else { - sg_count = host->next_data.sg_count; - host->next_data.sg_count =0 ; - } +WARN_ON (data->host_cookie ==COOKIE_GIVEN ); + sg_count =dma_map_sg (mmc_dev (host->mmc), data->sg, data->sg_len, + data->flags &MMC_DATA_WRITE ? +DMA_TO_DEVICE :DMA_FROM_DEVICE );if (sg_count ==0 ) -return -EINVAL ; +return -ENOSPC ; -if (next) { - next->sg_count = sg_count; - data->host_cookie = ++next->cookie <0 ?1 : next->cookie; - }else - host->sg_count = sg_count; + data->sg_count = sg_count; + data->host_cookie =COOKIE_MAPPED ;return sg_count; }
@@ -2183,16 +2173,10 @@ static void sdhci_pre_req(struct mmc_hos {struct sdhci_host *host =mmc_priv (mmc); -if (mrq->data->host_cookie) { - mrq->data->host_cookie =0 ; -return ; - } + mrq->data->host_cookie =COOKIE_UNMAPPED ;if (host->flags &SDHCI_REQ_USE_DMA ) -if (sdhci_pre_dma_transfer (host, - mrq->data, - &host->next_data) <0 ) - mrq->data->host_cookie =0 ; +sdhci_pre_dma_transfer (host, mrq->data); }static void sdhci_card_event (struct mmc_host *mmc)
@@ -3090,7 +3074,6 @@ int sdhci_add_host(struct sdhci_host *ho host->max_clk = host->ops->get_max_clock (host); } - host->next_data.cookie =1 ;/* * In case of Host Controller v3.00, find out whether clock * multiplier is supported.
drivers/mmc/host/sdhci.h +4 -4
@@ -309,9 +309,10 @@ struct sdhci_adma2_64_desc {*/ #define SDHCI_MAX_SEGS 128 -struct sdhci_host_next { -unsigned int sg_count; -s32 cookie; +enum sdhci_cookie { +COOKIE_UNMAPPED , +COOKIE_MAPPED , +COOKIE_GIVEN , };struct sdhci_host {
@@ -506,7 +507,6 @@ struct sdhci_host {#define SDHCI_TUNING_MODE_1 0struct timer_list tuning_timer;/* Timer for tuning */ -struct sdhci_host_next next_data;unsigned long private[0 ]____cacheline_aligned ; };
include/linux/mmc/core.h +1 -0
@@ -121,6 +121,7 @@ struct mmc_data {struct mmc_request *mrq;/* associated request */ unsigned int sg_len;/* size of scatter list */ +int sg_count;/* mapped sg entries */ struct scatterlist *sg;/* I/O scatter list */ s32 host_cookie;/* host private data */ };
Patches currently in stable-queue which might be from [email protected] are
queue-4.1/mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch