Received: by 10.192.165.156 with SMTP id m28csp709830imm; Mon, 16 Apr 2018 07:30:57 -0700 (PDT) X-Google-Smtp-Source: AIpwx48yhtN474Ze1VrWGygS/Ax7qBOlvUAzriG+VbRHVdMmW6cLhh1UbgIUQOIJzTNsUP2QQ3mt X-Received: by 2002:a17:902:da4:: with SMTP id 33-v6mr15553683plv.52.1523889056958; Mon, 16 Apr 2018 07:30:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523889056; cv=none; d=google.com; s=arc-20160816; b=0Tliyd8wbhuCY8Qmrltt4fSJjZ4elFlsV4J+FZTINFyFwAhaO9j+TgnlApURDhZhRK 8k1kYlH9cyZ6+V2NYmz071elIC0iYm5mVcqJLr/hGjeEN9Q8APaKg9gSGrU72r7EwPzn CLGzMJEfvZcSF4qXxv42RLfPuU4inahOYawCGtx8PPJPgQBcvIc5ooqIvTct55I6+I7w ypjudwvjMMiLLB/kb7CS8I1Hr9V8DnSFSwf+sScJhzCmqj1jDWvozaK3gBT5VWF4I0Mg DQGKNmk7aQxftho1npKmwwC9l7Z55uVSERhSxKlFWLZx+0dHrNxUsHVgXzWNj6iXSzeE rBLw== 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 :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:dkim-signature :arc-authentication-results; bh=EGtNfkuWQDK+EixjliwclWpGWnKtEedQ+W/BihIXvNM=; b=S3Si/jNUTkYVybkKfqaoPjCPJqmP/3Cf8Z15RJKJZaDXexqfwUS6ukftQlkWpiYLfA VmD1UKbedloPnLBR+2Qjt/JjSsM5KueOvopa+ViGyvJjAkIKbo+YfDSGHanqUDxoYkPU glt3BYMovCFbSRXp3USehaoHDXzT6eUrE8/VXkb7lTNT8qjIeavY3yWI3v2fGo+CTQ/m KINssK/kO6Qz9k5bjl1UKWC7jZZCkyOVbL/sopa3UVQib3QIy4R7gQjYOKSzg2nJ5IPG KaOhSOGImRa55pgghvSU9J16uBEmY8gFhzYX5EiFR4NZ0gfKFkJCscmI9Y6CCSDlUl2M LsAQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=cnPr4sCy; 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; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s10-v6si12692865plq.240.2018.04.16.07.30.43; Mon, 16 Apr 2018 07:30:56 -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; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=cnPr4sCy; 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; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754047AbeDPLf3 (ORCPT + 99 others); Mon, 16 Apr 2018 07:35:29 -0400 Received: from lelnx193.ext.ti.com ([198.47.27.77]:12900 "EHLO lelnx193.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752058AbeDPLf1 (ORCPT ); Mon, 16 Apr 2018 07:35:27 -0400 Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by lelnx193.ext.ti.com (8.15.1/8.15.1) with ESMTP id w3GBYVkq011034; Mon, 16 Apr 2018 06:34:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ti.com; s=ti-com-17Q1; t=1523878471; bh=1f4M0SO4smiLDtCRG0x+Xrv19Oy8YSU08qrX7bX46NI=; h=Subject:To:CC:References:From:Date:In-Reply-To; b=cnPr4sCy6tPKtKMDv7ycV0ziKrrQEMiwoIuYwCwdXWF0bx/MIdFRcpXKUIBNMKcv4 eqr592oClyRZnU9pSKnC8mgA/xufV25XHaJXTbj0mYeI2skQldGMdxTzXzNmzWY5Uv u32lJtlN6/MIxM0+SMfT+40Ml29wc1vFR9+PgLCQ= Received: from DLEE110.ent.ti.com (dlee110.ent.ti.com [157.170.170.21]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id w3GBYVu3028759; Mon, 16 Apr 2018 06:34:31 -0500 Received: from DLEE109.ent.ti.com (157.170.170.41) by DLEE110.ent.ti.com (157.170.170.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1261.35; Mon, 16 Apr 2018 06:34:31 -0500 Received: from dlep33.itg.ti.com (157.170.170.75) by DLEE109.ent.ti.com (157.170.170.41) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1261.35 via Frontend Transport; Mon, 16 Apr 2018 06:34:31 -0500 Received: from [192.168.2.6] (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id w3GBYSHl023452; Mon, 16 Apr 2018 06:34:29 -0500 Subject: Re: [PATCH v2] mtd: onenand: omap2: Disable DMA for HIGHMEM buffers To: Ladislav Michl , , CC: Boris Brezillon , Roger Quadros , Aaro Koskinen , Tony Lindgren , "H. Nikolaus Schaller" , Andreas Kemnade References: <20180416065256.GA24455@lenoch> From: Peter Ujfalusi Message-ID: <8b073dce-2a9e-5068-6499-a36915f5ed90@ti.com> Date: Mon, 16 Apr 2018 14:34:54 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 MIME-Version: 1.0 In-Reply-To: <20180416065256.GA24455@lenoch> Content-Type: text/plain; charset="utf-8" Content-Language: en-US Content-Transfer-Encoding: 8bit X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2018-04-16 09:52, Ladislav Michl wrote: > dma_map_single doesn't get the proper DMA address for vmalloced area, Which is not a big surprise as vmalloc will allocate contiguous virtual memory (which might corresponds to non-contiguous physical memory). Even if you somehow get the physical address of the start of the vmalloced buffer, you don't really know how long that chunk is and where the buffer continues in physical memory. Creating sg_list of the vmalloced buffer should be possible also by walking the virt memory and get the pages with vmalloc_to_page(). I don't think there is a generic vmalloc_to_sg(), one can be implemented. > so disable DMA in this case. > > Signed-off-by: Ladislav Michl > Reported-by: "H. Nikolaus Schaller" > Tested-by: "H. Nikolaus Schaller" > --- > Changes: > -v2: Added Tested-by tag, based on v4.17-rc1 (no change in patch itself) > > 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); > - Péter Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki