From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org, Christoph Hellwig <hch@lst.de>,
Jianxiong Gao <jxgao@google.com>,
Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Subject: [PATCH 5.10 17/29] swiotlb: refactor swiotlb_tbl_map_single
Date: Wed, 5 May 2021 14:05:20 +0200 [thread overview]
Message-ID: <20210505112326.768975426@linuxfoundation.org> (raw)
In-Reply-To: <20210505112326.195493232@linuxfoundation.org>
From: Jianxiong Gao <jxgao@google.com>
commit: 26a7e094783d482f3e125f09945a5bb1d867b2e6
Split out a bunch of a self-contained helpers to make the function easier
to follow.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Jianxiong Gao <jxgao@google.com>
Tested-by: Jianxiong Gao <jxgao@google.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Jianxiong Gao <jxgao@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/dma/swiotlb.c | 179 +++++++++++++++++++++++++--------------------------
1 file changed, 89 insertions(+), 90 deletions(-)
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -452,134 +452,133 @@ static void swiotlb_bounce(phys_addr_t o
}
}
-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;
+#define slot_addr(start, idx) ((start) + ((idx) << IO_TLB_SHIFT))
- 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");
-
- 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 long 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;
-
- BUG_ON(!nslots);
+ stride <<= (PAGE_SHIFT - IO_TLB_SHIFT);
- /*
- * 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_SEGSIZE - 1 &&
- io_tlb_list[i]; i--)
- io_tlb_list[i] = ++count;
- tlb_addr = io_tlb_start + (index << IO_TLB_SHIFT);
-
- /*
- * Update the indices to avoid searching in the next
- * round.
- */
- io_tlb_index = ((index + nslots) < io_tlb_nslabs
- ? (index + nslots) : 0);
-
- goto found;
+ if (!iommu_is_span_boundary(index, nslots,
+ nr_slots(tbl_dma_addr),
+ max_slots)) {
+ if (io_tlb_list[index] >= nslots)
+ goto found;
}
- index += stride;
- if (index >= io_tlb_nslabs)
- index = 0;
+ index = wrap_index(index + stride);
} while (index != wrap);
not_found:
- tmp_io_tlb_used = io_tlb_used;
-
spin_unlock_irqrestore(&io_tlb_lock, flags);
- if (!(attrs & DMA_ATTR_NO_WARN) && printk_ratelimit())
- dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes), total %lu (slots), used %lu (slots)\n",
- alloc_size, io_tlb_nslabs, tmp_io_tlb_used);
- return (phys_addr_t)DMA_MAPPING_ERROR;
+ return -1;
+
found:
+ for (i = index; i < index + nslots; i++)
+ io_tlb_list[i] = 0;
+ for (i = index - 1;
+ io_tlb_offset(i) != IO_TLB_SEGSIZE - 1 &&
+ io_tlb_list[i]; i--)
+ io_tlb_list[i] = ++count;
+
+ /*
+ * Update the indices to avoid searching in the next round.
+ */
+ if (index + nslots < io_tlb_nslabs)
+ io_tlb_index = index + nslots;
+ else
+ io_tlb_index = 0;
io_tlb_used += nslots;
+
spin_unlock_irqrestore(&io_tlb_lock, flags);
+ return index;
+}
+
+phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
+ size_t mapping_size, size_t alloc_size,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+ unsigned int index, i;
+ phys_addr_t tlb_addr;
+
+ 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");
+
+ if (mapping_size > alloc_size) {
+ dev_warn_once(dev, "Invalid sizes (mapping: %zd bytes, alloc: %zd bytes)",
+ mapping_size, alloc_size);
+ return (phys_addr_t)DMA_MAPPING_ERROR;
+ }
+
+ index = find_slots(dev, alloc_size);
+ if (index == -1) {
+ if (!(attrs & DMA_ATTR_NO_WARN))
+ dev_warn_ratelimited(dev,
+ "swiotlb buffer is full (sz: %zd bytes), total %lu (slots), used %lu (slots)\n",
+ alloc_size, io_tlb_nslabs, io_tlb_used);
+ return (phys_addr_t)DMA_MAPPING_ERROR;
+ }
/*
* Save away the mapping from the original address to the DMA address.
* This is needed when we sync the memory. Then we sync the buffer if
* needed.
*/
- for (i = 0; i < nslots; i++)
- io_tlb_orig_addr[index+i] = orig_addr + (i << IO_TLB_SHIFT);
+ for (i = 0; i < nr_slots(alloc_size); i++)
+ io_tlb_orig_addr[index + i] = slot_addr(orig_addr, i);
+
+ tlb_addr = slot_addr(io_tlb_start, index);
if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
swiotlb_bounce(orig_addr, tlb_addr, mapping_size, DMA_TO_DEVICE);
-
return tlb_addr;
}
next prev parent reply other threads:[~2021-05-05 12:07 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-05 12:05 [PATCH 5.10 00/29] 5.10.35-rc1 review Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 01/29] mips: Do not include hi and lo in clobber list for R6 Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 02/29] netfilter: conntrack: Make global sysctls readonly in non-init netns Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 03/29] net: usb: ax88179_178a: initialize local variables before use Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 04/29] igb: Enable RSS for Intel I211 Ethernet Controller Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 05/29] bpf: Fix masking negation logic upon negative dst register Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 06/29] bpf: Fix leakage of uninitialized bpf stack under speculation Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 07/29] net: qrtr: Avoid potential use after free in MHI send Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 08/29] perf data: Fix error return code in perf_data__create_dir() Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 09/29] capabilities: require CAP_SETFCAP to map uid 0 Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 10/29] perf ftrace: Fix access to pid in array when setting a pid filter Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 11/29] tools/cgroup/slabinfo.py: updated to work on current kernel Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 12/29] driver core: add a min_align_mask field to struct device_dma_parameters Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 13/29] swiotlb: add a IO_TLB_SIZE define Greg Kroah-Hartman
2021-05-05 20:45 ` Yet another way to mark upstream commits was " Pavel Machek
2021-05-05 12:05 ` [PATCH 5.10 14/29] swiotlb: factor out an io_tlb_offset helper Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 15/29] swiotlb: factor out a nr_slots helper Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 16/29] swiotlb: clean up swiotlb_tbl_unmap_single Greg Kroah-Hartman
2021-05-05 12:05 ` Greg Kroah-Hartman [this message]
2021-05-05 12:05 ` [PATCH 5.10 18/29] swiotlb: dont modify orig_addr in swiotlb_tbl_sync_single Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 19/29] swiotlb: respect min_align_mask Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 20/29] nvme-pci: set min_align_mask Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 21/29] ovl: fix leaked dentry Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 22/29] ovl: allow upperdir inside lowerdir Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 23/29] ALSA: usb-audio: Add MIDI quirk for Vox ToneLab EX Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 24/29] USB: Add LPM quirk for Lenovo ThinkPad USB-C Dock Gen2 Ethernet Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 25/29] USB: Add reset-resume quirk for WD19s Realtek Hub Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 26/29] ASoC: ak4458: Add MODULE_DEVICE_TABLE Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 27/29] ASoC: ak5558: " Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 28/29] platform/x86: thinkpad_acpi: Correct thermal sensor allocation Greg Kroah-Hartman
2021-05-05 12:05 ` [PATCH 5.10 29/29] perf/core: Fix unconditional security_locked_down() call Greg Kroah-Hartman
2021-05-05 15:04 ` [PATCH 5.10 00/29] 5.10.35-rc1 review Patrick Mccormick
2021-05-05 18:54 ` Jon Hunter
2021-05-05 19:30 ` Florian Fainelli
2021-05-05 20:19 ` Fox Chen
2021-05-05 21:04 ` Shuah Khan
2021-05-06 1:50 ` Guenter Roeck
2021-05-06 2:52 ` Samuel Zou
2021-05-06 7:46 ` Naresh Kamboju
2021-05-06 8:57 ` Pavel Machek
2021-05-06 10:07 ` Sudip Mukherjee
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=20210505112326.768975426@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=hch@lst.de \
--cc=jxgao@google.com \
--cc=konrad.wilk@oracle.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@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 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.