* [PATCH 0/2] dma-mapping: update default segment_boundary_mask
@ 2020-09-01 22:16 Nicolin Chen
2020-09-01 22:16 ` [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages() Nicolin Chen
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Nicolin Chen @ 2020-09-01 22:16 UTC (permalink / raw)
To: hch
Cc: sfr, mpe, benh, paulus, linuxppc-dev, linux-kernel, rth, ink,
mattst88, linux-alpha, tony.luck, fenghua.yu, linux-ia64,
schnelle, gerald.schaefer, hca, gor, borntraeger, linux-s390,
davem, sparclinux, tglx, mingo, bp, x86, hpa, James.Bottomley,
deller, linux-parisc
These two patches are to update default segment_boundary_mask.
PATCH-1 fixes overflow issues in callers of dma_get_seg_boundary.
Previous version was a series: https://lkml.org/lkml/2020/8/31/1026
Then PATCH-2 sets default segment_boundary_mask to ULONG_MAX.
Nicolin Chen (2):
dma-mapping: introduce dma_get_seg_boundary_nr_pages()
dma-mapping: set default segment_boundary_mask to ULONG_MAX
arch/alpha/kernel/pci_iommu.c | 7 +------
arch/ia64/hp/common/sba_iommu.c | 3 +--
arch/powerpc/kernel/iommu.c | 9 ++-------
arch/s390/pci/pci_dma.c | 6 ++----
arch/sparc/kernel/iommu-common.c | 10 +++-------
arch/sparc/kernel/iommu.c | 3 +--
arch/sparc/kernel/pci_sun4v.c | 3 +--
arch/x86/kernel/amd_gart_64.c | 3 +--
drivers/parisc/ccio-dma.c | 3 +--
drivers/parisc/sba_iommu.c | 3 +--
include/linux/dma-mapping.h | 21 ++++++++++++++++++++-
11 files changed, 34 insertions(+), 37 deletions(-)
--
2.17.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages()
2020-09-01 22:16 [PATCH 0/2] dma-mapping: update default segment_boundary_mask Nicolin Chen
@ 2020-09-01 22:16 ` Nicolin Chen
2020-09-03 3:47 ` Michael Ellerman
2020-09-03 10:57 ` Andy Shevchenko
2020-09-01 22:16 ` [PATCH 2/2] dma-mapping: set default segment_boundary_mask to ULONG_MAX Nicolin Chen
2020-09-02 8:13 ` [PATCH 0/2] dma-mapping: update default segment_boundary_mask Niklas Schnelle
2 siblings, 2 replies; 10+ messages in thread
From: Nicolin Chen @ 2020-09-01 22:16 UTC (permalink / raw)
To: hch
Cc: sfr, mpe, benh, paulus, linuxppc-dev, linux-kernel, rth, ink,
mattst88, linux-alpha, tony.luck, fenghua.yu, linux-ia64,
schnelle, gerald.schaefer, hca, gor, borntraeger, linux-s390,
davem, sparclinux, tglx, mingo, bp, x86, hpa, James.Bottomley,
deller, linux-parisc
We found that callers of dma_get_seg_boundary mostly do an ALIGN
with page mask and then do a page shift to get number of pages:
ALIGN(boundary + 1, 1 << shift) >> shift
However, the boundary might be as large as ULONG_MAX, which means
that a device has no specific boundary limit. So either "+ 1" or
passing it to ALIGN() would potentially overflow.
According to kernel defines:
#define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define ALIGN(x, a) ALIGN_MASK(x, (typeof(x))(a) - 1)
We can simplify the logic here into a helper function doing:
ALIGN(boundary + 1, 1 << shift) >> shift
= ALIGN_MASK(b + 1, (1 << s) - 1) >> s
= {[b + 1 + (1 << s) - 1] & ~[(1 << s) - 1]} >> s
= [b + 1 + (1 << s) - 1] >> s
= [b + (1 << s)] >> s
= (b >> s) + 1
This patch introduces and applies dma_get_seg_boundary_nr_pages()
as an overflow-free helper for the dma_get_seg_boundary() callers
to get numbers of pages. It also takes care of the NULL dev case
for non-DMA API callers.
Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
---
arch/alpha/kernel/pci_iommu.c | 7 +------
arch/ia64/hp/common/sba_iommu.c | 3 +--
arch/powerpc/kernel/iommu.c | 9 ++-------
arch/s390/pci/pci_dma.c | 6 ++----
arch/sparc/kernel/iommu-common.c | 10 +++-------
arch/sparc/kernel/iommu.c | 3 +--
arch/sparc/kernel/pci_sun4v.c | 3 +--
arch/x86/kernel/amd_gart_64.c | 3 +--
drivers/parisc/ccio-dma.c | 3 +--
drivers/parisc/sba_iommu.c | 3 +--
include/linux/dma-mapping.h | 19 +++++++++++++++++++
11 files changed, 33 insertions(+), 36 deletions(-)
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 81037907268d..6f7de4f4e191 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -141,12 +141,7 @@ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
unsigned long boundary_size;
base = arena->dma_base >> PAGE_SHIFT;
- if (dev) {
- boundary_size = dma_get_seg_boundary(dev) + 1;
- boundary_size >>= PAGE_SHIFT;
- } else {
- boundary_size = 1UL << (32 - PAGE_SHIFT);
- }
+ boundary_size = dma_get_seg_boundary_nr_pages(dev, PAGE_SHIFT);
/* Search forward for the first mask-aligned sequence of N free ptes */
ptes = arena->ptes;
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 656a4888c300..b49b73a95067 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -485,8 +485,7 @@ sba_search_bitmap(struct ioc *ioc, struct device *dev,
ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
ASSERT(res_ptr < res_end);
- boundary_size = (unsigned long long)dma_get_seg_boundary(dev) + 1;
- boundary_size = ALIGN(boundary_size, 1ULL << iovp_shift) >> iovp_shift;
+ boundary_size = dma_get_seg_boundary_nr_pages(dev, iovp_shift);
BUG_ON(ioc->ibase & ~iovp_mask);
shift = ioc->ibase >> iovp_shift;
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 9704f3f76e63..cbc2e62db597 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -236,15 +236,10 @@ static unsigned long iommu_range_alloc(struct device *dev,
}
}
- if (dev)
- boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
- 1 << tbl->it_page_shift);
- else
- boundary_size = ALIGN(1UL << 32, 1 << tbl->it_page_shift);
- /* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
+ boundary_size = dma_get_seg_boundary_nr_pages(dev, tbl->it_page_shift);
n = iommu_area_alloc(tbl->it_map, limit, start, npages, tbl->it_offset,
- boundary_size >> tbl->it_page_shift, align_mask);
+ boundary_size, align_mask);
if (n == -1) {
if (likely(pass == 0)) {
/* First try the pool from the start */
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 64b1399a73f0..4a37d8f4de9d 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -261,13 +261,11 @@ static unsigned long __dma_alloc_iommu(struct device *dev,
unsigned long start, int size)
{
struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
- unsigned long boundary_size;
- boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
- PAGE_SIZE) >> PAGE_SHIFT;
return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages,
start, size, zdev->start_dma >> PAGE_SHIFT,
- boundary_size, 0);
+ dma_get_seg_boundary_nr_pages(dev, PAGE_SHIFT),
+ 0);
}
static dma_addr_t dma_alloc_address(struct device *dev, int size)
diff --git a/arch/sparc/kernel/iommu-common.c b/arch/sparc/kernel/iommu-common.c
index 59cb16691322..23ca75f09277 100644
--- a/arch/sparc/kernel/iommu-common.c
+++ b/arch/sparc/kernel/iommu-common.c
@@ -166,13 +166,6 @@ unsigned long iommu_tbl_range_alloc(struct device *dev,
}
}
- if (dev)
- boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
- 1 << iommu->table_shift);
- else
- boundary_size = ALIGN(1ULL << 32, 1 << iommu->table_shift);
-
- boundary_size = boundary_size >> iommu->table_shift;
/*
* if the skip_span_boundary_check had been set during init, we set
* things up so that iommu_is_span_boundary() merely checks if the
@@ -181,6 +174,9 @@ unsigned long iommu_tbl_range_alloc(struct device *dev,
if ((iommu->flags & IOMMU_NO_SPAN_BOUND) != 0) {
shift = 0;
boundary_size = iommu->poolsize * iommu->nr_pools;
+ } else {
+ boundary_size = dma_get_seg_boundary_nr_pages(dev,
+ iommu->table_shift);
}
n = iommu_area_alloc(iommu->map, limit, start, npages, shift,
boundary_size, align_mask);
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 4ae7388b1bff..c3e4e2df26a8 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -472,8 +472,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
outs->dma_length = 0;
max_seg_size = dma_get_max_seg_size(dev);
- seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
- IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
+ seg_boundary_size = dma_get_seg_boundary_nr_pages(dev, IO_PAGE_SHIFT);
base_shift = iommu->tbl.table_map_base >> IO_PAGE_SHIFT;
for_each_sg(sglist, s, nelems, i) {
unsigned long paddr, npages, entry, out_entry = 0, slen;
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 14b93c5564e3..6b92dd51c002 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -508,8 +508,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
iommu_batch_start(dev, prot, ~0UL);
max_seg_size = dma_get_max_seg_size(dev);
- seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
- IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
+ seg_boundary_size = dma_get_seg_boundary_nr_pages(dev, IO_PAGE_SHIFT);
mask = *dev->dma_mask;
if (!iommu_use_atu(iommu, mask))
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index e89031e9c847..bccc5357bffd 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -96,8 +96,7 @@ static unsigned long alloc_iommu(struct device *dev, int size,
base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),
PAGE_SIZE) >> PAGE_SHIFT;
- boundary_size = ALIGN((u64)dma_get_seg_boundary(dev) + 1,
- PAGE_SIZE) >> PAGE_SHIFT;
+ boundary_size = dma_get_seg_boundary_nr_pages(dev, PAGE_SHIFT);
spin_lock_irqsave(&iommu_bitmap_lock, flags);
offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit,
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index a5507f75b524..ba16b7f8f806 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -356,8 +356,7 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size)
** ggg sacrifices another 710 to the computer gods.
*/
- boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1,
- 1ULL << IOVP_SHIFT) >> IOVP_SHIFT;
+ boundary_size = dma_get_seg_boundary_nr_pages(dev, IOVP_SHIFT);
if (pages_needed <= 8) {
/*
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index d4314fba0269..959bda193b96 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -342,8 +342,7 @@ sba_search_bitmap(struct ioc *ioc, struct device *dev,
unsigned long shift;
int ret;
- boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1,
- 1ULL << IOVP_SHIFT) >> IOVP_SHIFT;
+ boundary_size = dma_get_seg_boundary_nr_pages(dev, IOVP_SHIFT);
#if defined(ZX1_SUPPORT)
BUG_ON(ioc->ibase & ~IOVP_MASK);
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 52635e91143b..faab0a8210b9 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -632,6 +632,25 @@ static inline unsigned long dma_get_seg_boundary(struct device *dev)
return DMA_BIT_MASK(32);
}
+/**
+ * dma_get_seg_boundary_nr_pages - return the segment boundary in "page" units
+ * @dev: device to guery the boundary for
+ * @page_shift: ilog() of the IOMMU page size
+ *
+ * Return the segment boundary in IOMMU page units (which may be different from
+ * the CPU page size) for the passed in device.
+ *
+ * If @dev is NULL a boundary of U32_MAX is assumed, this case is just for
+ * non-DMA API callers.
+ */
+static inline unsigned long dma_get_seg_boundary_nr_pages(struct device *dev,
+ unsigned int page_shift)
+{
+ if (!dev)
+ return (U32_MAX >> page_shift) + 1;
+ return (dma_get_seg_boundary(dev) >> page_shift) + 1;
+}
+
static inline int dma_set_seg_boundary(struct device *dev, unsigned long mask)
{
if (dev->dma_parms) {
--
2.17.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] dma-mapping: set default segment_boundary_mask to ULONG_MAX
2020-09-01 22:16 [PATCH 0/2] dma-mapping: update default segment_boundary_mask Nicolin Chen
2020-09-01 22:16 ` [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages() Nicolin Chen
@ 2020-09-01 22:16 ` Nicolin Chen
2020-09-02 8:13 ` [PATCH 0/2] dma-mapping: update default segment_boundary_mask Niklas Schnelle
2 siblings, 0 replies; 10+ messages in thread
From: Nicolin Chen @ 2020-09-01 22:16 UTC (permalink / raw)
To: hch
Cc: sfr, mpe, benh, paulus, linuxppc-dev, linux-kernel, rth, ink,
mattst88, linux-alpha, tony.luck, fenghua.yu, linux-ia64,
schnelle, gerald.schaefer, hca, gor, borntraeger, linux-s390,
davem, sparclinux, tglx, mingo, bp, x86, hpa, James.Bottomley,
deller, linux-parisc
The default segment_boundary_mask was set to DMA_BIT_MAKS(32)
a decade ago by referencing SCSI/block subsystem, as a 32-bit
mask was good enough for most of the devices.
Now more and more drivers set dma_masks above DMA_BIT_MAKS(32)
while only a handful of them call dma_set_seg_boundary(). This
means that most drivers have a 4GB segmention boundary because
DMA API returns a 32-bit default value, though they might not
really have such a limit.
The default segment_boundary_mask should mean "no limit" since
the device doesn't explicitly set the mask. But a 32-bit mask
certainly limits those devices capable of 32+ bits addressing.
So this patch sets default segment_boundary_mask to ULONG_MAX.
Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
---
include/linux/dma-mapping.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index faab0a8210b9..df0bff2ea750 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -629,7 +629,7 @@ static inline unsigned long dma_get_seg_boundary(struct device *dev)
{
if (dev->dma_parms && dev->dma_parms->segment_boundary_mask)
return dev->dma_parms->segment_boundary_mask;
- return DMA_BIT_MASK(32);
+ return ULONG_MAX;
}
/**
--
2.17.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] dma-mapping: update default segment_boundary_mask
2020-09-01 22:16 [PATCH 0/2] dma-mapping: update default segment_boundary_mask Nicolin Chen
2020-09-01 22:16 ` [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages() Nicolin Chen
2020-09-01 22:16 ` [PATCH 2/2] dma-mapping: set default segment_boundary_mask to ULONG_MAX Nicolin Chen
@ 2020-09-02 8:13 ` Niklas Schnelle
2020-09-03 3:26 ` Nicolin Chen
2020-09-03 16:13 ` Christoph Hellwig
2 siblings, 2 replies; 10+ messages in thread
From: Niklas Schnelle @ 2020-09-02 8:13 UTC (permalink / raw)
To: Nicolin Chen, hch
Cc: sfr, mpe, benh, paulus, linuxppc-dev, linux-kernel, rth, ink,
mattst88, linux-alpha, tony.luck, fenghua.yu, linux-ia64,
gerald.schaefer, hca, gor, borntraeger, linux-s390, davem,
sparclinux, tglx, mingo, bp, x86, hpa, James.Bottomley, deller,
linux-parisc
On 9/2/20 12:16 AM, Nicolin Chen wrote:
> These two patches are to update default segment_boundary_mask.
>
> PATCH-1 fixes overflow issues in callers of dma_get_seg_boundary.
> Previous version was a series: https://lkml.org/lkml/2020/8/31/1026
>
> Then PATCH-2 sets default segment_boundary_mask to ULONG_MAX.
>
> Nicolin Chen (2):
> dma-mapping: introduce dma_get_seg_boundary_nr_pages()
> dma-mapping: set default segment_boundary_mask to ULONG_MAX
I gave both of your patches a quick test ride on a couple of dev mainframes,
both NVMe, ConnectX and virtio-pci devices all seems to work fine.
I already commented on Christoph's mail that I like the helper approach,
so as for s390 you can add my
Acked-by: Niklas Schnelle <schnelle@linux.ibm.com>
>
> arch/alpha/kernel/pci_iommu.c | 7 +------
> arch/ia64/hp/common/sba_iommu.c | 3 +--
> arch/powerpc/kernel/iommu.c | 9 ++-------
> arch/s390/pci/pci_dma.c | 6 ++----
> arch/sparc/kernel/iommu-common.c | 10 +++-------
> arch/sparc/kernel/iommu.c | 3 +--
> arch/sparc/kernel/pci_sun4v.c | 3 +--
> arch/x86/kernel/amd_gart_64.c | 3 +--
> drivers/parisc/ccio-dma.c | 3 +--
> drivers/parisc/sba_iommu.c | 3 +--
> include/linux/dma-mapping.h | 21 ++++++++++++++++++++-
> 11 files changed, 34 insertions(+), 37 deletions(-)
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] dma-mapping: update default segment_boundary_mask
2020-09-02 8:13 ` [PATCH 0/2] dma-mapping: update default segment_boundary_mask Niklas Schnelle
@ 2020-09-03 3:26 ` Nicolin Chen
2020-09-03 16:13 ` Christoph Hellwig
1 sibling, 0 replies; 10+ messages in thread
From: Nicolin Chen @ 2020-09-03 3:26 UTC (permalink / raw)
To: Niklas Schnelle
Cc: hch, sfr, mpe, benh, paulus, linuxppc-dev, linux-kernel, rth,
ink, mattst88, linux-alpha, tony.luck, fenghua.yu, linux-ia64,
gerald.schaefer, hca, gor, borntraeger, linux-s390, davem,
sparclinux, tglx, mingo, bp, x86, hpa, James.Bottomley, deller,
linux-parisc
On Wed, Sep 02, 2020 at 10:13:12AM +0200, Niklas Schnelle wrote:
> On 9/2/20 12:16 AM, Nicolin Chen wrote:
> > These two patches are to update default segment_boundary_mask.
> >
> > PATCH-1 fixes overflow issues in callers of dma_get_seg_boundary.
> > Previous version was a series: https://lkml.org/lkml/2020/8/31/1026
> >
> > Then PATCH-2 sets default segment_boundary_mask to ULONG_MAX.
> >
> > Nicolin Chen (2):
> > dma-mapping: introduce dma_get_seg_boundary_nr_pages()
> > dma-mapping: set default segment_boundary_mask to ULONG_MAX
>
> I gave both of your patches a quick test ride on a couple of dev mainframes,
> both NVMe, ConnectX and virtio-pci devices all seems to work fine.
> I already commented on Christoph's mail that I like the helper approach,
> so as for s390 you can add my
>
> Acked-by: Niklas Schnelle <schnelle@linux.ibm.com>
Thanks for testing and the ack!
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages()
2020-09-01 22:16 ` [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages() Nicolin Chen
@ 2020-09-03 3:47 ` Michael Ellerman
2020-09-03 10:57 ` Andy Shevchenko
1 sibling, 0 replies; 10+ messages in thread
From: Michael Ellerman @ 2020-09-03 3:47 UTC (permalink / raw)
To: Nicolin Chen, hch
Cc: sfr, benh, paulus, linuxppc-dev, linux-kernel, rth, ink,
mattst88, linux-alpha, tony.luck, fenghua.yu, linux-ia64,
schnelle, gerald.schaefer, hca, gor, borntraeger, linux-s390,
davem, sparclinux, tglx, mingo, bp, x86, hpa, James.Bottomley,
deller, linux-parisc
Nicolin Chen <nicoleotsuka@gmail.com> writes:
> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
> index 9704f3f76e63..cbc2e62db597 100644
> --- a/arch/powerpc/kernel/iommu.c
> +++ b/arch/powerpc/kernel/iommu.c
> @@ -236,15 +236,10 @@ static unsigned long iommu_range_alloc(struct device *dev,
> }
> }
>
> - if (dev)
> - boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
> - 1 << tbl->it_page_shift);
> - else
> - boundary_size = ALIGN(1UL << 32, 1 << tbl->it_page_shift);
> - /* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
> + boundary_size = dma_get_seg_boundary_nr_pages(dev, tbl->it_page_shift);
>
> n = iommu_area_alloc(tbl->it_map, limit, start, npages, tbl->it_offset,
> - boundary_size >> tbl->it_page_shift, align_mask);
> + boundary_size, align_mask);
This has changed the units of boundary_size, but it's unused elsewhere
in the function so that's OK.
If you need to do a v2 for any other reason, then I'd just drop
boundary_size and call dma_get_seg_boundary_nr_pages() directly in the
function call.
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
cheers
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages()
2020-09-01 22:16 ` [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages() Nicolin Chen
2020-09-03 3:47 ` Michael Ellerman
@ 2020-09-03 10:57 ` Andy Shevchenko
2020-09-03 16:12 ` Christoph Hellwig
1 sibling, 1 reply; 10+ messages in thread
From: Andy Shevchenko @ 2020-09-03 10:57 UTC (permalink / raw)
To: Nicolin Chen
Cc: Christoph Hellwig, Stephen Rothwell, Michael Ellerman,
Benjamin Herrenschmidt, Paul Mackerras,
open list:LINUX FOR POWERPC PA SEMI PWRFICIENT,
Linux Kernel Mailing List, rth, ink, Matt Turner, linux-alpha,
Tony Luck, Fenghua Yu, linux-ia64, schnelle, gerald.schaefer,
hca, Vasily Gorbik, Christian Borntraeger, linux-s390,
David S. Miller, sparclinux, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, James Bottomley, Helge Deller, linux-parisc
On Wed, Sep 2, 2020 at 1:20 AM Nicolin Chen <nicoleotsuka@gmail.com> wrote:
>
> We found that callers of dma_get_seg_boundary mostly do an ALIGN
> with page mask and then do a page shift to get number of pages:
> ALIGN(boundary + 1, 1 << shift) >> shift
>
> However, the boundary might be as large as ULONG_MAX, which means
> that a device has no specific boundary limit. So either "+ 1" or
> passing it to ALIGN() would potentially overflow.
>
> According to kernel defines:
> #define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
> #define ALIGN(x, a) ALIGN_MASK(x, (typeof(x))(a) - 1)
>
> We can simplify the logic here into a helper function doing:
> ALIGN(boundary + 1, 1 << shift) >> shift
> = ALIGN_MASK(b + 1, (1 << s) - 1) >> s
> = {[b + 1 + (1 << s) - 1] & ~[(1 << s) - 1]} >> s
> = [b + 1 + (1 << s) - 1] >> s
> = [b + (1 << s)] >> s
> = (b >> s) + 1
>
> This patch introduces and applies dma_get_seg_boundary_nr_pages()
> as an overflow-free helper for the dma_get_seg_boundary() callers
> to get numbers of pages. It also takes care of the NULL dev case
> for non-DMA API callers.
...
> +static inline unsigned long dma_get_seg_boundary_nr_pages(struct device *dev,
> + unsigned int page_shift)
> +{
> + if (!dev)
> + return (U32_MAX >> page_shift) + 1;
> + return (dma_get_seg_boundary(dev) >> page_shift) + 1;
Can it be better to do something like
unsigned long boundary = dev ? dma_get_seg_boundary(dev) : U32_MAX;
return (boundary >> page_shift) + 1;
?
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages()
2020-09-03 10:57 ` Andy Shevchenko
@ 2020-09-03 16:12 ` Christoph Hellwig
2020-09-03 17:53 ` Christophe Leroy
0 siblings, 1 reply; 10+ messages in thread
From: Christoph Hellwig @ 2020-09-03 16:12 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Nicolin Chen, Christoph Hellwig, Stephen Rothwell,
Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
open list:LINUX FOR POWERPC PA SEMI PWRFICIENT,
Linux Kernel Mailing List, rth, ink, Matt Turner, linux-alpha,
Tony Luck, Fenghua Yu, linux-ia64, schnelle, gerald.schaefer,
hca, Vasily Gorbik, Christian Borntraeger, linux-s390,
David S. Miller, sparclinux, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, James Bottomley, Helge Deller, linux-parisc
On Thu, Sep 03, 2020 at 01:57:39PM +0300, Andy Shevchenko wrote:
> > +{
> > + if (!dev)
> > + return (U32_MAX >> page_shift) + 1;
> > + return (dma_get_seg_boundary(dev) >> page_shift) + 1;
>
> Can it be better to do something like
> unsigned long boundary = dev ? dma_get_seg_boundary(dev) : U32_MAX;
>
> return (boundary >> page_shift) + 1;
>
> ?
I don't really see what that would buy us.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] dma-mapping: update default segment_boundary_mask
2020-09-02 8:13 ` [PATCH 0/2] dma-mapping: update default segment_boundary_mask Niklas Schnelle
2020-09-03 3:26 ` Nicolin Chen
@ 2020-09-03 16:13 ` Christoph Hellwig
1 sibling, 0 replies; 10+ messages in thread
From: Christoph Hellwig @ 2020-09-03 16:13 UTC (permalink / raw)
To: Niklas Schnelle
Cc: Nicolin Chen, hch, sfr, mpe, benh, paulus, linuxppc-dev,
linux-kernel, rth, ink, mattst88, linux-alpha, tony.luck,
fenghua.yu, linux-ia64, gerald.schaefer, hca, gor, borntraeger,
linux-s390, davem, sparclinux, tglx, mingo, bp, x86, hpa,
James.Bottomley, deller, linux-parisc
Applied with the recommendation from Michael folded in.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages()
2020-09-03 16:12 ` Christoph Hellwig
@ 2020-09-03 17:53 ` Christophe Leroy
0 siblings, 0 replies; 10+ messages in thread
From: Christophe Leroy @ 2020-09-03 17:53 UTC (permalink / raw)
To: Christoph Hellwig, Andy Shevchenko
Cc: linux-ia64, James Bottomley, Paul Mackerras, H. Peter Anvin,
sparclinux, Stephen Rothwell, Helge Deller,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
Christian Borntraeger, Ingo Molnar, Matt Turner, Fenghua Yu,
Vasily Gorbik, schnelle, hca, Nicolin Chen, ink, Thomas Gleixner,
gerald.schaefer, rth, Tony Luck, linux-parisc, linux-s390,
Linux Kernel Mailing List, linux-alpha, Borislav Petkov,
open list:LINUX FOR POWERPC PA SEMI PWRFICIENT, David S. Miller
Le 03/09/2020 à 18:12, Christoph Hellwig a écrit :
> On Thu, Sep 03, 2020 at 01:57:39PM +0300, Andy Shevchenko wrote:
>>> +{
>>> + if (!dev)
>>> + return (U32_MAX >> page_shift) + 1;
>>> + return (dma_get_seg_boundary(dev) >> page_shift) + 1;
>>
>> Can it be better to do something like
>> unsigned long boundary = dev ? dma_get_seg_boundary(dev) : U32_MAX;
>>
>> return (boundary >> page_shift) + 1;
>>
>> ?
>
> I don't really see what that would buy us.
>
I guess it would avoid the duplication of >> page_shift) + 1
Christophe
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2020-09-03 17:59 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-01 22:16 [PATCH 0/2] dma-mapping: update default segment_boundary_mask Nicolin Chen
2020-09-01 22:16 ` [PATCH 1/2] dma-mapping: introduce dma_get_seg_boundary_nr_pages() Nicolin Chen
2020-09-03 3:47 ` Michael Ellerman
2020-09-03 10:57 ` Andy Shevchenko
2020-09-03 16:12 ` Christoph Hellwig
2020-09-03 17:53 ` Christophe Leroy
2020-09-01 22:16 ` [PATCH 2/2] dma-mapping: set default segment_boundary_mask to ULONG_MAX Nicolin Chen
2020-09-02 8:13 ` [PATCH 0/2] dma-mapping: update default segment_boundary_mask Niklas Schnelle
2020-09-03 3:26 ` Nicolin Chen
2020-09-03 16:13 ` Christoph Hellwig
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).