@@ -246,22 +246,6 @@ static struct ice_vsi *ice_vf_vsi_setup(struct ice_vf *vf)
246
246
return vsi ;
247
247
}
248
248
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
- }
265
249
266
250
/**
267
251
* 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)
528
512
return 0 ;
529
513
}
530
514
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
+
531
561
/**
532
562
* ice_init_vf_vsi_res - initialize/setup VF VSI resources
533
563
* @vf: VF to initialize/setup the VSI for
@@ -541,7 +571,9 @@ static int ice_init_vf_vsi_res(struct ice_vf *vf)
541
571
struct ice_vsi * vsi ;
542
572
int err ;
543
573
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 ;
545
577
546
578
vsi = ice_vf_vsi_setup (vf );
547
579
if (!vsi )
@@ -1000,6 +1032,52 @@ u32 ice_sriov_get_vf_total_msix(struct pci_dev *pdev)
1000
1032
return pf -> sriov_irq_size - ice_get_max_used_msix_vector (pf );
1001
1033
}
1002
1034
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
+
1003
1081
/**
1004
1082
* ice_sriov_set_msix_vec_count
1005
1083
* @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)
1018
1096
{
1019
1097
struct pci_dev * pdev = pci_physfn (vf_dev );
1020
1098
struct ice_pf * pf = pci_get_drvdata (pdev );
1099
+ u16 prev_msix , prev_queues , queues ;
1100
+ bool needs_rebuild = false;
1021
1101
struct ice_vf * vf ;
1022
- u16 queues ;
1023
1102
int id ;
1024
1103
1025
1104
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)
1032
1111
/* add 1 MSI-X for OICR */
1033
1112
msix_vec_count += 1 ;
1034
1113
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
+
1035
1121
/* Transition of PCI VF function number to function_id */
1036
1122
for (id = 0 ; id < pci_num_vf (pdev ); id ++ ) {
1037
1123
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)
1046
1132
if (!vf )
1047
1133
return - ENOENT ;
1048
1134
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
+
1049
1143
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
+
1050
1149
vf -> num_msix = msix_vec_count ;
1051
1150
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
+
1053
1166
ice_ena_vf_mappings (vf );
1054
1167
ice_put_vf (vf );
1055
1168
1056
1169
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 ;
1057
1189
}
1058
1190
1059
1191
/**
0 commit comments