From: Jan Kara <jack@suse.cz>
To: Dan Williams <dan.j.williams@intel.com>
Cc: "Jan Kara" <jack@suse.cz>,
linux-nvdimm@lists.01.org, david@fromorbit.com,
linux-xfs@vger.kernel.org, linux-mm@kvack.org,
"Jérôme Glisse" <jglisse@redhat.com>,
linux-fsdevel@vger.kernel.org, "Christoph Hellwig" <hch@lst.de>
Subject: Re: [PATCH v9 3/9] memremap: split devm_memremap_pages() and memremap() infrastructure
Date: Wed, 9 May 2018 12:29:11 +0200 [thread overview]
Message-ID: <20180509102911.fqr7p3urcsielgqo@quack2.suse.cz> (raw)
In-Reply-To: <152461279892.17530.9006728553718402327.stgit@dwillia2-desk3.amr.corp.intel.com>
On Tue 24-04-18 16:33:19, Dan Williams wrote:
> Currently, kernel/memremap.c contains generic code for supporting
> memremap() (CONFIG_HAS_IOMEM) and devm_memremap_pages()
> (CONFIG_ZONE_DEVICE). This causes ongoing build maintenance problems as
> additions to memremap.c, especially for the ZONE_DEVICE case, need to be
> careful about being placed in ifdef guards. Remove the need for these
> ifdef guards by moving the ZONE_DEVICE support functions to their own
> compilation unit.
>
> Cc: Jan Kara <jack@suse.cz>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: "Jérôme Glisse" <jglisse@redhat.com>
> Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Good idea. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> kernel/Makefile | 3 +
> kernel/iomem.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++
> kernel/memremap.c | 178 +----------------------------------------------------
> 3 files changed, 171 insertions(+), 177 deletions(-)
> create mode 100644 kernel/iomem.c
>
> diff --git a/kernel/Makefile b/kernel/Makefile
> index f85ae5dfa474..9b9241361311 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -112,7 +112,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o
> obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
> obj-$(CONFIG_TORTURE_TEST) += torture.o
>
> -obj-$(CONFIG_HAS_IOMEM) += memremap.o
> +obj-$(CONFIG_HAS_IOMEM) += iomem.o
> +obj-$(CONFIG_ZONE_DEVICE) += memremap.o
>
> $(obj)/configs.o: $(obj)/config_data.h
>
> diff --git a/kernel/iomem.c b/kernel/iomem.c
> new file mode 100644
> index 000000000000..f7525e14ebc6
> --- /dev/null
> +++ b/kernel/iomem.c
> @@ -0,0 +1,167 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#include <linux/device.h>
> +#include <linux/types.h>
> +#include <linux/io.h>
> +#include <linux/mm.h>
> +
> +#ifndef ioremap_cache
> +/* temporary while we convert existing ioremap_cache users to memremap */
> +__weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
> +{
> + return ioremap(offset, size);
> +}
> +#endif
> +
> +#ifndef arch_memremap_wb
> +static void *arch_memremap_wb(resource_size_t offset, unsigned long size)
> +{
> + return (__force void *)ioremap_cache(offset, size);
> +}
> +#endif
> +
> +#ifndef arch_memremap_can_ram_remap
> +static bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
> + unsigned long flags)
> +{
> + return true;
> +}
> +#endif
> +
> +static void *try_ram_remap(resource_size_t offset, size_t size,
> + unsigned long flags)
> +{
> + unsigned long pfn = PHYS_PFN(offset);
> +
> + /* In the simple case just return the existing linear address */
> + if (pfn_valid(pfn) && !PageHighMem(pfn_to_page(pfn)) &&
> + arch_memremap_can_ram_remap(offset, size, flags))
> + return __va(offset);
> +
> + return NULL; /* fallback to arch_memremap_wb */
> +}
> +
> +/**
> + * memremap() - remap an iomem_resource as cacheable memory
> + * @offset: iomem resource start address
> + * @size: size of remap
> + * @flags: any of MEMREMAP_WB, MEMREMAP_WT, MEMREMAP_WC,
> + * MEMREMAP_ENC, MEMREMAP_DEC
> + *
> + * memremap() is "ioremap" for cases where it is known that the resource
> + * being mapped does not have i/o side effects and the __iomem
> + * annotation is not applicable. In the case of multiple flags, the different
> + * mapping types will be attempted in the order listed below until one of
> + * them succeeds.
> + *
> + * MEMREMAP_WB - matches the default mapping for System RAM on
> + * the architecture. This is usually a read-allocate write-back cache.
> + * Morever, if MEMREMAP_WB is specified and the requested remap region is RAM
> + * memremap() will bypass establishing a new mapping and instead return
> + * a pointer into the direct map.
> + *
> + * MEMREMAP_WT - establish a mapping whereby writes either bypass the
> + * cache or are written through to memory and never exist in a
> + * cache-dirty state with respect to program visibility. Attempts to
> + * map System RAM with this mapping type will fail.
> + *
> + * MEMREMAP_WC - establish a writecombine mapping, whereby writes may
> + * be coalesced together (e.g. in the CPU's write buffers), but is otherwise
> + * uncached. Attempts to map System RAM with this mapping type will fail.
> + */
> +void *memremap(resource_size_t offset, size_t size, unsigned long flags)
> +{
> + int is_ram = region_intersects(offset, size,
> + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
> + void *addr = NULL;
> +
> + if (!flags)
> + return NULL;
> +
> + if (is_ram == REGION_MIXED) {
> + WARN_ONCE(1, "memremap attempted on mixed range %pa size: %#lx\n",
> + &offset, (unsigned long) size);
> + return NULL;
> + }
> +
> + /* Try all mapping types requested until one returns non-NULL */
> + if (flags & MEMREMAP_WB) {
> + /*
> + * MEMREMAP_WB is special in that it can be satisifed
> + * from the direct map. Some archs depend on the
> + * capability of memremap() to autodetect cases where
> + * the requested range is potentially in System RAM.
> + */
> + if (is_ram == REGION_INTERSECTS)
> + addr = try_ram_remap(offset, size, flags);
> + if (!addr)
> + addr = arch_memremap_wb(offset, size);
> + }
> +
> + /*
> + * If we don't have a mapping yet and other request flags are
> + * present then we will be attempting to establish a new virtual
> + * address mapping. Enforce that this mapping is not aliasing
> + * System RAM.
> + */
> + if (!addr && is_ram == REGION_INTERSECTS && flags != MEMREMAP_WB) {
> + WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
> + &offset, (unsigned long) size);
> + return NULL;
> + }
> +
> + if (!addr && (flags & MEMREMAP_WT))
> + addr = ioremap_wt(offset, size);
> +
> + if (!addr && (flags & MEMREMAP_WC))
> + addr = ioremap_wc(offset, size);
> +
> + return addr;
> +}
> +EXPORT_SYMBOL(memremap);
> +
> +void memunmap(void *addr)
> +{
> + if (is_vmalloc_addr(addr))
> + iounmap((void __iomem *) addr);
> +}
> +EXPORT_SYMBOL(memunmap);
> +
> +static void devm_memremap_release(struct device *dev, void *res)
> +{
> + memunmap(*(void **)res);
> +}
> +
> +static int devm_memremap_match(struct device *dev, void *res, void *match_data)
> +{
> + return *(void **)res == match_data;
> +}
> +
> +void *devm_memremap(struct device *dev, resource_size_t offset,
> + size_t size, unsigned long flags)
> +{
> + void **ptr, *addr;
> +
> + ptr = devres_alloc_node(devm_memremap_release, sizeof(*ptr), GFP_KERNEL,
> + dev_to_node(dev));
> + if (!ptr)
> + return ERR_PTR(-ENOMEM);
> +
> + addr = memremap(offset, size, flags);
> + if (addr) {
> + *ptr = addr;
> + devres_add(dev, ptr);
> + } else {
> + devres_free(ptr);
> + return ERR_PTR(-ENXIO);
> + }
> +
> + return addr;
> +}
> +EXPORT_SYMBOL(devm_memremap);
> +
> +void devm_memunmap(struct device *dev, void *addr)
> +{
> + WARN_ON(devres_release(dev, devm_memremap_release,
> + devm_memremap_match, addr));
> +}
> +EXPORT_SYMBOL(devm_memunmap);
> diff --git a/kernel/memremap.c b/kernel/memremap.c
> index 895e6b76b25e..37a9604133f6 100644
> --- a/kernel/memremap.c
> +++ b/kernel/memremap.c
> @@ -1,15 +1,5 @@
> -/*
> - * Copyright(c) 2015 Intel Corporation. All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of version 2 of the GNU General Public License as
> - * published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful, but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * General Public License for more details.
> - */
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright(c) 2015 Intel Corporation. All rights reserved. */
> #include <linux/radix-tree.h>
> #include <linux/device.h>
> #include <linux/types.h>
> @@ -20,169 +10,6 @@
> #include <linux/swap.h>
> #include <linux/swapops.h>
>
> -#ifndef ioremap_cache
> -/* temporary while we convert existing ioremap_cache users to memremap */
> -__weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
> -{
> - return ioremap(offset, size);
> -}
> -#endif
> -
> -#ifndef arch_memremap_wb
> -static void *arch_memremap_wb(resource_size_t offset, unsigned long size)
> -{
> - return (__force void *)ioremap_cache(offset, size);
> -}
> -#endif
> -
> -#ifndef arch_memremap_can_ram_remap
> -static bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
> - unsigned long flags)
> -{
> - return true;
> -}
> -#endif
> -
> -static void *try_ram_remap(resource_size_t offset, size_t size,
> - unsigned long flags)
> -{
> - unsigned long pfn = PHYS_PFN(offset);
> -
> - /* In the simple case just return the existing linear address */
> - if (pfn_valid(pfn) && !PageHighMem(pfn_to_page(pfn)) &&
> - arch_memremap_can_ram_remap(offset, size, flags))
> - return __va(offset);
> -
> - return NULL; /* fallback to arch_memremap_wb */
> -}
> -
> -/**
> - * memremap() - remap an iomem_resource as cacheable memory
> - * @offset: iomem resource start address
> - * @size: size of remap
> - * @flags: any of MEMREMAP_WB, MEMREMAP_WT, MEMREMAP_WC,
> - * MEMREMAP_ENC, MEMREMAP_DEC
> - *
> - * memremap() is "ioremap" for cases where it is known that the resource
> - * being mapped does not have i/o side effects and the __iomem
> - * annotation is not applicable. In the case of multiple flags, the different
> - * mapping types will be attempted in the order listed below until one of
> - * them succeeds.
> - *
> - * MEMREMAP_WB - matches the default mapping for System RAM on
> - * the architecture. This is usually a read-allocate write-back cache.
> - * Morever, if MEMREMAP_WB is specified and the requested remap region is RAM
> - * memremap() will bypass establishing a new mapping and instead return
> - * a pointer into the direct map.
> - *
> - * MEMREMAP_WT - establish a mapping whereby writes either bypass the
> - * cache or are written through to memory and never exist in a
> - * cache-dirty state with respect to program visibility. Attempts to
> - * map System RAM with this mapping type will fail.
> - *
> - * MEMREMAP_WC - establish a writecombine mapping, whereby writes may
> - * be coalesced together (e.g. in the CPU's write buffers), but is otherwise
> - * uncached. Attempts to map System RAM with this mapping type will fail.
> - */
> -void *memremap(resource_size_t offset, size_t size, unsigned long flags)
> -{
> - int is_ram = region_intersects(offset, size,
> - IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
> - void *addr = NULL;
> -
> - if (!flags)
> - return NULL;
> -
> - if (is_ram == REGION_MIXED) {
> - WARN_ONCE(1, "memremap attempted on mixed range %pa size: %#lx\n",
> - &offset, (unsigned long) size);
> - return NULL;
> - }
> -
> - /* Try all mapping types requested until one returns non-NULL */
> - if (flags & MEMREMAP_WB) {
> - /*
> - * MEMREMAP_WB is special in that it can be satisifed
> - * from the direct map. Some archs depend on the
> - * capability of memremap() to autodetect cases where
> - * the requested range is potentially in System RAM.
> - */
> - if (is_ram == REGION_INTERSECTS)
> - addr = try_ram_remap(offset, size, flags);
> - if (!addr)
> - addr = arch_memremap_wb(offset, size);
> - }
> -
> - /*
> - * If we don't have a mapping yet and other request flags are
> - * present then we will be attempting to establish a new virtual
> - * address mapping. Enforce that this mapping is not aliasing
> - * System RAM.
> - */
> - if (!addr && is_ram == REGION_INTERSECTS && flags != MEMREMAP_WB) {
> - WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
> - &offset, (unsigned long) size);
> - return NULL;
> - }
> -
> - if (!addr && (flags & MEMREMAP_WT))
> - addr = ioremap_wt(offset, size);
> -
> - if (!addr && (flags & MEMREMAP_WC))
> - addr = ioremap_wc(offset, size);
> -
> - return addr;
> -}
> -EXPORT_SYMBOL(memremap);
> -
> -void memunmap(void *addr)
> -{
> - if (is_vmalloc_addr(addr))
> - iounmap((void __iomem *) addr);
> -}
> -EXPORT_SYMBOL(memunmap);
> -
> -static void devm_memremap_release(struct device *dev, void *res)
> -{
> - memunmap(*(void **)res);
> -}
> -
> -static int devm_memremap_match(struct device *dev, void *res, void *match_data)
> -{
> - return *(void **)res == match_data;
> -}
> -
> -void *devm_memremap(struct device *dev, resource_size_t offset,
> - size_t size, unsigned long flags)
> -{
> - void **ptr, *addr;
> -
> - ptr = devres_alloc_node(devm_memremap_release, sizeof(*ptr), GFP_KERNEL,
> - dev_to_node(dev));
> - if (!ptr)
> - return ERR_PTR(-ENOMEM);
> -
> - addr = memremap(offset, size, flags);
> - if (addr) {
> - *ptr = addr;
> - devres_add(dev, ptr);
> - } else {
> - devres_free(ptr);
> - return ERR_PTR(-ENXIO);
> - }
> -
> - return addr;
> -}
> -EXPORT_SYMBOL(devm_memremap);
> -
> -void devm_memunmap(struct device *dev, void *addr)
> -{
> - WARN_ON(devres_release(dev, devm_memremap_release,
> - devm_memremap_match, addr));
> -}
> -EXPORT_SYMBOL(devm_memunmap);
> -
> -#ifdef CONFIG_ZONE_DEVICE
> static DEFINE_MUTEX(pgmap_lock);
> static RADIX_TREE(pgmap_radix, GFP_KERNEL);
> #define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1)
> @@ -473,7 +300,6 @@ struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
>
> return pgmap;
> }
> -#endif /* CONFIG_ZONE_DEVICE */
>
> #if IS_ENABLED(CONFIG_DEVICE_PRIVATE) || IS_ENABLED(CONFIG_DEVICE_PUBLIC)
> void put_zone_device_private_or_public_page(struct page *page)
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm
next prev parent reply other threads:[~2018-05-09 10:29 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-24 23:33 [PATCH v9 0/9] dax: fix dma vs truncate/hole-punch Dan Williams
2018-04-24 23:33 ` [PATCH v9 1/9] dax, dm: introduce ->fs_{claim, release}() dax_device infrastructure Dan Williams
2018-05-09 10:37 ` Jan Kara
2018-04-24 23:33 ` [PATCH v9 2/9] mm, dax: enable filesystems to trigger dev_pagemap ->page_free callbacks Dan Williams
2018-05-16 7:20 ` Dan Williams
2018-04-24 23:33 ` [PATCH v9 3/9] memremap: split devm_memremap_pages() and memremap() infrastructure Dan Williams
2018-05-09 10:29 ` Jan Kara [this message]
2018-04-24 23:33 ` [PATCH v9 4/9] mm, dev_pagemap: introduce CONFIG_DEV_PAGEMAP_OPS Dan Williams
2018-04-24 23:33 ` [PATCH v9 5/9] mm: fix __gup_device_huge vs unmap Dan Williams
2018-05-09 10:46 ` Jan Kara
2018-04-24 23:33 ` [PATCH v9 6/9] mm, fs, dax: handle layout changes to pinned dax mappings Dan Williams
2018-05-09 10:56 ` Jan Kara
2018-05-09 22:06 ` Dan Williams
2018-04-24 23:33 ` [PATCH v9 7/9] xfs: prepare xfs_break_layouts() to be called with XFS_MMAPLOCK_EXCL Dan Williams
2018-04-24 23:33 ` [PATCH v9 8/9] xfs: prepare xfs_break_layouts() for another layout type Dan Williams
2018-04-24 23:33 ` [PATCH v9 9/9] xfs, dax: introduce xfs_break_dax_layouts() Dan Williams
2018-05-09 12:27 ` Jan Kara
2018-05-09 22:54 ` Dan Williams
2018-05-09 14:38 ` Darrick J. Wong
2018-05-03 23:53 ` [PATCH v9 0/9] dax: fix dma vs truncate/hole-punch Dan Williams
2018-05-08 0:16 ` Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180509102911.fqr7p3urcsielgqo@quack2.suse.cz \
--to=jack@suse.cz \
--cc=dan.j.williams@intel.com \
--cc=david@fromorbit.com \
--cc=hch@lst.de \
--cc=jglisse@redhat.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-nvdimm@lists.01.org \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).