Skip to content

Commit 4d38cb4

Browse files
Michal Swiatkowskidavem330
authored andcommitted
ice: manage VFs MSI-X using resource tracking
Track MSI-X for VFs using bitmap, by setting and clearing bitmap during allocation and freeing. Try to linearize irqs usage for VFs, by freeing them and allocating once again. Do it only for VFs that aren't currently running. Signed-off-by: Michal Swiatkowski <[email protected]> Reviewed-by: Przemek Kitszel <[email protected]> Tested-by: Rafal Romanowski <[email protected]> Signed-off-by: Jacob Keller <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 05c1668 commit 4d38cb4

File tree

1 file changed

+151
-19
lines changed

1 file changed

+151
-19
lines changed

drivers/net/ethernet/intel/ice/ice_sriov.c

Lines changed: 151 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -246,22 +246,6 @@ static struct ice_vsi *ice_vf_vsi_setup(struct ice_vf *vf)
246246
return vsi;
247247
}
248248

249-
/**
250-
* ice_calc_vf_first_vector_idx - Calculate MSIX vector index in the PF space
251-
* @pf: pointer to PF structure
252-
* @vf: pointer to VF that the first MSIX vector index is being calculated for
253-
*
254-
* This returns the first MSIX vector index in PF space that is used by this VF.
255-
* This index is used when accessing PF relative registers such as
256-
* GLINT_VECT2FUNC and GLINT_DYN_CTL.
257-
* This will always be the OICR index in the AVF driver so any functionality
258-
* using vf->first_vector_idx for queue configuration will have to increment by
259-
* 1 to avoid meddling with the OICR index.
260-
*/
261-
static int ice_calc_vf_first_vector_idx(struct ice_pf *pf, struct ice_vf *vf)
262-
{
263-
return pf->sriov_base_vector + vf->vf_id * pf->vfs.num_msix_per;
264-
}
265249

266250
/**
267251
* ice_ena_vf_msix_mappings - enable VF MSIX mappings in hardware
@@ -528,6 +512,52 @@ static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs)
528512
return 0;
529513
}
530514

515+
/**
516+
* ice_sriov_get_irqs - get irqs for SR-IOV usacase
517+
* @pf: pointer to PF structure
518+
* @needed: number of irqs to get
519+
*
520+
* This returns the first MSI-X vector index in PF space that is used by this
521+
* VF. This index is used when accessing PF relative registers such as
522+
* GLINT_VECT2FUNC and GLINT_DYN_CTL.
523+
* This will always be the OICR index in the AVF driver so any functionality
524+
* using vf->first_vector_idx for queue configuration_id: id of VF which will
525+
* use this irqs
526+
*
527+
* Only SRIOV specific vectors are tracked in sriov_irq_bm. SRIOV vectors are
528+
* allocated from the end of global irq index. First bit in sriov_irq_bm means
529+
* last irq index etc. It simplifies extension of SRIOV vectors.
530+
* They will be always located from sriov_base_vector to the last irq
531+
* index. While increasing/decreasing sriov_base_vector can be moved.
532+
*/
533+
static int ice_sriov_get_irqs(struct ice_pf *pf, u16 needed)
534+
{
535+
int res = bitmap_find_next_zero_area(pf->sriov_irq_bm,
536+
pf->sriov_irq_size, 0, needed, 0);
537+
/* conversion from number in bitmap to global irq index */
538+
int index = pf->sriov_irq_size - res - needed;
539+
540+
if (res >= pf->sriov_irq_size || index < pf->sriov_base_vector)
541+
return -ENOENT;
542+
543+
bitmap_set(pf->sriov_irq_bm, res, needed);
544+
return index;
545+
}
546+
547+
/**
548+
* ice_sriov_free_irqs - free irqs used by the VF
549+
* @pf: pointer to PF structure
550+
* @vf: pointer to VF structure
551+
*/
552+
static void ice_sriov_free_irqs(struct ice_pf *pf, struct ice_vf *vf)
553+
{
554+
/* Move back from first vector index to first index in bitmap */
555+
int bm_i = pf->sriov_irq_size - vf->first_vector_idx - vf->num_msix;
556+
557+
bitmap_clear(pf->sriov_irq_bm, bm_i, vf->num_msix);
558+
vf->first_vector_idx = 0;
559+
}
560+
531561
/**
532562
* ice_init_vf_vsi_res - initialize/setup VF VSI resources
533563
* @vf: VF to initialize/setup the VSI for
@@ -541,7 +571,9 @@ static int ice_init_vf_vsi_res(struct ice_vf *vf)
541571
struct ice_vsi *vsi;
542572
int err;
543573

544-
vf->first_vector_idx = ice_calc_vf_first_vector_idx(pf, vf);
574+
vf->first_vector_idx = ice_sriov_get_irqs(pf, vf->num_msix);
575+
if (vf->first_vector_idx < 0)
576+
return -ENOMEM;
545577

546578
vsi = ice_vf_vsi_setup(vf);
547579
if (!vsi)
@@ -1000,6 +1032,52 @@ u32 ice_sriov_get_vf_total_msix(struct pci_dev *pdev)
10001032
return pf->sriov_irq_size - ice_get_max_used_msix_vector(pf);
10011033
}
10021034

1035+
static int ice_sriov_move_base_vector(struct ice_pf *pf, int move)
1036+
{
1037+
if (pf->sriov_base_vector - move < ice_get_max_used_msix_vector(pf))
1038+
return -ENOMEM;
1039+
1040+
pf->sriov_base_vector -= move;
1041+
return 0;
1042+
}
1043+
1044+
static void ice_sriov_remap_vectors(struct ice_pf *pf, u16 restricted_id)
1045+
{
1046+
u16 vf_ids[ICE_MAX_SRIOV_VFS];
1047+
struct ice_vf *tmp_vf;
1048+
int to_remap = 0, bkt;
1049+
1050+
/* For better irqs usage try to remap irqs of VFs
1051+
* that aren't running yet
1052+
*/
1053+
ice_for_each_vf(pf, bkt, tmp_vf) {
1054+
/* skip VF which is changing the number of MSI-X */
1055+
if (restricted_id == tmp_vf->vf_id ||
1056+
test_bit(ICE_VF_STATE_ACTIVE, tmp_vf->vf_states))
1057+
continue;
1058+
1059+
ice_dis_vf_mappings(tmp_vf);
1060+
ice_sriov_free_irqs(pf, tmp_vf);
1061+
1062+
vf_ids[to_remap] = tmp_vf->vf_id;
1063+
to_remap += 1;
1064+
}
1065+
1066+
for (int i = 0; i < to_remap; i++) {
1067+
tmp_vf = ice_get_vf_by_id(pf, vf_ids[i]);
1068+
if (!tmp_vf)
1069+
continue;
1070+
1071+
tmp_vf->first_vector_idx =
1072+
ice_sriov_get_irqs(pf, tmp_vf->num_msix);
1073+
/* there is no need to rebuild VSI as we are only changing the
1074+
* vector indexes not amount of MSI-X or queues
1075+
*/
1076+
ice_ena_vf_mappings(tmp_vf);
1077+
ice_put_vf(tmp_vf);
1078+
}
1079+
}
1080+
10031081
/**
10041082
* ice_sriov_set_msix_vec_count
10051083
* @vf_dev: pointer to pci_dev struct of VF device
@@ -1018,8 +1096,9 @@ int ice_sriov_set_msix_vec_count(struct pci_dev *vf_dev, int msix_vec_count)
10181096
{
10191097
struct pci_dev *pdev = pci_physfn(vf_dev);
10201098
struct ice_pf *pf = pci_get_drvdata(pdev);
1099+
u16 prev_msix, prev_queues, queues;
1100+
bool needs_rebuild = false;
10211101
struct ice_vf *vf;
1022-
u16 queues;
10231102
int id;
10241103

10251104
if (!ice_get_num_vfs(pf))
@@ -1032,6 +1111,13 @@ int ice_sriov_set_msix_vec_count(struct pci_dev *vf_dev, int msix_vec_count)
10321111
/* add 1 MSI-X for OICR */
10331112
msix_vec_count += 1;
10341113

