Add samsung specific changes
This commit is contained in:
@@ -120,6 +120,18 @@ config DMA_RESTRICTED_POOL
|
||||
and <kernel/dma/swiotlb.c>.
|
||||
If unsure, say "n".
|
||||
|
||||
config SWIOTLB_NONLINEAR
|
||||
bool "Allow swiotlb to use non-linear memory as bounce buffers"
|
||||
depends on SWIOTLB
|
||||
help
|
||||
This allows swiotlb driver to work with memory regions where
|
||||
physical to virtual address translations can't be done using APIs
|
||||
such as phys_to_virt. These could be reserved memory regions that
|
||||
are not mapped by default or could be seen as "device" memory
|
||||
accessed via ioremap().
|
||||
|
||||
If unsure, say "n".
|
||||
|
||||
#
|
||||
# Should be selected if we can mmap non-coherent mappings to userspace.
|
||||
# The only thing that is really required is a way to set an uncached bit
|
||||
|
@@ -96,6 +96,16 @@ static struct io_tlb_mem io_tlb_default_mem;
|
||||
|
||||
#endif /* CONFIG_SWIOTLB_DYNAMIC */
|
||||
|
||||
#ifdef CONFIG_SWIOTLB_NONLINEAR
|
||||
phys_addr_t io_tlb_start, io_tlb_end;
|
||||
static unsigned long io_tlb_nslabs;
|
||||
static char *io_tlb_vstart;
|
||||
|
||||
static inline unsigned char *swiotlb_phys_to_virt(phys_addr_t tlb_addr);
|
||||
#else
|
||||
#define swiotlb_phys_to_virt phys_to_virt
|
||||
#endif
|
||||
|
||||
static unsigned long default_nslabs = IO_TLB_DEFAULT_SIZE >> IO_TLB_SHIFT;
|
||||
static unsigned long default_nareas;
|
||||
|
||||
@@ -266,7 +276,7 @@ void __init swiotlb_update_mem_attributes(void)
|
||||
static void swiotlb_init_io_tlb_pool(struct io_tlb_pool *mem, phys_addr_t start,
|
||||
unsigned long nslabs, bool late_alloc, unsigned int nareas)
|
||||
{
|
||||
void *vaddr = phys_to_virt(start);
|
||||
void *vaddr = swiotlb_phys_to_virt(start);
|
||||
unsigned long bytes = nslabs << IO_TLB_SHIFT, i;
|
||||
|
||||
mem->nslabs = nslabs;
|
||||
@@ -518,6 +528,63 @@ error_area:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SWIOTLB_NONLINEAR
|
||||
static int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
|
||||
{
|
||||
struct io_tlb_pool *mem = &io_tlb_default_mem.defpool;
|
||||
unsigned long bytes = nslabs << IO_TLB_SHIFT;
|
||||
unsigned int area_order;
|
||||
|
||||
/* protect against double initialization */
|
||||
if (WARN_ON_ONCE(mem->nslabs))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!default_nareas)
|
||||
swiotlb_adjust_nareas(num_possible_cpus());
|
||||
|
||||
area_order = get_order(array_size(sizeof(*mem->areas),
|
||||
default_nareas));
|
||||
mem->areas = (struct io_tlb_area *)
|
||||
__get_free_pages(GFP_KERNEL | __GFP_ZERO, area_order);
|
||||
if (!mem->areas)
|
||||
return -ENOMEM;
|
||||
|
||||
mem->slots = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
|
||||
get_order(array_size(sizeof(*mem->slots), nslabs)));
|
||||
if (!mem->slots)
|
||||
goto error_slots;
|
||||
|
||||
set_memory_decrypted((unsigned long)tlb, bytes >> PAGE_SHIFT);
|
||||
swiotlb_init_io_tlb_pool(mem, io_tlb_start, nslabs, true, default_nareas);
|
||||
add_mem_pool(&io_tlb_default_mem, mem);
|
||||
|
||||
swiotlb_print_info();
|
||||
return 0;
|
||||
|
||||
error_slots:
|
||||
free_pages((unsigned long)mem->areas, area_order);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int swiotlb_late_init_with_tblpaddr(char *tlb,
|
||||
phys_addr_t tlb_paddr, unsigned long nslabs)
|
||||
{
|
||||
unsigned long bytes;
|
||||
|
||||
if (io_tlb_start)
|
||||
return -EBUSY;
|
||||
|
||||
bytes = nslabs << IO_TLB_SHIFT;
|
||||
io_tlb_nslabs = nslabs;
|
||||
io_tlb_start = tlb_paddr;
|
||||
io_tlb_vstart = tlb;
|
||||
io_tlb_end = io_tlb_start + bytes;
|
||||
|
||||
return swiotlb_late_init_with_tbl(tlb, nslabs);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(swiotlb_late_init_with_tblpaddr);
|
||||
#endif /* CONFIG_SWIOTLB_NONLINEAR */
|
||||
|
||||
void __init swiotlb_exit(void)
|
||||
{
|
||||
struct io_tlb_pool *mem = &io_tlb_default_mem.defpool;
|
||||
@@ -829,6 +896,13 @@ static unsigned int swiotlb_align_offset(struct device *dev, u64 addr)
|
||||
return addr & dma_get_min_align_mask(dev) & (IO_TLB_SIZE - 1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SWIOTLB_NONLINEAR
|
||||
static inline unsigned char *swiotlb_phys_to_virt(phys_addr_t tlb_addr)
|
||||
{
|
||||
return (unsigned char *)(io_tlb_vstart + (tlb_addr - io_tlb_start));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bounce: copy the swiotlb buffer from or back to the original dma location
|
||||
*/
|
||||
@@ -1431,6 +1505,10 @@ void swiotlb_tbl_unmap_single(struct device *dev, phys_addr_t tlb_addr,
|
||||
swiotlb_release_slots(dev, tlb_addr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SWIOTLB_NONLINEAR
|
||||
EXPORT_SYMBOL_GPL(swiotlb_tbl_unmap_single);
|
||||
#endif
|
||||
|
||||
void swiotlb_sync_single_for_device(struct device *dev, phys_addr_t tlb_addr,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
{
|
||||
@@ -1481,6 +1559,15 @@ dma_addr_t swiotlb_map(struct device *dev, phys_addr_t paddr, size_t size,
|
||||
arch_sync_dma_for_device(swiotlb_addr, size, dir);
|
||||
return dma_addr;
|
||||
}
|
||||
#ifdef CONFIG_SWIOTLB_NONLINEAR
|
||||
EXPORT_SYMBOL_GPL(swiotlb_map);
|
||||
|
||||
size_t swiotlb_max_mapping_size(struct device *dev)
|
||||
{
|
||||
return 4096;
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
size_t swiotlb_max_mapping_size(struct device *dev)
|
||||
{
|
||||
@@ -1497,6 +1584,7 @@ size_t swiotlb_max_mapping_size(struct device *dev)
|
||||
|
||||
return ((size_t)IO_TLB_SIZE) * IO_TLB_SEGSIZE - min_align;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* is_swiotlb_allocated() - check if the default software IO TLB is initialized
|
||||
|
Reference in New Issue
Block a user