Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755021AbbHYB7G (ORCPT ); Mon, 24 Aug 2015 21:59:06 -0400 Received: from mail-bn1bn0101.outbound.protection.outlook.com ([157.56.110.101]:20928 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751841AbbHYB7D (ORCPT ); Mon, 24 Aug 2015 21:59:03 -0400 Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=freescale.com; vger.kernel.org; dkim=none (message not signed) header.d=none; From: Haibo Chen To: , CC: , , , , Subject: [PATCH] mmc: sdhci: fix dma memory leak in sdhci_pre_req() Date: Tue, 25 Aug 2015 10:02:11 +0800 Message-ID: <1440468131-9473-1-git-send-email-haibo.chen@freescale.com> X-Mailer: git-send-email 1.9.1 X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11FD012;1:Sw0IcjlXqtQRpqSc9uRt+OVWlJQJqwld//HJ0hCG1Iu5TYa3sBTa7HDjg2mUOGNVB/saeCXhkgtOjNp/uPR5i9uCUrpBPDbu0/kK5z9NlyEmdQkbwO5ULLM1xjmQGd+Viryi0hqIqGnxp/BHBA9p64joUQ40TWoR0ZqTZDtgVhCVoVgVsackIWjn1FXrWGEbHj3VngnixxT+pG3j8S/76W4MVKtryR7wEVXj7WeZKTDXKeX7xjdOjzNre6Qh+t1817/Fw4y8GG85TFdibGwhJ/6x0QlmNXs93jym0+Wje8fPm3OnCx+fPrV8iIhRTXuhe4FnhjS9uSpjZVoBEUOWcM/OpSyfWVz+AmVF8aciuySrpN9Jg5D2bCi/G5tc4AfINeOGeFvDsR+OnCZBHemXig== X-Forefront-Antispam-Report: CIP:192.88.158.2;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10019020)(6009001)(2980300002)(339900001)(3050300001)(189002)(199003)(33646002)(106466001)(47776003)(64706001)(50986999)(105606002)(229853001)(104016003)(46102003)(87936001)(19580405001)(68736005)(6806004)(77096005)(19580395003)(77156002)(5003940100001)(50226001)(5007970100001)(50466002)(48376002)(85426001)(69596002)(36756003)(92566002)(86362001)(5001770100001)(5001960100002)(81156007)(5001860100001)(97736004)(189998001)(4001540100001)(5001830100001)(5001920100001)(62966003);DIR:OUT;SFP:1102;SCL:1;SRVR:BY1PR03MB1417;H:az84smr01.freescale.net;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;MX:1;A:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BY1PR03MB1417;2:EhukNISuBLO9S/6QX6ckrAxi7tXMoZmUmN7UaZ+fUqb+GAvK1xhhAgrM0z1dkDgQzNMpH6M7HKNKcCRz++YogOnIWeE19ZCDZ1JfudQvaNIP3adHX2rVadmGYa6fYiW5XA4iP3pkOWdPwKNb9H7aKBThcbz90zP1vt9X/uj+INI=;3:Vzr2JbWjTNFyIuDXXjM5oDEGyATQx6v6B9YhGj3UmuvS8BLit1omkR6B3HMykU5CE954FeGMQK2QSJav1GKCtPT0MCdsukYB1GazUnkjNr+nl3oF3ffZiLJOSoNlYgHJiiTnWoPKNuuNetETL24y0p9Blr4jZopqf7huVcTyZ7JCTfIIYU6EFJaOYIYm+Aji3HXmKF7QNVpm0nqYtn5a4oa1l50BfyNJKF1SzHM/rcY=;25:vbdoAfvbDe+zSAcgdF2qXqNmS9Yy9nAkYg14K3NaKhSauxJ1qhcyvSV29Sh/Q9TrkuDhoqlUSywvNec/cLF2Ab2sCSvav30xX90foeztXdkNqWaNvYMHnzGfLRnecasviHki3oTydw0/3R8Rcr66IQV5qGUQQnak0diWCzX+cRl0S5+u/u1TaU2/JYGoQVaNkIerX0+eF21UcnWItP1LhkRDYfm3evBwwWRSBrfgc1t05aMW5cF40HPY8QDd0ipuIz7QYgDmICJbx2xqGrIISg== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY1PR03MB1417; X-Microsoft-Exchange-Diagnostics: 1;BY1PR03MB1417;20:fVW+9GyMHPSKxXh5086KNAhmdJz7TtSWOgLxmzgQxm00wAV3KiNnRttE0/0YlWZTpQAOH9ZGjX1OtamsJcSQmnX8OHfRKKf65bgPL63t1jfsWJhjLuLveeI/b6j6ODUOHPwkzyU+AAPyxyR47PNv3fP5T7NqIhag34LBpeRdSXq8g1oHJ07+wE8txh8ucxL5aex7qNcgEmZNjwy/wzEjpdsH8RNbdibOs2plDE0wL089e8kg0kEG0Tg3YpdmrpgF63VqA82BLjU3RzHLRHx2hONfzYKfJEwZ9wm4PUF9Sfr358D9l0CGzQgVkWPkRYAXOAI9TSFAyX/zh1HIwzDG6f3a4pGkniwmsDEEHAQIl/w=;4:TAsyayAwXDkZm5Y8DKwQpQQrrLbJkhj8qu7gsZeVT9TCQy+cveZH+sQcaWtNiY6k1EjtIhBw517IMmbthH0dCkP6L471pX60Zw9/c6MDwpv3fREaKBQId4Lm+pPPAIVpqhpCFicFLzPlrsVAJ4/nwEh+OzBOLZfKhgJ+9opixukZ6QEYZU3S4ViJhbCyodLQVb0Odly12HQtxRSWbWdplPPDNfXVLWp5cJStJnfbHO/YFjguje9rw+6fhkXYBOXMJe1qazWJYNzLbvghsVGc9+1cpR6m/KGBnXessuVKnKTl7fP3I6bymRKS6iqm0f3I X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(8121501046)(3002001);SRVR:BY1PR03MB1417;BCL:0;PCL:0;RULEID:;SRVR:BY1PR03MB1417; X-Forefront-PRVS: 06793E740F X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BY1PR03MB1417;23:W20spXe1KVbZ3r/mBKfHPetfE+CgWjkJgxh3xCUUz?= =?us-ascii?Q?7UkiDfRlezJuwZM4ttXw36MThZy1JCkN06q25BATlWQuhjkZCHR+OMDnLQU8?= =?us-ascii?Q?uTA1cVpaAwhdwAPfyerTTjf4bJFYJu+IXANMEx8838kMVTu/rA77doiVe3xp?= =?us-ascii?Q?Zyr+xrlydUgg6NaCe+QCKd49dBNmWBBl1fw6Z7q4urczFa+7POdx82ZhZz8j?= =?us-ascii?Q?FH58696IQgTsSL9DBEerPko0huKMJuczRSJPT2b3Qe+gSi2ocqfYu74vHBuU?= =?us-ascii?Q?/g04MvJVysxudILI2hTt9LTk9TRw7wQGtu0QEyT9UQLFC2IMMU9tTahHQFqc?= =?us-ascii?Q?cdP7TiG4s+ErCAceRf9kgm0//Yak+y3HLQVE33bvAjVLyNa2mAeBEGni/VDz?= =?us-ascii?Q?ui3izeuPbAa0aqgcFb/V5Eo8deK03uTv6jcK6pE0XbfDcCxhOnjhEXgOy5Qw?= =?us-ascii?Q?gdvKCi16kZDRk/elQUiIBv1FqQbWJAruFW3o1IAinUYcQBANFU3QJFrLJKKE?= =?us-ascii?Q?OMWq9Fds7RmwhT3L91h6lut2sorN5cJr0FHugko66ZEuO3N6+gx2Lv/scBCC?= =?us-ascii?Q?bs5H31Efx6ySlVclZGs2iZwfK+wVqHEqZfNcWSeULNj7JSbnrzUVZ+YqeyGi?= =?us-ascii?Q?0A5Qb1jPMNyjcWKctgOl8u85DDBsvoDfQhrZPSXFbc6q4UY5GmZt8TbzJai4?= =?us-ascii?Q?oOx8ZcaYjTcVdLteebEmHqnNDK3BdxXQ63yi0dDs9X35hw159J9SnM+G95UM?= =?us-ascii?Q?X5QxOhWhjor/1JJBXyFV8YlQJFPoe7ykBwPYZOQXvntd+YPkrQ24ft51od/F?= =?us-ascii?Q?hvTX61E1UFDbgJ4rfAiERhDGaZp/UYmGAZeW1SXitnjGXewejNvdMaTMkcO2?= =?us-ascii?Q?g87zVpaE+eQ8sHl9YgKgM3PkavAnMwJx8l62BMcWuAW13nYEnlrvLMFx0I9M?= =?us-ascii?Q?83JROb3k8ApnRCiuf0S48U7gbri0pO8htkBCqGj5wEvxCeN93qbSwA8fe2oC?= =?us-ascii?Q?Km2GgKmpqW7KYNqBoTvANqwWNMKg2mdC0MecuaDJR1RpdQibvbVYFFGn5wgG?= =?us-ascii?Q?TjJMWvz1igZbbFqm0ebgm6MXSPbDwqEke5e4j/jG8kbRD1NRzM+oox00kYBw?= =?us-ascii?Q?9JQqg3a1F5F8AXku74ivl873/+ATqhOuRgasDXZ3KxDNgTUOgAP/Q=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;BY1PR03MB1417;5:iouzoibzCntpXpCYt4uCzy000S0S35WTpi15QB1frgdaYMErNl+y5mGNaKZAFscIXi+isFFeFBHFX5/arsDwrqCt5WViQZzWXu4iC4DSfmJmnmNwYytBoBEWdBl5t79zGe1xafMHTjvo07YlrG7OWA==;24:9G40vHv+disWOWLrM+PTG1OD28N0VN3GKfQja0mDKuxAG7aurTENmg/LIhtZKEK3DY1djRdo/WbQsjR7i6tVCYzBadXrvCDxKipNvn/2GWQ=;20:dK1IvkzbIT6u+8vR70Ib40sMrtaXwvG9uwgXS0N3iOUcDyIr00+WPlAMvZV3cFFduCsbn6vXFzrgmZuM9KF7rA== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Aug 2015 01:59:00.1076 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d;Ip=[192.88.158.2];Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY1PR03MB1417 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6623 Lines: 207 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. Fixes: commit 348487cb28e66b0 ("mmc: sdhci: use pipeline mmc requests to improve performance") Cc: stable@vger.kernel.org # 4.0+ Reported-and-tested-by: Jiri Slaby Signed-off-by: Haibo Chen --- drivers/mmc/host/sdhci.c | 67 ++++++++++++++++++------------------------------ drivers/mmc/host/sdhci.h | 8 +++--- 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c83d110..8d2864b 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -54,8 +54,7 @@ static void sdhci_finish_command(struct sdhci_host *); static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); 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 @@ -495,7 +494,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, 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; @@ -634,9 +633,11 @@ static void sdhci_adma_table_post(struct sdhci_host *host, } } - 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) @@ -832,7 +833,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } 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 @@ -948,11 +949,13 @@ static void sdhci_finish_data(struct sdhci_host *host) if (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; + } } } @@ -2105,49 +2108,36 @@ static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, struct 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; } @@ -2157,16 +2147,10 @@ static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, { 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) @@ -3038,7 +3022,6 @@ int sdhci_add_host(struct sdhci_host *host) 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. diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 67046ca..7c02ff4 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -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 { @@ -505,7 +506,6 @@ struct sdhci_host { unsigned int tuning_mode; /* Re-tuning mode supported by host */ #define SDHCI_TUNING_MODE_1 0 - struct sdhci_host_next next_data; unsigned long private[0] ____cacheline_aligned; }; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/