Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp3708941imm; Mon, 18 Jun 2018 02:44:04 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKc9PQx61c+ilZlzd1IgVAD48lTPpVeVxbz04YAo2+DW9cVNWtjW/2r6jJyhLhz0CJXwnVW X-Received: by 2002:a17:902:8348:: with SMTP id z8-v6mr13165826pln.239.1529315044732; Mon, 18 Jun 2018 02:44:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529315044; cv=none; d=google.com; s=arc-20160816; b=ao9pv7UnWrrJRZGwcFxbUbzPUDqooDWrIf5O1WQ6HMrEyqEG6JouW6BomSD1MBvfMW WsE9Kvn9hknAeodmjgrKMzgjofKOlunTGmneWovTRcBW7VOYiyTqZqmax+FSCJINkpvV Wb9hW23oh6x0DQ8/DH04oxYKIFgTX3qU/QKCG+GCHYiZOHs0aWsm1jIyc4Dd1zYlTzK1 MA+mybKwqABqsrXv8de6Q6hlSRvHOQtePpvVjHXLzvRoOo5l/+qbBzLBGSEVZUY0ezcB GZ5fVvOVRgW2PmPlm5rG9e6C9X5JFkC+JJYVnS5zfZanEAuI3FETLvVHE/sS1je/meFg 7ZEw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=0lmdXZKD8gtX1i8mF4btWO63ERvILWWeIJXbWS0Kwvs=; b=FLQWNc7RyVWygNrW8daT5EdlcTIMjXAo0jvl8GvFoyHBoV7B3v9zJDLMhDqu6JFX9l uWGBDLf52JSUSJ/bj85HCBA9udoERVwKVc+e+KcNAlbz1iSrbi+KjqDfce86mQfK1T74 0//lRo7lw4FDl8cnK6mC+P+bL0xrZcdSRrJwyjl29VcBy/kjW9fzlWAozrBDgcBemaCO ziB31YiJohDiTzwYZ62MDiT1R3uP6IlOl2RvN+gbXWG98DjWGKWacCJFOHkcVyLM4tZs 7FX0Mo4CzP0H/er2ywgjo9B/VptfDH5jxa8bjFiRsYWqrqhlKdScpwRqByxzaCAPFb6n MwxQ== 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 y16-v6si13578321pfn.111.2018.06.18.02.43.51; Mon, 18 Jun 2018 02:44:04 -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 S965487AbeFRIW0 (ORCPT + 99 others); Mon, 18 Jun 2018 04:22:26 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:55520 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965435AbeFRIWY (ORCPT ); Mon, 18 Jun 2018 04:22:24 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 494A2C7A; Mon, 18 Jun 2018 08:22:23 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Ladislav Michl , "H. Nikolaus Schaller" , Peter Ujfalusi , Boris Brezillon , Sasha Levin Subject: [PATCH 4.16 155/279] mtd: onenand: omap2: Disable DMA for HIGHMEM buffers Date: Mon, 18 Jun 2018 10:12:20 +0200 Message-Id: <20180618080615.243663438@linuxfoundation.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180618080608.851973560@linuxfoundation.org> References: <20180618080608.851973560@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Ladislav Michl [ Upstream commit 6732cfd4cac514b556f36b518670af91c8bdf19a ] 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" Reviewed-by: Peter Ujfalusi Signed-off-by: Boris Brezillon Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/onenand/omap2.c | 105 +++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 67 deletions(-) --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -377,56 +377,42 @@ static int omap2_onenand_read_bufferram( { 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); @@ -439,49 +425,34 @@ static int omap2_onenand_write_bufferram { 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);