Received: by 10.192.165.148 with SMTP id m20csp1564067imm; Thu, 3 May 2018 01:20:45 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpvPt9ZpC2SU4MvlbPmLlKV43g8QqBHjy9JaZ2UmkntRUhLUAbP62RRB8shTkBEuYecBH8k X-Received: by 10.98.74.80 with SMTP id x77mr22262128pfa.142.1525335645298; Thu, 03 May 2018 01:20:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525335645; cv=none; d=google.com; s=arc-20160816; b=kfTFW+bVp78jqPrAFY/Ne39D5jrjnt2uRLaih6iX9MyQmItUehXhPATa3eIXgzk8J6 JW69Gj29HNofPGADP8/fc2SbK3Dkhk3DUmHZeBgTz5v1trnyrmUXKbxzUKEkYGtPBaiX hVm1uVAYL+b445Z+NEt068KHXgIpUv6JQNDWW89PUtmBbIHuVlXAu0A4VHQaoZZPC2qI oyh0wVcrM2eKoaF/lRqr5KeWQYKoYu0GYybpoR+y8iypIoQZ3VIYQPvMuy74HmbLT2dS HAaahHw5WpF7bnhLP1g7E9gTFse4QKOQq3nvDXNFuGOXI28P8Lp7qSxBQeEclKjEo3gc MHzQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:subject:cc:to:from:date :arc-authentication-results; bh=l21OFIvDhFBBcYfMwYq0djFr0kHK5Wr7behvuoCJZh0=; b=Tm6D//v8yANXq+BUDFaeH97cnfoPFRpPD7d9tESufRvU+x+mYZU4ELI46W4DSazvoB Ml0p9y0LoSHZjxoU3a4o5tQDc0QsQd3H+6LvSrqKFCkmbNdpop8Ms8qFFB4pTkSPg0ub wzqykx70iQj1yVZr2QUz9GRzzCgJobXF6s5ZuvZrvzwNvSxyUK1CksDOkIO5dBT+Vxdj QiKK74LiS5A6K66IhE+emAoNaccpe2hHArDxKG8tgiq8L7x3SEPegQm8lzMs+IIQdVls 6Vy6MuSHLgDyge9CikWLA3ICSqNbiNPtb9KUY1+Rao26bM4c0MqJ1dbbX7YI5wu716q8 DFBA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 33-v6si12978170plg.34.2018.05.03.01.20.30; Thu, 03 May 2018 01:20:45 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751132AbeECIUA (ORCPT + 99 others); Thu, 3 May 2018 04:20:00 -0400 Received: from mail.bootlin.com ([62.4.15.54]:45190 "EHLO mail.bootlin.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750781AbeECITz (ORCPT ); Thu, 3 May 2018 04:19:55 -0400 Received: by mail.bootlin.com (Postfix, from userid 110) id 7D4AC207B3; Thu, 3 May 2018 10:19:53 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT shortcircuit=ham autolearn=disabled version=3.4.0 Received: from bbrezillon (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.bootlin.com (Postfix) with ESMTPSA id 2602B207CC; Thu, 3 May 2018 10:19:43 +0200 (CEST) Date: Thu, 3 May 2018 10:19:42 +0200 From: Boris Brezillon To: Ladislav Michl Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, Peter Ujfalusi , Roger Quadros , Aaro Koskinen , Tony Lindgren , "H. Nikolaus Schaller" , Andreas Kemnade Subject: Re: [PATCH v3] mtd: onenand: omap2: Disable DMA for HIGHMEM buffers Message-ID: <20180503101942.6851a4fc@bbrezillon> In-Reply-To: <20180502104132.GA12979@lenoch> References: <20180502104132.GA12979@lenoch> X-Mailer: Claws Mail 3.15.0-dirty (GTK+ 2.24.31; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, 2 May 2018 12:41:32 +0200 Ladislav Michl wrote: > dma_map_single does not work for vmalloc-ed buffers, > so disable DMA in this case. > > Signed-off-by: Ladislav Michl > Reported-by: "H. Nikolaus Schaller" > Tested-by: "H. Nikolaus Schaller" Applied to mtd/master. Will be part of the next fixes PR I'll send later this week. Thanks, Boris > --- > Changes: > -v2: Added Tested-by tag, based on v4.17-rc1 (no change in patch itself) > -v3: Reworded commit log > > drivers/mtd/nand/onenand/omap2.c | 105 +++++++++++-------------------- > 1 file changed, 38 insertions(+), 67 deletions(-) > > diff --git a/drivers/mtd/nand/onenand/omap2.c b/drivers/mtd/nand/onenand/omap2.c > index 9c159f0dd9a6..321137158ff3 100644 > --- a/drivers/mtd/nand/onenand/omap2.c > +++ b/drivers/mtd/nand/onenand/omap2.c > @@ -375,56 +375,42 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area, > { > struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd); > struct onenand_chip *this = mtd->priv; > - dma_addr_t dma_src, dma_dst; > - int bram_offset; > + struct device *dev = &c->pdev->dev; > void *buf = (void *)buffer; > + dma_addr_t dma_src, dma_dst; > + int bram_offset, err; > size_t xtra; > - int ret; > > bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset; > - if (bram_offset & 3 || (size_t)buf & 3 || count < 384) > - goto out_copy; > - > - /* panic_write() may be in an interrupt context */ > - if (in_interrupt() || oops_in_progress) > + /* > + * If the buffer address is not DMA-able, len is not long enough to make > + * DMA transfers profitable or panic_write() may be in an interrupt > + * context fallback to PIO mode. > + */ > + if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 || > + count < 384 || in_interrupt() || oops_in_progress ) > goto out_copy; > > - if (buf >= high_memory) { > - struct page *p1; > - > - if (((size_t)buf & PAGE_MASK) != > - ((size_t)(buf + count - 1) & PAGE_MASK)) > - goto out_copy; > - p1 = vmalloc_to_page(buf); > - if (!p1) > - goto out_copy; > - buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK); > - } > - > xtra = count & 3; > if (xtra) { > count -= xtra; > memcpy(buf + count, this->base + bram_offset + count, xtra); > } > > + dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE); > dma_src = c->phys_base + bram_offset; > - dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE); > - if (dma_mapping_error(&c->pdev->dev, dma_dst)) { > - dev_err(&c->pdev->dev, > - "Couldn't DMA map a %d byte buffer\n", > - count); > - goto out_copy; > - } > > - ret = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count); > - dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE); > - > - if (ret) { > - dev_err(&c->pdev->dev, "timeout waiting for DMA\n"); > + if (dma_mapping_error(dev, dma_dst)) { > + dev_err(dev, "Couldn't DMA map a %d byte buffer\n", count); > goto out_copy; > } > > - return 0; > + err = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count); > + dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE); > + if (!err) > + return 0; > + > + dev_err(dev, "timeout waiting for DMA\n"); > > out_copy: > memcpy(buf, this->base + bram_offset, count); > @@ -437,49 +423,34 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area, > { > struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd); > struct onenand_chip *this = mtd->priv; > - dma_addr_t dma_src, dma_dst; > - int bram_offset; > + struct device *dev = &c->pdev->dev; > void *buf = (void *)buffer; > - int ret; > + dma_addr_t dma_src, dma_dst; > + int bram_offset, err; > > bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset; > - if (bram_offset & 3 || (size_t)buf & 3 || count < 384) > - goto out_copy; > - > - /* panic_write() may be in an interrupt context */ > - if (in_interrupt() || oops_in_progress) > + /* > + * If the buffer address is not DMA-able, len is not long enough to make > + * DMA transfers profitable or panic_write() may be in an interrupt > + * context fallback to PIO mode. > + */ > + if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 || > + count < 384 || in_interrupt() || oops_in_progress ) > goto out_copy; > > - if (buf >= high_memory) { > - struct page *p1; > - > - if (((size_t)buf & PAGE_MASK) != > - ((size_t)(buf + count - 1) & PAGE_MASK)) > - goto out_copy; > - p1 = vmalloc_to_page(buf); > - if (!p1) > - goto out_copy; > - buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK); > - } > - > - dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE); > + dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE); > dma_dst = c->phys_base + bram_offset; > - if (dma_mapping_error(&c->pdev->dev, dma_src)) { > - dev_err(&c->pdev->dev, > - "Couldn't DMA map a %d byte buffer\n", > - count); > - return -1; > - } > - > - ret = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count); > - dma_unmap_single(&c->pdev->dev, dma_src, count, DMA_TO_DEVICE); > - > - if (ret) { > - dev_err(&c->pdev->dev, "timeout waiting for DMA\n"); > + if (dma_mapping_error(dev, dma_src)) { > + dev_err(dev, "Couldn't DMA map a %d byte buffer\n", count); > goto out_copy; > } > > - return 0; > + err = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count); > + dma_unmap_page(dev, dma_src, count, DMA_TO_DEVICE); > + if (!err) > + return 0; > + > + dev_err(dev, "timeout waiting for DMA\n"); > > out_copy: > memcpy(this->base + bram_offset, buf, count);