From patchwork Mon Jul 21 20:47:26 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Gorski X-Patchwork-Id: 372200 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2001:1868:205::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2A0B1140143 for ; Tue, 22 Jul 2014 06:49:28 +1000 (EST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1X9KVB-0008Rc-97; Mon, 21 Jul 2014 20:48:05 +0000 Received: from arrakis.dune.hu ([78.24.191.176]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X9KV7-0008OM-MZ for linux-mtd@lists.infradead.org; Mon, 21 Jul 2014 20:48:02 +0000 Received: from localhost (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 6C927284138; Mon, 21 Jul 2014 22:45:23 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=ALL_TRUSTED,BAYES_00 autolearn=ham version=3.3.2 X-Virus-Scanned: at arrakis.dune.hu Received: from ixxyvirt.lan (dslb-088-073-029-079.pools.arcor-ip.net [88.73.29.79]) by arrakis.dune.hu (Postfix) with ESMTPSA id D7FCD281621; Mon, 21 Jul 2014 22:45:17 +0200 (CEST) From: Jonas Gorski To: linux-mtd@lists.infradead.org Subject: [PATCH 1/3] mtd: simple_map: make NO_XIP actually prevent unaligned accesses Date: Mon, 21 Jul 2014 22:47:26 +0200 Message-Id: <1405975648-25375-2-git-send-email-jogo@openwrt.org> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1405975648-25375-1-git-send-email-jogo@openwrt.org> References: <1405975648-25375-1-git-send-email-jogo@openwrt.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140721_134801_907514_B1A77B41 X-CRM114-Status: GOOD ( 16.09 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- Cc: Artem Bityutskiy , Kevin Cernekee , Gregory Fong , Maxime Bizon , Stefan Roese , David Woodhouse , Florian Fainelli X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Some mapping drivers set the map->phys pointer to NO_XIP intending to mean "no unaligned accesses" (see also the DT property of physmap_of). But simple mapping read_from/write_to still just call memcpy, which will do unaligned reads/writes at least on mips. To work around this, make the inline version check for NO_XIP and do a byte wise copy if "to" or "from" is unaligned. Signed-off-by: Jonas Gorski --- include/linux/mtd/map.h | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 5f487d7..92a8a0a 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -435,15 +435,35 @@ static inline void inline_map_write(struct map_info *map, const map_word datum, static inline void inline_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { - if (map->cached) + if (map->cached) { memcpy(to, (char *)map->cached + from, len); - else + } else if (map->phys != NO_XIP || + (IS_ALIGNED((unsigned long)to, sizeof(long)) && + IS_ALIGNED((unsigned long)map->virt + from, + sizeof(long)))) { memcpy_fromio(to, map->virt + from, len); + } else { + void __iomem *src = map->virt + from; + char *dst = (char *)to; + + while (len--) + *dst++ = readb(src++); + } } static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) { - memcpy_toio(map->virt + to, from, len); + if (map->phys != NO_XIP || + (IS_ALIGNED((unsigned long)map->virt + to, sizeof(long)) && + IS_ALIGNED((unsigned long)from, sizeof(long)))) { + memcpy_toio(map->virt + to, from, len); + } else { + char *src = (char *)from; + void __iomem *dst = map->virt + to; + + while (len--) + writeb(*src++, dst++); + } } #ifdef CONFIG_MTD_COMPLEX_MAPPINGS