Skip to content

Commit 8fd2ed1

Browse files
committed
Merge branch 'stable/for-linus-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb
Pull swiotlb fix from Konrad Rzeszutek Wilk: "A fix for the regression for the DMA operations where the offset was ignored and corruptions would appear. Going forward there will be a cleanups to make the offset and alignment logic more clearer and better test-cases to help with this" * 'stable/for-linus-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb: swiotlb: manipulate orig_addr when tlb_addr has offset
2 parents 0c18f29 + 5f89468 commit 8fd2ed1

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

kernel/dma/swiotlb.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,14 @@ void __init swiotlb_exit(void)
334334
io_tlb_default_mem = NULL;
335335
}
336336

337+
/*
338+
* Return the offset into a iotlb slot required to keep the device happy.
339+
*/
340+
static unsigned int swiotlb_align_offset(struct device *dev, u64 addr)
341+
{
342+
return addr & dma_get_min_align_mask(dev) & (IO_TLB_SIZE - 1);
343+
}
344+
337345
/*
338346
* Bounce: copy the swiotlb buffer from or back to the original dma location
339347
*/
@@ -346,10 +354,17 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size
346354
size_t alloc_size = mem->slots[index].alloc_size;
347355
unsigned long pfn = PFN_DOWN(orig_addr);
348356
unsigned char *vaddr = phys_to_virt(tlb_addr);
357+
unsigned int tlb_offset;
349358

350359
if (orig_addr == INVALID_PHYS_ADDR)
351360
return;
352361

362+
tlb_offset = (tlb_addr & (IO_TLB_SIZE - 1)) -
363+
swiotlb_align_offset(dev, orig_addr);
364+
365+
orig_addr += tlb_offset;
366+
alloc_size -= tlb_offset;
367+
353368
if (size > alloc_size) {
354369
dev_WARN_ONCE(dev, 1,
355370
"Buffer overflow detected. Allocation size: %zu. Mapping size: %zu.\n",
@@ -390,14 +405,6 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size
390405

391406
#define slot_addr(start, idx) ((start) + ((idx) << IO_TLB_SHIFT))
392407

393-
/*
394-
* Return the offset into a iotlb slot required to keep the device happy.
395-
*/
396-
static unsigned int swiotlb_align_offset(struct device *dev, u64 addr)
397-
{
398-
return addr & dma_get_min_align_mask(dev) & (IO_TLB_SIZE - 1);
399-
}
400-
401408
/*
402409
* Carefully handle integer overflow which can occur when boundary_mask == ~0UL.
403410
*/

0 commit comments

Comments
 (0)