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
This commit is contained in:
commit
8fd2ed1c01
|
@ -334,6 +334,14 @@ void __init swiotlb_exit(void)
|
|||
io_tlb_default_mem = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the offset into a iotlb slot required to keep the device happy.
|
||||
*/
|
||||
static unsigned int swiotlb_align_offset(struct device *dev, u64 addr)
|
||||
{
|
||||
return addr & dma_get_min_align_mask(dev) & (IO_TLB_SIZE - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bounce: copy the swiotlb buffer from or back to the original dma location
|
||||
*/
|
||||
|
@ -346,10 +354,17 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size
|
|||
size_t alloc_size = mem->slots[index].alloc_size;
|
||||
unsigned long pfn = PFN_DOWN(orig_addr);
|
||||
unsigned char *vaddr = phys_to_virt(tlb_addr);
|
||||
unsigned int tlb_offset;
|
||||
|
||||
if (orig_addr == INVALID_PHYS_ADDR)
|
||||
return;
|
||||
|
||||
tlb_offset = (tlb_addr & (IO_TLB_SIZE - 1)) -
|
||||
swiotlb_align_offset(dev, orig_addr);
|
||||
|
||||
orig_addr += tlb_offset;
|
||||
alloc_size -= tlb_offset;
|
||||
|
||||
if (size > alloc_size) {
|
||||
dev_WARN_ONCE(dev, 1,
|
||||
"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
|
|||
|
||||
#define slot_addr(start, idx) ((start) + ((idx) << IO_TLB_SHIFT))
|
||||
|
||||
/*
|
||||
* Return the offset into a iotlb slot required to keep the device happy.
|
||||
*/
|
||||
static unsigned int swiotlb_align_offset(struct device *dev, u64 addr)
|
||||
{
|
||||
return addr & dma_get_min_align_mask(dev) & (IO_TLB_SIZE - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Carefully handle integer overflow which can occur when boundary_mask == ~0UL.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue