Skip to content

Commit 3dad568

Browse files
YongjiXiemstsirkin
authored andcommitted
virtio-vdpa: Support interrupt affinity spreading mechanism
To support interrupt affinity spreading mechanism, this makes use of group_cpus_evenly() to create an irq callback affinity mask for each virtqueue of vdpa device. Then we will unify set_vq_affinity callback to pass the affinity to the vdpa device driver. Signed-off-by: Xie Yongji <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]> Acked-by: Jason Wang <[email protected]>
1 parent 1d24692 commit 3dad568

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

drivers/virtio/virtio_vdpa.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/kernel.h>
1414
#include <linux/slab.h>
1515
#include <linux/uuid.h>
16+
#include <linux/group_cpus.h>
1617
#include <linux/virtio.h>
1718
#include <linux/vdpa.h>
1819
#include <linux/virtio_config.h>
@@ -272,6 +273,66 @@ static void virtio_vdpa_del_vqs(struct virtio_device *vdev)
272273
virtio_vdpa_del_vq(vq);
273274
}
274275

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+
275336
static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
276337
struct virtqueue *vqs[],
277338
vq_callback_t *callbacks[],
@@ -282,9 +343,15 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
282343
struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
283344
struct vdpa_device *vdpa = vd_get_vdpa(vdev);
284345
const struct vdpa_config_ops *ops = vdpa->config;
346+
struct irq_affinity default_affd = { 0 };
347+
struct cpumask *masks;
285348
struct vdpa_callback cb;
286349
int i, err, queue_idx = 0;
287350

351+
masks = create_affinity_masks(nvqs, desc ? desc : &default_affd);
352+
if (!masks)
353+
return -ENOMEM;
354+
288355
for (i = 0; i < nvqs; ++i) {
289356
if (!names[i]) {
290357
vqs[i] = NULL;
@@ -298,6 +365,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
298365
err = PTR_ERR(vqs[i]);
299366
goto err_setup_vq;
300367
}
368+
ops->set_vq_affinity(vdpa, i, &masks[i]);
301369
}
302370

303371
cb.callback = virtio_vdpa_config_cb;

0 commit comments

Comments
 (0)