Re: [PATCH 6/9] swiotlb: refactor swiotlb_tbl_map_single

2021-02-22 Thread Christoph Hellwig
On Mon, Feb 22, 2021 at 02:29:37PM -0500, Konrad Rzeszutek Wilk wrote:
> > 'max_slots' should be 'unsigned long' here. Breaks SWIOTLB on RPi4. Do you 
> > want
> > me to send a fix or you prefer editing the patch?
> 
> I can roll it in. Thx!

Thanks to both of you!
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 6/9] swiotlb: refactor swiotlb_tbl_map_single

2021-02-22 Thread Konrad Rzeszutek Wilk
> > +static int find_slots(struct device *dev, size_t alloc_size)
> > +{
> > +   unsigned long boundary_mask = dma_get_seg_boundary(dev);
> > +   dma_addr_t tbl_dma_addr =
> > +   phys_to_dma_unencrypted(dev, io_tlb_start) & boundary_mask;
> > +   unsigned int max_slots = get_max_slots(boundary_mask);
> 
> 'max_slots' should be 'unsigned long' here. Breaks SWIOTLB on RPi4. Do you 
> want
> me to send a fix or you prefer editing the patch?

I can roll it in. Thx!
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 6/9] swiotlb: refactor swiotlb_tbl_map_single

2021-02-22 Thread Nicolas Saenz Julienne
Hi Christoph,