1114+
if (queues > min(ice_get_avail_txq_count(pf),
1115+
ice_get_avail_rxq_count(pf)))
1116+
return -EINVAL;
1117+
1118+
if (msix_vec_count < ICE_MIN_INTR_PER_VF)
1119+
return -EINVAL;
1120+
10351121
/* Transition of PCI VF function number to function_id */
10361122
for (id = 0; id < pci_num_vf(pdev); id++) {
10371123
if (vf_dev->devfn == pci_iov_virtfn_devfn(pdev, id))
@@ -1046,14 +1132,60 @@ int ice_sriov_set_msix_vec_count(struct pci_dev *vf_dev, int msix_vec_count)
10461132
if (!vf)
10471133
return -ENOENT;
10481134

1135+
prev_msix = vf->num_msix;
1136+
prev_queues = vf->num_vf_qs;
1137+
1138+
if (ice_sriov_move_base_vector(pf, msix_vec_count - prev_msix)) {
1139+
ice_put_vf(vf);
1140+
return -ENOSPC;
1141+
}
1142+
10491143
ice_dis_vf_mappings(vf);
1144+
ice_sriov_free_irqs(pf, vf);
1145+
1146+
/* Remap all VFs beside the one is now configured */
1147+
ice_sriov_remap_vectors(pf, vf->vf_id);
1148+
10501149
vf->num_msix = msix_vec_count;
10511150
vf->num_vf_qs = queues;
1052-
ice_vsi_rebuild(ice_get_vf_vsi(vf), ICE_VSI_FLAG_NO_INIT);
1151+
vf->first_vector_idx = ice_sriov_get_irqs(pf, vf->num_msix);
1152+
if (vf->first_vector_idx < 0)
1153+
goto unroll;
1154+
1155+
ice_vf_vsi_release(vf);
1156+
if (vf->vf_ops->create_vsi(vf)) {
1157+
/* Try to rebuild with previous values */
1158+
needs_rebuild = true;
1159+
goto unroll;
1160+
}
1161+
1162+
dev_info(ice_pf_to_dev(pf),
1163+
"Changing VF %d resources to %d vectors and %d queues\n",
1164+
vf->vf_id, vf->num_msix, vf->num_vf_qs);
1165+
10531166
ice_ena_vf_mappings(vf);
10541167
ice_put_vf(vf);
10551168

10561169
return 0;
1170+
1171+
unroll:
1172+
dev_info(ice_pf_to_dev(pf),
1173+
"Can't set %d vectors on VF %d, falling back to %d\n",
1174+
vf->num_msix, vf->vf_id, prev_msix);
1175+
1176+
vf->num_msix = prev_msix;
1177+
vf->num_vf_qs = prev_queues;
1178+
vf->first_vector_idx = ice_sriov_get_irqs(pf, vf->num_msix);
1179+
if (vf->first_vector_idx < 0)
1180+
return -EINVAL;
1181+
1182+
if (needs_rebuild)
1183+
vf->vf_ops->create_vsi(vf);
1184+
1185+
ice_ena_vf_mappings(vf);
1186+
ice_put_vf(vf);
1187+
1188+
return -EINVAL;
10571189
}
10581190

10591191
/**

0 commit comments

Comments
 (0)