static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr,
			      size_t alloc_size, unsigned int alloc_align_mask)
{
	struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
	unsigned long boundary_mask = dma_get_seg_boundary(dev);
	dma_addr_t tbl_dma_addr =
		phys_to_dma_unencrypted(dev, mem->start) & boundary_mask;
	unsigned long max_slots = get_max_slots(boundary_mask);
	unsigned int iotlb_align_mask =
		dma_get_min_align_mask(dev) & ~(IO_TLB_SIZE - 1);
	unsigned int nslots = nr_slots(alloc_size), stride;
	unsigned int index, wrap, count = 0, i;
	unsigned int offset = swiotlb_align_offset(dev, orig_addr);
	unsigned long flags;

	BUG_ON(!nslots);

	/*
	 * For mappings with an alignment requirement don't bother looping to
	 * unaligned slots once we found an aligned one.  For allocations of
	 * PAGE_SIZE or larger only look for page aligned allocations.
	 */
	stride = (iotlb_align_mask >> IO_TLB_SHIFT) + 1;
	if (alloc_size >= PAGE_SIZE)
		stride = max(stride, stride << (PAGE_SHIFT - IO_TLB_SHIFT));
	stride = max(stride, (alloc_align_mask >> IO_TLB_SHIFT) + 1);

	spin_lock_irqsave(&mem->lock, flags);
	if (unlikely(nslots > mem->nslabs - mem->used))
		goto not_found;

	index = wrap = wrap_index(mem, ALIGN(mem->index, stride));
	do {
		if (orig_addr &&
		    (slot_addr(tbl_dma_addr, index) & iotlb_align_mask) !=
			    (orig_addr & iotlb_align_mask)) {
			index = wrap_index(mem, index + 1);
			continue;
		}

		/*
		 * 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 (!iommu_is_span_boundary(index, nslots,
					    nr_slots(tbl_dma_addr),
					    max_slots)) {
			if (mem->slots[index].list >= nslots)
				goto found;
		}
		index = wrap_index(mem, index + stride);
	} while (index != wrap);

not_found:
	spin_unlock_irqrestore(&mem->lock, flags);
	return -1;

found:
	for (i = index; i < index + nslots; i++) {
		mem->slots[i].list = 0;
		mem->slots[i].alloc_size =
			alloc_size - (offset + ((i - index) << IO_TLB_SHIFT));
	}
	for (i = index - 1;
	     io_tlb_offset(i) != IO_TLB_SEGSIZE - 1 &&
	     mem->slots[i].list; i--)
		mem->slots[i].list = ++count;

	/*
	 * Update the indices to avoid searching in the next round.
	 */
	if (index + nslots < mem->nslabs)
		mem->index = index + nslots;
	else
		mem->index = 0;
	mem->used += nslots;

	spin_unlock_irqrestore(&mem->lock, flags);
	return index;
}
static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr,
			      size_t alloc_size, unsigned int alloc_align_mask)
{
	struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
	unsigned long boundary_mask = dma_get_seg_boundary(dev);
	dma_addr_t tbl_dma_addr =
		phys_to_dma_unencrypted(dev, mem->start) & boundary_mask;
	unsigned long max_slots = get_max_slots(boundary_mask);
	unsigned int iotlb_align_mask =
		dma_get_min_align_mask(dev) & ~(IO_TLB_SIZE - 1);
	unsigned int nslots = nr_slots(alloc_size), stride;
	unsigned int index, wrap, count = 0, i;
	unsigned int offset = swiotlb_align_offset(dev, orig_addr);
	unsigned long flags;

	BUG_ON(!nslots);

	 
	stride = (iotlb_align_mask >> IO_TLB_SHIFT) + 1;
	if (alloc_size >= PAGE_SIZE)
		stride = max(stride, stride << (PAGE_SHIFT - IO_TLB_SHIFT));
	stride = max(stride, (alloc_align_mask >> IO_TLB_SHIFT) + 1);

	spin_lock_irqsave(&mem->lock, flags);
	if (unlikely(nslots > mem->nslabs - mem->used))
		goto not_found;

	index = wrap = wrap_index(mem, ALIGN(mem->index, stride));
	do {
		if (orig_addr &&
		    (slot_addr(tbl_dma_addr, index) & iotlb_align_mask) !=
			    (orig_addr & iotlb_align_mask)) {
			index = wrap_index(mem, index + 1);
			continue;
		}

		 
		if (!iommu_is_span_boundary(index, nslots,
					    nr_slots(tbl_dma_addr),
					    max_slots)) {
			if (mem->slots[index].list >= nslots)
				goto found;
		}
		index = wrap_index(mem, index + stride);
	} while (index != wrap);

not_found:
	spin_unlock_irqrestore(&mem->lock, flags);
	return -1;

found:
	for (i = index; i < index + nslots; i++) {
		mem->slots[i].list = 0;
		mem->slots[i].alloc_size =
			alloc_size - (offset + ((i - index) << IO_TLB_SHIFT));
	}
	for (i = index - 1;
	     io_tlb_offset(i) != IO_TLB_SEGSIZE - 1 &&
	     mem->slots[i].list; i--)
		mem->slots[i].list = ++count;

	 
	if (index + nslots < mem->nslabs)
		mem->index = index + nslots;
	else
		mem->index = 0;
	mem->used += nslots;

	spin_unlock_irqrestore(&mem->lock, flags);
	return index;
}