On Sun, 2021-02-07 at 17:03 +0100, Christoph Hellwig wrote:
> Split out a bunch of a self-contained helpers to make the function easier
> to follow.
> 
> Signed-off-by: Christoph Hellwig 
> ---
>  kernel/dma/swiotlb.c | 179 +--
>  1 file changed, 89 insertions(+), 90 deletions(-)
> 
> diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
> index b38b1553c4663a..381c24ef1ac1d0 100644
> --- a/kernel/dma/swiotlb.c
> +++ b/kernel/dma/swiotlb.c
> @@ -468,134 +468,133 @@ static void swiotlb_bounce(phys_addr_t orig_addr, 
> phys_addr_t tlb_addr,
>   }
>  }
>  
> 
> -phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t 
> orig_addr,
> - size_t mapping_size, size_t alloc_size,
> - enum dma_data_direction dir, unsigned long attrs)
> -{
> - dma_addr_t tbl_dma_addr = phys_to_dma_unencrypted(hwdev, io_tlb_start);
> - unsigned long flags;
> - phys_addr_t tlb_addr;
> - unsigned int nslots, stride, index, wrap;
> - int i;
> - unsigned long mask;
> - unsigned long offset_slots;
> - unsigned long max_slots;
> - unsigned long tmp_io_tlb_used;
> -
> - if (no_iotlb_memory)
> - panic("Can not allocate SWIOTLB buffer earlier and can't now 
> provide you with the DMA bounce buffer");
> -
> - if (mem_encrypt_active())
> - pr_warn_once("Memory encryption is active and system is using 
> DMA bounce buffers\n");
> +#define slot_addr(start, idx)((start) + ((idx) << IO_TLB_SHIFT))
>  
> 
> - if (mapping_size > alloc_size) {
> - dev_warn_once(hwdev, "Invalid sizes (mapping: %zd bytes, alloc: 
> %zd bytes)",
> -   mapping_size, alloc_size);
> - return (phys_addr_t)DMA_MAPPING_ERROR;
> - }
> -
> - mask = dma_get_seg_boundary(hwdev);
> +/*
> + * Carefully handle integer overflow which can occur when boundary_mask == 
> ~0UL.
> + */
> +static inline unsigned long get_max_slots(unsigned long boundary_mask)
> +{
> + if (boundary_mask == ~0UL)
> + return 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
> + return nr_slots(boundary_mask + 1);
> +}
>  
> 
> - tbl_dma_addr &= mask;
> +static unsigned int wrap_index(unsigned int index)
> +{
> + if (index >= io_tlb_nslabs)
> + return 0;
> + return index;
> +}
>  
> 
> - offset_slots = nr_slots(tbl_dma_addr);
> +/*
> + * Find a suitable number of IO TLB entries size that will fit this request 
> and
> + * allocate a buffer from that IO TLB pool.
> + */
> +static int find_slots(struct device *dev, size_t alloc_size)
> +{
> + unsigned long boundary_mask = dma_get_seg_boundary(dev);
> + dma_addr_t tbl_dma_addr =
> + phys_to_dma_unencrypted(dev, io_tlb_start) & boundary_mask;
> + unsigned int max_slots = get_max_slots(boundary_mask);

'max_slots' should be 'unsigned long' here. Breaks SWIOTLB on RPi4. Do you want
me to send a fix or you prefer editing the patch?

Regards,
Nicolas



signature.asc
Description: This is a digitally signed message part
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH 6/9] swiotlb: refactor swiotlb_tbl_map_single

2021-02-07 Thread Christoph Hellwig
Split out a bunch of a self-contained helpers to make the function easier
to follow.

Signed-off-by: Christoph Hellwig 
---
 kernel/dma/swiotlb.c | 179 +--
 1 file changed, 89 insertions(+), 90 deletions(-)

diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index b38b1553c4663a..381c24ef1ac1d0 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -468,134 +468,133 @@ static void swiotlb_bounce(phys_addr_t orig_addr, 
phys_addr_t tlb_addr,
}
 }
 
-phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, phys_addr_t orig_addr,
-   size_t mapping_size, size_t alloc_size,
-   enum dma_data_direction dir, unsigned long attrs)
-{
-   dma_addr_t tbl_dma_addr = phys_to_dma_unencrypted(hwdev, io_tlb_start);
-   unsigned long flags;
-   phys_addr_t tlb_addr;
-   unsigned int nslots, stride, index, wrap;
-   int i;
-   unsigned long mask;
-   unsigned long offset_slots;
-   unsigned long max_slots;
-   unsigned long tmp_io_tlb_used;
-
-   if (no_iotlb_memory)
-   panic("Can not allocate SWIOTLB buffer earlier and can't now 
provide you with the DMA bounce buffer");
-
-   if (mem_encrypt_active())
-   pr_warn_once("Memory encryption is active and system is using 
DMA bounce buffers\n");
+#define slot_addr(start, idx)  ((start) + ((idx) << IO_TLB_SHIFT))
 
-   if (mapping_size > alloc_size) {
-   dev_warn_once(hwdev, "Invalid sizes (mapping: %zd bytes, alloc: 
%zd bytes)",
- mapping_size, alloc_size);
-   return (phys_addr_t)DMA_MAPPING_ERROR;
-   }
-
-   mask = dma_get_seg_boundary(hwdev);
+/*
+ * Carefully handle integer overflow which can occur when boundary_mask == 
~0UL.
+ */
+static inline unsigned long get_max_slots(unsigned long boundary_mask)
+{
+   if (boundary_mask == ~0UL)
+   return 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
+   return nr_slots(boundary_mask + 1);
+}
 
-   tbl_dma_addr &= mask;
+static unsigned int wrap_index(unsigned int index)
+{
+   if (index >= io_tlb_nslabs)
+   return 0;
+   return index;
+}
 
-   offset_slots = nr_slots(tbl_dma_addr);
+/*
+ * Find a suitable number of IO TLB entries size that will fit this request and
+ * allocate a buffer from that IO TLB pool.
+ */
+static int find_slots(struct device *dev, size_t alloc_size)
+{
+   unsigned long boundary_mask = dma_get_seg_boundary(dev);
+   dma_addr_t tbl_dma_addr =
+   phys_to_dma_unencrypted(dev, io_tlb_start) & boundary_mask;
+   unsigned int max_slots = get_max_slots(boundary_mask);
+   unsigned int nslots = nr_slots(alloc_size), stride = 1;
+   unsigned int index, wrap, count = 0, i;
+   unsigned long flags;
 
-   /*
-* Carefully handle integer overflow which can occur when mask == ~0UL.
-*/
-   max_slots = mask + 1
-   ? nr_slots(mask + 1)
-   : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
+   BUG_ON(!nslots);
 
/*
 * For mappings greater than or equal to a page, we limit the stride
 * (and hence alignment) to a page size.
 */
-   nslots = nr_slots(alloc_size);
if (alloc_size >= PAGE_SIZE)
-   stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
-   else
-   stride = 1;
+   stride <<= (PAGE_SHIFT - IO_TLB_SHIFT);
 
-   BUG_ON(!nslots);
-
-   /*
-* Find suitable number of IO TLB entries size that will fit this
-* request and allocate a buffer from that IO TLB pool.
-*/
spin_lock_irqsave(&io_tlb_lock, flags);
-
if (unlikely(nslots > io_tlb_nslabs - io_tlb_used))
goto not_found;
 
-   index = ALIGN(io_tlb_index, stride);
-   if (index >= io_tlb_nslabs)
-   index = 0;
-   wrap = index;
-
+   index = wrap = wrap_index(ALIGN(io_tlb_index, stride));
do {
-   while (iommu_is_span_boundary(index, nslots, offset_slots,
- max_slots)) {
-   index += stride;
-   if (index >= io_tlb_nslabs)
-   index = 0;
-   if (index == wrap)
-   goto not_found;
-   }
-
/*
 * If we find a slot that indicates we have 'nslots' number of
 * contiguous buffers, we allocate the buffers from that slot
 * and mark the entries as '0' indicating unavailable.
 */
-   if (io_tlb_list[index] >= nslots) {
-   int count = 0;
-
-   for (i = index; i < (int) (index + nslots); i++)
-   io_tlb_list[i] = 0;
-   for (i = index - 1;
-io_tlb_offset(i) != IO_TLB_SEGSIZ