mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 05:06:29 +00:00
vfio: Commonize combine_ranges for use in other VFIO drivers
Currently only Mellanox uses the combine_ranges function. The new pds_vfio driver also needs this function. So, move it to a common location for other vendor drivers to use. Also, fix RCT ordering while moving/renaming the function. Cc: Yishai Hadas <yishaih@nvidia.com> Signed-off-by: Brett Creeley <brett.creeley@amd.com> Signed-off-by: Shannon Nelson <shannon.nelson@amd.com> Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> Link: https://lore.kernel.org/r/20230807205755.29579-2-brett.creeley@amd.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
73e2f19da5
commit
9a4087fab3
@ -732,52 +732,6 @@ void mlx5fv_cmd_clean_migf_resources(struct mlx5_vf_migration_file *migf)
|
||||
mlx5vf_cmd_dealloc_pd(migf);
|
||||
}
|
||||
|
||||
static void combine_ranges(struct rb_root_cached *root, u32 cur_nodes,
|
||||
u32 req_nodes)
|
||||
{
|
||||
struct interval_tree_node *prev, *curr, *comb_start, *comb_end;
|
||||
unsigned long min_gap;
|
||||
unsigned long curr_gap;
|
||||
|
||||
/* Special shortcut when a single range is required */
|
||||
if (req_nodes == 1) {
|
||||
unsigned long last;
|
||||
|
||||
curr = comb_start = interval_tree_iter_first(root, 0, ULONG_MAX);
|
||||
while (curr) {
|
||||
last = curr->last;
|
||||
prev = curr;
|
||||
curr = interval_tree_iter_next(curr, 0, ULONG_MAX);
|
||||
if (prev != comb_start)
|
||||
interval_tree_remove(prev, root);
|
||||
}
|
||||
comb_start->last = last;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Combine ranges which have the smallest gap */
|
||||
while (cur_nodes > req_nodes) {
|
||||
prev = NULL;
|
||||
min_gap = ULONG_MAX;
|
||||
curr = interval_tree_iter_first(root, 0, ULONG_MAX);
|
||||
while (curr) {
|
||||
if (prev) {
|
||||
curr_gap = curr->start - prev->last;
|
||||
if (curr_gap < min_gap) {
|
||||
min_gap = curr_gap;
|
||||
comb_start = prev;
|
||||
comb_end = curr;
|
||||
}
|
||||
}
|
||||
prev = curr;
|
||||
curr = interval_tree_iter_next(curr, 0, ULONG_MAX);
|
||||
}
|
||||
comb_start->last = comb_end->last;
|
||||
interval_tree_remove(comb_end, root);
|
||||
cur_nodes--;
|
||||
}
|
||||
}
|
||||
|
||||
static int mlx5vf_create_tracker(struct mlx5_core_dev *mdev,
|
||||
struct mlx5vf_pci_core_device *mvdev,
|
||||
struct rb_root_cached *ranges, u32 nnodes)
|
||||
@ -800,7 +754,7 @@ static int mlx5vf_create_tracker(struct mlx5_core_dev *mdev,
|
||||
int i;
|
||||
|
||||
if (num_ranges > max_num_range) {
|
||||
combine_ranges(ranges, nnodes, max_num_range);
|
||||
vfio_combine_iova_ranges(ranges, nnodes, max_num_range);
|
||||
num_ranges = max_num_range;
|
||||
}
|
||||
|
||||
|
@ -935,6 +935,53 @@ static int vfio_ioctl_device_feature_migration(struct vfio_device *device,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vfio_combine_iova_ranges(struct rb_root_cached *root, u32 cur_nodes,
|
||||
u32 req_nodes)
|
||||
{
|
||||
struct interval_tree_node *prev, *curr, *comb_start, *comb_end;
|
||||
unsigned long min_gap, curr_gap;
|
||||
|
||||
/* Special shortcut when a single range is required */
|
||||
if (req_nodes == 1) {
|
||||
unsigned long last;
|
||||
|
||||
comb_start = interval_tree_iter_first(root, 0, ULONG_MAX);
|
||||
curr = comb_start;
|
||||
while (curr) {
|
||||
last = curr->last;
|
||||
prev = curr;
|
||||
curr = interval_tree_iter_next(curr, 0, ULONG_MAX);
|
||||
if (prev != comb_start)
|
||||
interval_tree_remove(prev, root);
|
||||
}
|
||||
comb_start->last = last;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Combine ranges which have the smallest gap */
|
||||
while (cur_nodes > req_nodes) {
|
||||
prev = NULL;
|
||||
min_gap = ULONG_MAX;
|
||||
curr = interval_tree_iter_first(root, 0, ULONG_MAX);
|
||||
while (curr) {
|
||||
if (prev) {
|
||||
curr_gap = curr->start - prev->last;
|
||||
if (curr_gap < min_gap) {
|
||||
min_gap = curr_gap;
|
||||
comb_start = prev;
|
||||
comb_end = curr;
|
||||
}
|
||||
}
|
||||
prev = curr;
|
||||
curr = interval_tree_iter_next(curr, 0, ULONG_MAX);
|
||||
}
|
||||
comb_start->last = comb_end->last;
|
||||
interval_tree_remove(comb_end, root);
|
||||
cur_nodes--;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfio_combine_iova_ranges);
|
||||
|
||||
/* Ranges should fit into a single kernel page */
|
||||
#define LOG_MAX_RANGES \
|
||||
(PAGE_SIZE / sizeof(struct vfio_device_feature_dma_logging_range))
|
||||
|
@ -283,6 +283,9 @@ int vfio_mig_get_next_state(struct vfio_device *device,
|
||||
enum vfio_device_mig_state new_fsm,
|
||||
enum vfio_device_mig_state *next_fsm);
|
||||
|
||||
void vfio_combine_iova_ranges(struct rb_root_cached *root, u32 cur_nodes,
|
||||
u32 req_nodes);
|
||||
|
||||
/*
|
||||
* External user API
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user