From patchwork Mon May 1 21:43:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrian Chadd X-Patchwork-Id: 9707057 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A60E3602B5 for ; Mon, 1 May 2017 21:44:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 96DD4206E2 for ; Mon, 1 May 2017 21:44:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8BB3B282E2; Mon, 1 May 2017 21:44:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 22FFC206E2 for ; Mon, 1 May 2017 21:44:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753120AbdEAVnq (ORCPT ); Mon, 1 May 2017 17:43:46 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:33837 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752377AbdEAVnm (ORCPT ); Mon, 1 May 2017 17:43:42 -0400 Received: by mail-pf0-f194.google.com with SMTP id g23so29369397pfj.1 for ; Mon, 01 May 2017 14:43:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id; bh=OZemZTCgDHJBAIdF0cbq4aNKsXqFez5gwPQh15uKj4Y=; b=aKXCatfhZI/+wV4LxZdo+Yr9EtyM3gR4S/mSQQzZrjxvJAzMgyl2qOLjSO7QhmB/no Hvs/J7mVzQEs+HjX20q3A1EIv/ek/L98Fkv5dEDGyrZHVNcRrHLuOgzamLsv4M6EG6BE vFXlhfSm9d6UWjtCuF3IjTsrwU8Q/GU2U2cbaEpsCAml0crjZMaqNI+QVuBpYxZtY+je GbaoHH1sLdrFe6SsBinmYLDZnR9tLQM/ZIxhw/0XoqnoheD39uTyhOO9G1XR7KsBYnP3 MKCzZrRWs65XYGQW+4t/cUzFVIC5VJte0U3py3nU0/G6mwYvcUxxyTVmQD9Cqyq3/SSK m6nQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id; bh=OZemZTCgDHJBAIdF0cbq4aNKsXqFez5gwPQh15uKj4Y=; b=C0L0IQ5zDD6f6XOLjMQXpMU8za1yBwaFc7q9TseD4Ey/bftNswzKUEZP5IsK9rJhNI ZdpSE3U6H8a4Hlp92qRCl6tDC8VAWlwduIkAquX55w541HWn028PUu7x+/ZEN5sIa++e 3c5LpzI9SYUg3a0Ln/ZCzvudOIRCUC4sRdpiTfYl2XcAbP6XBgh73ruSRw+7Dl5xUy9k ZUEsEUF6S2Go0W30K/HHdNIN7jqseh9G9WmvrBp814tV7FXcE1MtFYTWLf4v2v/Gz0ho v1KXGrFoCwN6DlW/xWGSqajcALNuKhHsCiPHuJ/ooLXYLBuWmR2ImwqTGibHTE04UOKU OptQ== X-Gm-Message-State: AN3rC/7i7vf5H0AcMHMaVaQD3yaK1gLNoXemOCwaWfxPPJroe/eE24iU xTgqd1Xtt7IR9zhDHqc= X-Received: by 10.84.132.33 with SMTP id 30mr37430260ple.46.1493675016601; Mon, 01 May 2017 14:43:36 -0700 (PDT) Received: from gertrude.bwrwc.bowers-wilkins.com ([4.14.32.251]) by smtp.gmail.com with ESMTPSA id y68sm3133201pfi.13.2017.05.01.14.43.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 01 May 2017 14:43:35 -0700 (PDT) From: Adrian Chadd To: ath10k@lists.infradead.org, Kalle Valo , linux-wireless@vger.kernel.org Cc: Adrian Chadd , Adrian Chadd Subject: [PATCH] [ath10k] go back to using dma_alloc_coherent() for firmware scratch memory. Date: Mon, 1 May 2017 14:43:27 -0700 Message-Id: <20170501214327.5621-1-adrian@freebsd.org> X-Mailer: git-send-email 2.11.1 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This reverts b057886524be060021e3cfad0ba8458c850330cd in 2015 which converted this allocation from dma_map_coherent() to kzalloc() / dma_map_single(). The current problem manifests when using later model NICs with larger (>700KiB) scratch spaces in memory. Although the kzalloc call succeeds, the software IOMMU TLB code (via dma_map_single()) panics because it can't find 700KiB of linear physmem bounce buffers for DMA. Now, this is a bit of a silly failure mode for the dma map API, but it's what we currently have to play with. In these cases, doing kzalloc() works fine, but the dma_map_single() call fails. After chatting with Linus briefly about this, it indeed should be using dma_alloc_coherent() for doing larger device memory allocation that requires some kind of physical address mapping. You're not supposed to be using kzalloc and dma_map_* calls for large memory regions, and I'm guessing not for long-held mappings either. Typically dma mappings should be temporary for DMA, not long held like these. Now, since hopefully the major annoying underlying problem has also been addressed (ie, ath10k is no longer tears down all of these allocations and reallocates them every time the vdevs are brought down) fragmentation should stop being such a touchy issue. If it is though, using dma_alloc_coherent() use gets us access to the CMB APIs too relatively easily and ideally we would be allocating memory early in boot for exactly these reasons. Signed-off-by: Adrian Chadd Tested-by: Sven Eckelmann --- drivers/net/wireless/ath/ath10k/wmi.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 6afc8d2..cc89f53 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4482,31 +4482,17 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id, u32 num_units, u32 unit_len) { dma_addr_t paddr; - u32 pool_size = 0; + u32 pool_size; int idx = ar->wmi.num_mem_chunks; - void *vaddr = NULL; - - if (ar->wmi.num_mem_chunks == ARRAY_SIZE(ar->wmi.mem_chunks)) - return -ENOMEM; + void *vaddr; - while (!vaddr && num_units) { - pool_size = num_units * round_up(unit_len, 4); - if (!pool_size) - return -EINVAL; + pool_size = num_units * round_up(unit_len, 4); + vaddr = dma_alloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL); - vaddr = kzalloc(pool_size, GFP_KERNEL | __GFP_NOWARN); - if (!vaddr) - num_units /= 2; - } - - if (!num_units) + if (!vaddr) return -ENOMEM; - paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_BIDIRECTIONAL); - if (dma_mapping_error(ar->dev, paddr)) { - kfree(vaddr); - return -ENOMEM; - } + memset(vaddr, 0, pool_size); ar->wmi.mem_chunks[idx].vaddr = vaddr; ar->wmi.mem_chunks[idx].paddr = paddr; @@ -8290,11 +8276,10 @@ void ath10k_wmi_free_host_mem(struct ath10k *ar) /* free the host memory chunks requested by firmware */ for (i = 0; i < ar->wmi.num_mem_chunks; i++) { - dma_unmap_single(ar->dev, - ar->wmi.mem_chunks[i].paddr, - ar->wmi.mem_chunks[i].len, - DMA_BIDIRECTIONAL); - kfree(ar->wmi.mem_chunks[i].vaddr); + dma_free_coherent(ar->dev, + ar->wmi.mem_chunks[i].len, + ar->wmi.mem_chunks[i].vaddr, + ar->wmi.mem_chunks[i].paddr); } ar->wmi.num_mem_chunks = 0;