13
13
#include <linux/kernel.h>
14
14
#include <linux/slab.h>
15
15
#include <linux/uuid.h>
16
+ #include <linux/group_cpus.h>
16
17
#include <linux/virtio.h>
17
18
#include <linux/vdpa.h>
18
19
#include <linux/virtio_config.h>
@@ -272,6 +273,66 @@ static void virtio_vdpa_del_vqs(struct virtio_device *vdev)
272
273
virtio_vdpa_del_vq (vq );
273
274
}
274
275
276
+ static void default_calc_sets (struct irq_affinity * affd , unsigned int affvecs )
277
+ {
278
+ affd -> nr_sets = 1 ;
279
+ affd -> set_size [0 ] = affvecs ;
280
+ }
281
+
282
+ static struct cpumask *
283
+ create_affinity_masks (unsigned int nvecs , struct irq_affinity * affd )
284
+ {
285
+ unsigned int affvecs = 0 , curvec , usedvecs , i ;
286
+ struct cpumask * masks = NULL ;
287
+
288
+ if (nvecs > affd -> pre_vectors + affd -> post_vectors )
289
+ affvecs = nvecs - affd -> pre_vectors - affd -> post_vectors ;
290
+
291
+ if (!affd -> calc_sets )
292
+ affd -> calc_sets = default_calc_sets ;
293
+
294
+ affd -> calc_sets (affd , affvecs );
295
+
296
+ if (!affvecs )
297
+ return NULL ;
298
+
299
+ masks = kcalloc (nvecs , sizeof (* masks ), GFP_KERNEL );
300
+ if (!masks )
301
+ return NULL ;
302
+
303
+ /* Fill out vectors at the beginning that don't need affinity */
304
+ for (curvec = 0 ; curvec < affd -> pre_vectors ; curvec ++ )
305
+ cpumask_setall (& masks [curvec ]);
306
+
307
+ for (i = 0 , usedvecs = 0 ; i < affd -> nr_sets ; i ++ ) {
308
+ unsigned int this_vecs = affd -> set_size [i ];
309
+ int j ;
310
+ struct cpumask * result = group_cpus_evenly (this_vecs );
311
+
312
+ if (!result ) {
313
+ kfree (masks );
314
+ return NULL ;
315
+ }
316
+
317
+ for (j = 0 ; j < this_vecs ; j ++ )
318
+ cpumask_copy (& masks [curvec + j ], & result [j ]);
319
+ kfree (result );
320
+
321
+ curvec += this_vecs ;
322
+ usedvecs += this_vecs ;
323
+ }
324
+
325
+ /* Fill out vectors at the end that don't need affinity */
326
+ if (usedvecs >= affvecs )
327
+ curvec = affd -> pre_vectors + affvecs ;
328
+ else
329
+ curvec = affd -> pre_vectors + usedvecs ;
330
+ for (; curvec < nvecs ; curvec ++ )
331
+ cpumask_setall (& masks [curvec ]);
332
+
333
+ return masks ;
334
+ }
335
+
275
336
static int virtio_vdpa_find_vqs (struct virtio_device * vdev , unsigned int nvqs ,
276
337
struct virtqueue * vqs [],
277
338
vq_callback_t * callbacks [],
@@ -282,9 +343,15 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
282
343
struct virtio_vdpa_device * vd_dev = to_virtio_vdpa_device (vdev );
283
344
struct vdpa_device * vdpa = vd_get_vdpa (vdev );
284
345
const struct vdpa_config_ops * ops = vdpa -> config ;
346
+ struct irq_affinity default_affd = { 0 };
347
+ struct cpumask * masks ;
285
348
struct vdpa_callback cb ;
286
349
int i , err , queue_idx = 0 ;
287
350
351
+ masks = create_affinity_masks (nvqs , desc ? desc : & default_affd );
352
+ if (!masks )
353
+ return - ENOMEM ;
354
+
288
355
for (i = 0 ; i < nvqs ; ++ i ) {
289
356
if (!names [i ]) {
290
357
vqs [i ] = NULL ;
@@ -298,6 +365,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
298
365
err = PTR_ERR (vqs [i ]);
299
366
goto err_setup_vq ;
300
367
}
368
+ ops -> set_vq_affinity (vdpa , i , & masks [i ]);
301
369
}
302
370
303
371
cb .callback = virtio_vdpa_config_cb ;
0 commit comments