Skip to content

Commit

Permalink
vfio: Commonize combine_ranges for use in other VFIO drivers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Brett Creeley authored and Alex Williamson committed Aug 16, 2023
1 parent 73e2f19 commit 9a4087f
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 47 deletions.
48 changes: 1 addition & 47 deletions drivers/vfio/pci/mlx5/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}

Expand Down
47 changes: 47 additions & 0 deletions drivers/vfio/vfio_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
3 changes: 3 additions & 0 deletions include/linux/vfio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down

0 comments on commit 9a4087f

Please sign in to comment.