Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
このコミットが含まれているのは:
@@ -640,6 +640,7 @@ static inline void radix_tree_shrink(struct radix_tree_root *root,
|
||||
update_node(node, private);
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(!list_empty(&node->private_list));
|
||||
radix_tree_node_free(node);
|
||||
}
|
||||
}
|
||||
@@ -666,6 +667,7 @@ static void delete_node(struct radix_tree_root *root,
|
||||
root->rnode = NULL;
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(!list_empty(&node->private_list));
|
||||
radix_tree_node_free(node);
|
||||
|
||||
node = parent;
|
||||
@@ -767,6 +769,7 @@ static void radix_tree_free_nodes(struct radix_tree_node *node)
|
||||
struct radix_tree_node *old = child;
|
||||
offset = child->offset + 1;
|
||||
child = child->parent;
|
||||
WARN_ON_ONCE(!list_empty(&node->private_list));
|
||||
radix_tree_node_free(old);
|
||||
if (old == entry_to_node(node))
|
||||
return;
|
||||
@@ -1824,15 +1827,19 @@ EXPORT_SYMBOL(radix_tree_gang_lookup_tag_slot);
|
||||
* __radix_tree_delete_node - try to free node after clearing a slot
|
||||
* @root: radix tree root
|
||||
* @node: node containing @index
|
||||
* @update_node: callback for changing leaf nodes
|
||||
* @private: private data to pass to @update_node
|
||||
*
|
||||
* After clearing the slot at @index in @node from radix tree
|
||||
* rooted at @root, call this function to attempt freeing the
|
||||
* node and shrinking the tree.
|
||||
*/
|
||||
void __radix_tree_delete_node(struct radix_tree_root *root,
|
||||
struct radix_tree_node *node)
|
||||
struct radix_tree_node *node,
|
||||
radix_tree_update_node_t update_node,
|
||||
void *private)
|
||||
{
|
||||
delete_node(root, node, NULL, NULL);
|
||||
delete_node(root, node, update_node, private);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -53,7 +53,7 @@
|
||||
*/
|
||||
#define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
|
||||
|
||||
int swiotlb_force;
|
||||
enum swiotlb_force swiotlb_force;
|
||||
|
||||
/*
|
||||
* Used to do a quick range check in swiotlb_tbl_unmap_single and
|
||||
@@ -82,6 +82,12 @@ static phys_addr_t io_tlb_overflow_buffer;
|
||||
static unsigned int *io_tlb_list;
|
||||
static unsigned int io_tlb_index;
|
||||
|
||||
/*
|
||||
* Max segment that we can provide which (if pages are contingous) will
|
||||
* not be bounced (unless SWIOTLB_FORCE is set).
|
||||
*/
|
||||
unsigned int max_segment;
|
||||
|
||||
/*
|
||||
* We need to save away the original address corresponding to a mapped entry
|
||||
* for the sync operations.
|
||||
@@ -106,8 +112,12 @@ setup_io_tlb_npages(char *str)
|
||||
}
|
||||
if (*str == ',')
|
||||
++str;
|
||||
if (!strcmp(str, "force"))
|
||||
swiotlb_force = 1;
|
||||
if (!strcmp(str, "force")) {
|
||||
swiotlb_force = SWIOTLB_FORCE;
|
||||
} else if (!strcmp(str, "noforce")) {
|
||||
swiotlb_force = SWIOTLB_NO_FORCE;
|
||||
io_tlb_nslabs = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -120,6 +130,20 @@ unsigned long swiotlb_nr_tbl(void)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(swiotlb_nr_tbl);
|
||||
|
||||
unsigned int swiotlb_max_segment(void)
|
||||
{
|
||||
return max_segment;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(swiotlb_max_segment);
|
||||
|
||||
void swiotlb_set_max_segment(unsigned int val)
|
||||
{
|
||||
if (swiotlb_force == SWIOTLB_FORCE)
|
||||
max_segment = 1;
|
||||
else
|
||||
max_segment = rounddown(val, PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* default to 64MB */
|
||||
#define IO_TLB_DEFAULT_SIZE (64UL<<20)
|
||||
unsigned long swiotlb_size_or_default(void)
|
||||
@@ -201,6 +225,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
|
||||
if (verbose)
|
||||
swiotlb_print_info();
|
||||
|
||||
swiotlb_set_max_segment(io_tlb_nslabs << IO_TLB_SHIFT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -279,6 +304,7 @@ swiotlb_late_init_with_default_size(size_t default_size)
|
||||
rc = swiotlb_late_init_with_tbl(vstart, io_tlb_nslabs);
|
||||
if (rc)
|
||||
free_pages((unsigned long)vstart, order);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -333,6 +359,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
|
||||
|
||||
late_alloc = 1;
|
||||
|
||||
swiotlb_set_max_segment(io_tlb_nslabs << IO_TLB_SHIFT);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup4:
|
||||
@@ -347,6 +375,7 @@ cleanup2:
|
||||
io_tlb_end = 0;
|
||||
io_tlb_start = 0;
|
||||
io_tlb_nslabs = 0;
|
||||
max_segment = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -375,6 +404,7 @@ void __init swiotlb_free(void)
|
||||
PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
|
||||
}
|
||||
io_tlb_nslabs = 0;
|
||||
max_segment = 0;
|
||||
}
|
||||
|
||||
int is_swiotlb_buffer(phys_addr_t paddr)
|
||||
@@ -543,8 +573,15 @@ static phys_addr_t
|
||||
map_single(struct device *hwdev, phys_addr_t phys, size_t size,
|
||||
enum dma_data_direction dir, unsigned long attrs)
|
||||
{
|
||||
dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
|
||||
dma_addr_t start_dma_addr;
|
||||
|
||||
if (swiotlb_force == SWIOTLB_NO_FORCE) {
|
||||
dev_warn_ratelimited(hwdev, "Cannot do DMA to address %pa\n",
|
||||
&phys);
|
||||
return SWIOTLB_MAP_ERROR;
|
||||
}
|
||||
|
||||
start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
|
||||
return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size,
|
||||
dir, attrs);
|
||||
}
|
||||
@@ -721,6 +758,9 @@ static void
|
||||
swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
|
||||
int do_panic)
|
||||
{
|
||||
if (swiotlb_force == SWIOTLB_NO_FORCE)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Ran out of IOMMU space for this operation. This is very bad.
|
||||
* Unfortunately the drivers cannot handle this operation properly.
|
||||
@@ -763,7 +803,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
|
||||
* we can safely return the device addr and not worry about bounce
|
||||
* buffering it.
|
||||
*/
|
||||
if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
|
||||
if (dma_capable(dev, dev_addr, size) && swiotlb_force != SWIOTLB_FORCE)
|
||||
return dev_addr;
|
||||
|
||||
trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
|
||||
@@ -904,7 +944,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
|
||||
phys_addr_t paddr = sg_phys(sg);
|
||||
dma_addr_t dev_addr = phys_to_dma(hwdev, paddr);
|
||||
|
||||
if (swiotlb_force ||
|
||||
if (swiotlb_force == SWIOTLB_FORCE ||
|
||||
!dma_capable(hwdev, dev_addr, sg->length)) {
|
||||
phys_addr_t map = map_single(hwdev, sg_phys(sg),
|
||||
sg->length, dir, attrs);
|
||||
|
新しいイシューから参照
ユーザーをブロックする