From: Dan Williams <dan.j.williams@intel.com> To: linux-kernel@vger.kernel.org Cc: axboe@kernel.dk, boaz@plexistor.com, david@fromorbit.com, linux-arch@vger.kernel.org, arnd@arndb.de, ross.zwisler@linux.intel.com, linux-nvdimm@lists.01.org, benh@kernel.crashing.org, linux-fsdevel@vger.kernel.org, heiko.carstens@de.ibm.com, hch@lst.de, tj@kernel.org, paulus@samba.org, hpa@zytor.com, schwidefsky@de.ibm.com, willy@linux.intel.com, akpm@linux-foundation.org, torvalds@linux-foundation.org, mingo@kernel.org Subject: [PATCH v4 5/9] dma-mapping: allow archs to optionally specify a ->map_pfn() operation Date: Fri, 05 Jun 2015 17:19:30 -0400 [thread overview] Message-ID: <20150605211929.20751.764.stgit@dwillia2-desk3.amr.corp.intel.com> (raw) In-Reply-To: <20150605205052.20751.77149.stgit@dwillia2-desk3.amr.corp.intel.com> Initially this enables the conversion of struct scatterlist to carry a __pfn_t instead of a struct page * reference. Later this enables block device drivers to perform DMA to/from persistent memory which may not have a backing struct page entry. Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- arch/Kconfig | 3 +++ include/asm-generic/dma-mapping-common.h | 30 ++++++++++++++++++++++++++++++ include/linux/dma-debug.h | 23 +++++++++++++++++++---- include/linux/dma-mapping.h | 8 +++++++- lib/dma-debug.c | 10 ++++++---- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 9b98732e0f3b..69d3a3fa21af 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -203,6 +203,9 @@ config HAVE_DMA_ATTRS config HAVE_DMA_CONTIGUOUS bool +config HAVE_DMA_PFN + bool + config HAVE_KMAP_PFN bool diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h index 940d5ec122c9..7305efb1bac6 100644 --- a/include/asm-generic/dma-mapping-common.h +++ b/include/asm-generic/dma-mapping-common.h @@ -17,9 +17,15 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, kmemcheck_mark_initialized(ptr, size); BUG_ON(!valid_dma_direction(dir)); +#ifdef CONFIG_HAVE_DMA_PFN + addr = ops->map_pfn(dev, page_to_pfn_typed(virt_to_page(ptr)), + (unsigned long)ptr & ~PAGE_MASK, size, + dir, attrs); +#else addr = ops->map_page(dev, virt_to_page(ptr), (unsigned long)ptr & ~PAGE_MASK, size, dir, attrs); +#endif debug_dma_map_page(dev, virt_to_page(ptr), (unsigned long)ptr & ~PAGE_MASK, size, dir, addr, true); @@ -73,6 +79,29 @@ static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg ops->unmap_sg(dev, sg, nents, dir, attrs); } +#ifdef CONFIG_HAVE_DMA_PFN +static inline dma_addr_t dma_map_pfn(struct device *dev, __pfn_t pfn, + size_t offset, size_t size, + enum dma_data_direction dir) +{ + struct dma_map_ops *ops = get_dma_ops(dev); + dma_addr_t addr; + + BUG_ON(!valid_dma_direction(dir)); + addr = ops->map_pfn(dev, pfn, offset, size, dir, NULL); + debug_dma_map_pfn(dev, pfn, offset, size, dir, addr, false); + + return addr; +} + +static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, + size_t offset, size_t size, + enum dma_data_direction dir) +{ + kmemcheck_mark_initialized(page_address(page) + offset, size); + return dma_map_pfn(dev, page_to_pfn_typed(page), offset, size, dir); +} +#else static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, size_t offset, size_t size, enum dma_data_direction dir) @@ -87,6 +116,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, return addr; } +#endif /* CONFIG_HAVE_DMA_PFN */ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir) diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h index fe8cb610deac..a3b4c8c0cd68 100644 --- a/include/linux/dma-debug.h +++ b/include/linux/dma-debug.h @@ -34,10 +34,18 @@ extern void dma_debug_init(u32 num_entries); extern int dma_debug_resize_entries(u32 num_entries); -extern void debug_dma_map_page(struct device *dev, struct page *page, - size_t offset, size_t size, - int direction, dma_addr_t dma_addr, - bool map_single); +extern void debug_dma_map_pfn(struct device *dev, __pfn_t pfn, size_t offset, + size_t size, int direction, dma_addr_t dma_addr, + bool map_single); + +static inline void debug_dma_map_page(struct device *dev, struct page *page, + size_t offset, size_t size, + int direction, dma_addr_t dma_addr, + bool map_single) +{ + return debug_dma_map_pfn(dev, page_to_pfn_t(page), offset, size, + direction, dma_addr, map_single); +} extern void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr); @@ -109,6 +117,13 @@ static inline void debug_dma_map_page(struct device *dev, struct page *page, { } +static inline void debug_dma_map_pfn(struct device *dev, __pfn_t pfn, + size_t offset, size_t size, + int direction, dma_addr_t dma_addr, + bool map_single) +{ +} + static inline void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index ac07ff090919..d6437b493300 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -26,11 +26,17 @@ struct dma_map_ops { int (*get_sgtable)(struct device *dev, struct sg_table *sgt, void *, dma_addr_t, size_t, struct dma_attrs *attrs); - +#ifdef CONFIG_HAVE_DMA_PFN + dma_addr_t (*map_pfn)(struct device *dev, __pfn_t pfn, + unsigned long offset, size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs); +#else dma_addr_t (*map_page)(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); +#endif void (*unmap_page)(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); diff --git a/lib/dma-debug.c b/lib/dma-debug.c index ae4b65e17e64..c24de1cd8f81 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -1250,11 +1250,12 @@ out: put_hash_bucket(bucket, &flags); } -void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, +void debug_dma_map_pfn(struct device *dev, __pfn_t pfn, size_t offset, size_t size, int direction, dma_addr_t dma_addr, bool map_single) { struct dma_debug_entry *entry; + struct page *page; if (unlikely(dma_debug_disabled())) return; @@ -1268,7 +1269,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, entry->dev = dev; entry->type = dma_debug_page; - entry->pfn = page_to_pfn(page); + entry->pfn = __pfn_t_to_pfn(pfn); entry->offset = offset, entry->dev_addr = dma_addr; entry->size = size; @@ -1278,7 +1279,8 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, if (map_single) entry->type = dma_debug_single; - if (!PageHighMem(page)) { + page = __pfn_t_to_page(pfn); + if (page && !PageHighMem(page)) { void *addr = page_address(page) + offset; check_for_stack(dev, addr); @@ -1287,7 +1289,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, add_dma_entry(entry); } -EXPORT_SYMBOL(debug_dma_map_page); +EXPORT_SYMBOL(debug_dma_map_pfn); void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) {
WARNING: multiple messages have this Message-ID (diff)
From: Dan Williams <dan.j.williams@intel.com> To: linux-kernel@vger.kernel.org Cc: axboe@kernel.dk, boaz@plexistor.com, david@fromorbit.com, linux-arch@vger.kernel.org, arnd@arndb.de, ross.zwisler@linux.intel.com, linux-nvdimm@ml01.01.org, benh@kernel.crashing.org, linux-fsdevel@vger.kernel.org, heiko.carstens@de.ibm.com, hch@lst.de, tj@kernel.org, paulus@samba.org, hpa@zytor.com, schwidefsky@de.ibm.com, willy@linux.intel.com, akpm@linux-foundation.org, torvalds@linux-foundation.org, mingo@kernel.org Subject: [PATCH v4 5/9] dma-mapping: allow archs to optionally specify a ->map_pfn() operation Date: Fri, 05 Jun 2015 17:19:30 -0400 [thread overview] Message-ID: <20150605211929.20751.764.stgit@dwillia2-desk3.amr.corp.intel.com> (raw) In-Reply-To: <20150605205052.20751.77149.stgit@dwillia2-desk3.amr.corp.intel.com> Initially this enables the conversion of struct scatterlist to carry a __pfn_t instead of a struct page * reference. Later this enables block device drivers to perform DMA to/from persistent memory which may not have a backing struct page entry. Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- arch/Kconfig | 3 +++ include/asm-generic/dma-mapping-common.h | 30 ++++++++++++++++++++++++++++++ include/linux/dma-debug.h | 23 +++++++++++++++++++---- include/linux/dma-mapping.h | 8 +++++++- lib/dma-debug.c | 10 ++++++---- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 9b98732e0f3b..69d3a3fa21af 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -203,6 +203,9 @@ config HAVE_DMA_ATTRS config HAVE_DMA_CONTIGUOUS bool +config HAVE_DMA_PFN + bool + config HAVE_KMAP_PFN bool diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h index 940d5ec122c9..7305efb1bac6 100644 --- a/include/asm-generic/dma-mapping-common.h +++ b/include/asm-generic/dma-mapping-common.h @@ -17,9 +17,15 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr, kmemcheck_mark_initialized(ptr, size); BUG_ON(!valid_dma_direction(dir)); +#ifdef CONFIG_HAVE_DMA_PFN + addr = ops->map_pfn(dev, page_to_pfn_typed(virt_to_page(ptr)), + (unsigned long)ptr & ~PAGE_MASK, size, + dir, attrs); +#else addr = ops->map_page(dev, virt_to_page(ptr), (unsigned long)ptr & ~PAGE_MASK, size, dir, attrs); +#endif debug_dma_map_page(dev, virt_to_page(ptr), (unsigned long)ptr & ~PAGE_MASK, size, dir, addr, true); @@ -73,6 +79,29 @@ static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg ops->unmap_sg(dev, sg, nents, dir, attrs); } +#ifdef CONFIG_HAVE_DMA_PFN +static inline dma_addr_t dma_map_pfn(struct device *dev, __pfn_t pfn, + size_t offset, size_t size, + enum dma_data_direction dir) +{ + struct dma_map_ops *ops = get_dma_ops(dev); + dma_addr_t addr; + + BUG_ON(!valid_dma_direction(dir)); + addr = ops->map_pfn(dev, pfn, offset, size, dir, NULL); + debug_dma_map_pfn(dev, pfn, offset, size, dir, addr, false); + + return addr; +} + +static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, + size_t offset, size_t size, + enum dma_data_direction dir) +{ + kmemcheck_mark_initialized(page_address(page) + offset, size); + return dma_map_pfn(dev, page_to_pfn_typed(page), offset, size, dir); +} +#else static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, size_t offset, size_t size, enum dma_data_direction dir) @@ -87,6 +116,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, return addr; } +#endif /* CONFIG_HAVE_DMA_PFN */ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir) diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h index fe8cb610deac..a3b4c8c0cd68 100644 --- a/include/linux/dma-debug.h +++ b/include/linux/dma-debug.h @@ -34,10 +34,18 @@ extern void dma_debug_init(u32 num_entries); extern int dma_debug_resize_entries(u32 num_entries); -extern void debug_dma_map_page(struct device *dev, struct page *page, - size_t offset, size_t size, - int direction, dma_addr_t dma_addr, - bool map_single); +extern void debug_dma_map_pfn(struct device *dev, __pfn_t pfn, size_t offset, + size_t size, int direction, dma_addr_t dma_addr, + bool map_single); + +static inline void debug_dma_map_page(struct device *dev, struct page *page, + size_t offset, size_t size, + int direction, dma_addr_t dma_addr, + bool map_single) +{ + return debug_dma_map_pfn(dev, page_to_pfn_t(page), offset, size, + direction, dma_addr, map_single); +} extern void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr); @@ -109,6 +117,13 @@ static inline void debug_dma_map_page(struct device *dev, struct page *page, { } +static inline void debug_dma_map_pfn(struct device *dev, __pfn_t pfn, + size_t offset, size_t size, + int direction, dma_addr_t dma_addr, + bool map_single) +{ +} + static inline void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index ac07ff090919..d6437b493300 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -26,11 +26,17 @@ struct dma_map_ops { int (*get_sgtable)(struct device *dev, struct sg_table *sgt, void *, dma_addr_t, size_t, struct dma_attrs *attrs); - +#ifdef CONFIG_HAVE_DMA_PFN + dma_addr_t (*map_pfn)(struct device *dev, __pfn_t pfn, + unsigned long offset, size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs); +#else dma_addr_t (*map_page)(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); +#endif void (*unmap_page)(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs); diff --git a/lib/dma-debug.c b/lib/dma-debug.c index ae4b65e17e64..c24de1cd8f81 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -1250,11 +1250,12 @@ out: put_hash_bucket(bucket, &flags); } -void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, +void debug_dma_map_pfn(struct device *dev, __pfn_t pfn, size_t offset, size_t size, int direction, dma_addr_t dma_addr, bool map_single) { struct dma_debug_entry *entry; + struct page *page; if (unlikely(dma_debug_disabled())) return; @@ -1268,7 +1269,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, entry->dev = dev; entry->type = dma_debug_page; - entry->pfn = page_to_pfn(page); + entry->pfn = __pfn_t_to_pfn(pfn); entry->offset = offset, entry->dev_addr = dma_addr; entry->size = size; @@ -1278,7 +1279,8 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, if (map_single) entry->type = dma_debug_single; - if (!PageHighMem(page)) { + page = __pfn_t_to_page(pfn); + if (page && !PageHighMem(page)) { void *addr = page_address(page) + offset; check_for_stack(dev, addr); @@ -1287,7 +1289,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, add_dma_entry(entry); } -EXPORT_SYMBOL(debug_dma_map_page); +EXPORT_SYMBOL(debug_dma_map_pfn); void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) {
next prev parent reply other threads:[~2015-06-05 21:19 UTC|newest] Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-06-05 21:19 [PATCH v4 0/9] introduce __pfn_t, evacuate struct page from sgls Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-05 21:19 ` [PATCH v4 1/9] introduce __pfn_t for scatterlists and pmem Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-05 21:37 ` Linus Torvalds 2015-06-05 21:37 ` Linus Torvalds 2015-06-05 22:12 ` Dan Williams 2015-06-05 22:12 ` Dan Williams 2015-06-05 21:19 ` [PATCH v4 2/9] x86: support kmap_atomic_pfn_t() for persistent memory Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-09 6:50 ` Christoph Hellwig 2015-06-09 6:50 ` Christoph Hellwig 2015-06-10 12:12 ` Christoph Hellwig 2015-06-10 12:12 ` Christoph Hellwig 2015-06-10 15:03 ` Matthew Wilcox 2015-06-10 15:03 ` Matthew Wilcox 2015-06-10 15:11 ` Christoph Hellwig 2015-06-10 15:11 ` Christoph Hellwig 2015-06-10 15:36 ` Dan Williams 2015-06-10 15:36 ` Dan Williams 2015-06-10 16:11 ` Christoph Hellwig 2015-06-10 16:11 ` Christoph Hellwig 2015-06-10 16:17 ` Dan Williams 2015-06-10 16:17 ` Dan Williams 2015-06-05 21:19 ` [PATCH v4 3/9] dax: drop size parameter to ->direct_access() Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-06 11:37 ` Matthew Wilcox 2015-06-06 11:37 ` Matthew Wilcox 2015-06-09 6:51 ` Christoph Hellwig 2015-06-09 6:51 ` Christoph Hellwig 2015-06-05 21:19 ` [PATCH v4 4/9] dax: fix mapping lifetime handling, convert to __pfn_t + kmap_atomic_pfn_t() Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-06 11:58 ` Matthew Wilcox 2015-06-06 11:58 ` Matthew Wilcox 2015-08-07 23:54 ` Dan Williams 2015-08-07 23:54 ` Dan Williams 2015-06-08 16:29 ` Elliott, Robert (Server Storage) 2015-06-08 16:29 ` Elliott, Robert (Server Storage) 2015-06-08 16:36 ` Dan Williams 2015-06-08 16:36 ` Dan Williams 2015-06-09 6:55 ` Christoph Hellwig 2015-06-09 6:55 ` Christoph Hellwig 2015-06-05 21:19 ` Dan Williams [this message] 2015-06-05 21:19 ` [PATCH v4 5/9] dma-mapping: allow archs to optionally specify a ->map_pfn() operation Dan Williams 2015-06-05 21:19 ` [PATCH v4 6/9] scatterlist: use sg_phys() Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-09 6:59 ` Christoph Hellwig 2015-06-09 6:59 ` Christoph Hellwig 2015-06-05 21:19 ` [PATCH v4 7/9] scatterlist: cleanup sg_chain() and sg_unmark_end() Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-05 21:19 ` [PATCH v4 8/9] scatterlist: convert to __pfn_t Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-05 21:19 ` [PATCH v4 9/9] x86: convert dma_map_ops to support mapping a __pfn_t Dan Williams 2015-06-05 21:19 ` Dan Williams 2015-06-09 6:58 ` Christoph Hellwig 2015-06-09 6:58 ` Christoph Hellwig 2015-06-09 13:47 ` Konrad Rzeszutek Wilk 2015-06-05 21:23 ` [PATCH v4 0/9] introduce __pfn_t, evacuate struct page from sgls Dan Williams 2015-06-05 21:23 ` Dan Williams
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=20150605211929.20751.764.stgit@dwillia2-desk3.amr.corp.intel.com \ --to=dan.j.williams@intel.com \ --cc=akpm@linux-foundation.org \ --cc=arnd@arndb.de \ --cc=axboe@kernel.dk \ --cc=benh@kernel.crashing.org \ --cc=boaz@plexistor.com \ --cc=david@fromorbit.com \ --cc=hch@lst.de \ --cc=heiko.carstens@de.ibm.com \ --cc=hpa@zytor.com \ --cc=linux-arch@vger.kernel.org \ --cc=linux-fsdevel@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-nvdimm@lists.01.org \ --cc=mingo@kernel.org \ --cc=paulus@samba.org \ --cc=ross.zwisler@linux.intel.com \ --cc=schwidefsky@de.ibm.com \ --cc=tj@kernel.org \ --cc=torvalds@linux-foundation.org \ --cc=willy@linux.intel.com \ /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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.