diff options
author | Salvatore Bonaccorso <carnil@debian.org> | 2021-06-30 15:07:41 +0200 |
---|---|---|
committer | Salvatore Bonaccorso <carnil@debian.org> | 2021-06-30 15:36:57 +0200 |
commit | 64786232808b4aafaedd4702db095851e7be0a85 (patch) | |
tree | 7ef2bd4b46d1f62a12a75f837f5042d1829994c0 | |
parent | ff825241062a00346f18271297660ffd7954e23b (diff) | |
download | kernel_replicant_linux-64786232808b4aafaedd4702db095851e7be0a85.tar.gz kernel_replicant_linux-64786232808b4aafaedd4702db095851e7be0a85.tar.bz2 kernel_replicant_linux-64786232808b4aafaedd4702db095851e7be0a85.zip |
swiotlb: manipulate orig_addr when tlb_addr has offset
Closes: #989778
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | debian/patches/bugfix/all/swiotlb-manipulate-orig_addr-when-tlb_addr-has-offse.patch | 128 | ||||
-rw-r--r-- | debian/patches/series | 1 |
3 files changed, 135 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog index 089a9692cf5f..39095a13e29c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +linux (5.10.46-2) UNRELEASED; urgency=medium + + * swiotlb: manipulate orig_addr when tlb_addr has offset (Closes: #989778) + + -- Salvatore Bonaccorso <carnil@debian.org> Wed, 30 Jun 2021 15:08:29 +0200 + linux (5.10.46-1) unstable; urgency=medium * New upstream stable update: diff --git a/debian/patches/bugfix/all/swiotlb-manipulate-orig_addr-when-tlb_addr-has-offse.patch b/debian/patches/bugfix/all/swiotlb-manipulate-orig_addr-when-tlb_addr-has-offse.patch new file mode 100644 index 000000000000..cb3584b82cad --- /dev/null +++ b/debian/patches/bugfix/all/swiotlb-manipulate-orig_addr-when-tlb_addr-has-offse.patch @@ -0,0 +1,128 @@ +From: Bumyong Lee <bumyong.lee@samsung.com> +Date: Mon, 10 May 2021 18:10:04 +0900 +Subject: swiotlb: manipulate orig_addr when tlb_addr has offset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=e6108147dd91b94d1979b110f265710c254c99d5 +Bug-Debian: https://bugs.debian.org/989778 + +commit 5f89468e2f060031cd89fd4287298e0eaf246bf6 upstream. + +in case of driver wants to sync part of ranges with offset, +swiotlb_tbl_sync_single() copies from orig_addr base to tlb_addr with +offset and ends up with data mismatch. + +It was removed from +"swiotlb: don't modify orig_addr in swiotlb_tbl_sync_single", +but said logic has to be added back in. + +From Linus's email: +"That commit which the removed the offset calculation entirely, because the old + + (unsigned long)tlb_addr & (IO_TLB_SIZE - 1) + +was wrong, but instead of removing it, I think it should have just +fixed it to be + + (tlb_addr - mem->start) & (IO_TLB_SIZE - 1); + +instead. That way the slot offset always matches the slot index calculation." + +(Unfortunatly that broke NVMe). + +The use-case that drivers are hitting is as follow: + +1. Get dma_addr_t from dma_map_single() + +dma_addr_t tlb_addr = dma_map_single(dev, vaddr, vsize, DMA_TO_DEVICE); + + |<---------------vsize------------->| + +-----------------------------------+ + | | original buffer + +-----------------------------------+ + vaddr + + swiotlb_align_offset + |<----->|<---------------vsize------------->| + +-------+-----------------------------------+ + | | | swiotlb buffer + +-------+-----------------------------------+ + tlb_addr + +2. Do something +3. Sync dma_addr_t through dma_sync_single_for_device(..) + +dma_sync_single_for_device(dev, tlb_addr + offset, size, DMA_TO_DEVICE); + + Error case. + Copy data to original buffer but it is from base addr (instead of + base addr + offset) in original buffer: + + swiotlb_align_offset + |<----->|<- offset ->|<- size ->| + +-------+-----------------------------------+ + | | |##########| | swiotlb buffer + +-------+-----------------------------------+ + tlb_addr + + |<- size ->| + +-----------------------------------+ + |##########| | original buffer + +-----------------------------------+ + vaddr + +The fix is to copy the data to the original buffer and take into +account the offset, like so: + + swiotlb_align_offset + |<----->|<- offset ->|<- size ->| + +-------+-----------------------------------+ + | | |##########| | swiotlb buffer + +-------+-----------------------------------+ + tlb_addr + + |<- offset ->|<- size ->| + +-----------------------------------+ + | |##########| | original buffer + +-----------------------------------+ + vaddr + +[One fix which was Linus's that made more sense to as it created a +symmetry would break NVMe. The reason for that is the: + unsigned int offset = (tlb_addr - mem->start) & (IO_TLB_SIZE - 1); + +would come up with the proper offset, but it would lose the +alignment (which this patch contains).] + +Fixes: 16fc3cef33a0 ("swiotlb: don't modify orig_addr in swiotlb_tbl_sync_single") +Signed-off-by: Bumyong Lee <bumyong.lee@samsung.com> +Signed-off-by: Chanho Park <chanho61.park@samsung.com> +Reviewed-by: Christoph Hellwig <hch@lst.de> +Reported-by: Dominique MARTINET <dominique.martinet@atmark-techno.com> +Reported-by: Horia Geantă <horia.geanta@nxp.com> +Tested-by: Horia Geantă <horia.geanta@nxp.com> +CC: stable@vger.kernel.org +Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/dma/swiotlb.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c +index 0f61b14b0099..0ed0e1f215c7 100644 +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -667,6 +667,9 @@ void swiotlb_tbl_sync_single(struct device *hwdev, phys_addr_t tlb_addr, + if (orig_addr == INVALID_PHYS_ADDR) + return; + ++ orig_addr += (tlb_addr & (IO_TLB_SIZE - 1)) - ++ swiotlb_align_offset(hwdev, orig_addr); ++ + switch (target) { + case SYNC_FOR_CPU: + if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) +-- +2.32.0 + diff --git a/debian/patches/series b/debian/patches/series index af09b317a459..fd30c81d8dcf 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -95,6 +95,7 @@ bugfix/all/partially-revert-usb-kconfig-using-select-for-usb_co.patch debian/makefile-do-not-check-for-libelf-when-building-oot-module.patch bugfix/all/partially-revert-net-socket-implement-64-bit-timestamps.patch bugfix/all/Revert-PCI-PM-Do-not-read-power-state-in-pci_enable_.patch +bugfix/all/swiotlb-manipulate-orig_addr-when-tlb_addr-has-offse.patch # Miscellaneous features |