Skip to content

Commit 69b9461

Browse files
author
Paolo Abeni
committed
virtio_pci_modern: allow configuring extended features
The virtio specifications allows for up to 128 bits for the device features. Soon we are going to use some of the 'extended' bits features (above 64) for the virtio_net driver. Extend the virtio pci modern driver to support configuring the full virtio features range, replacing the unrolled loops reading and writing the features space with explicit one bounded to the actual features space size in word and implementing the get_extended_features callback. Note that in vp_finalize_features() we only need to cache the lower 64 features bits, to process the transport features. Acked-by: Jason Wang <jasowang@redhat.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent e7d4c1c commit 69b9461

File tree

3 files changed

+84
-38
lines changed

3 files changed

+84
-38
lines changed

drivers/virtio/virtio_pci_modern.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222

2323
#define VIRTIO_AVQ_SGS_MAX 4
2424

25-
static u64 vp_get_features(struct virtio_device *vdev)
25+
static void vp_get_features(struct virtio_device *vdev, u64 *features)
2626
{
2727
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
2828

29-
return vp_modern_get_features(&vp_dev->mdev);
29+
vp_modern_get_extended_features(&vp_dev->mdev, features);
3030
}
3131

3232
static int vp_avq_index(struct virtio_device *vdev, u16 *index, u16 *num)
@@ -437,7 +437,7 @@ static int vp_finalize_features(struct virtio_device *vdev)
437437
if (vp_check_common_size(vdev))
438438
return -EINVAL;
439439

440-
vp_modern_set_features(&vp_dev->mdev, vdev->features);
440+
vp_modern_set_extended_features(&vp_dev->mdev, vdev->features_array);
441441

442442
return 0;
443443
}
@@ -1234,7 +1234,7 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
12341234
.find_vqs = vp_modern_find_vqs,
12351235
.del_vqs = vp_del_vqs,
12361236
.synchronize_cbs = vp_synchronize_vectors,
1237-
.get_features = vp_get_features,
1237+
.get_extended_features = vp_get_features,
12381238
.finalize_features = vp_finalize_features,
12391239
.bus_name = vp_bus_name,
12401240
.set_vq_affinity = vp_set_vq_affinity,
@@ -1254,7 +1254,7 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
12541254
.find_vqs = vp_modern_find_vqs,
12551255
.del_vqs = vp_del_vqs,
12561256
.synchronize_cbs = vp_synchronize_vectors,
1257-
.get_features = vp_get_features,
1257+
.get_extended_features = vp_get_features,
12581258
.finalize_features = vp_finalize_features,
12591259
.bus_name = vp_bus_name,
12601260
.set_vq_affinity = vp_set_vq_affinity,

drivers/virtio/virtio_pci_modern_dev.c

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -388,63 +388,74 @@ void vp_modern_remove(struct virtio_pci_modern_device *mdev)
388388
EXPORT_SYMBOL_GPL(vp_modern_remove);
389389

390390
/*
391-
* vp_modern_get_features - get features from device
391+
* vp_modern_get_extended_features - get features from device
392392
* @mdev: the modern virtio-pci device
393+
* @features: the features array to be filled
393394
*
394-
* Returns the features read from the device
395+
* Fill the specified features array with the features read from the device
395396
*/
396-
u64 vp_modern_get_features(struct virtio_pci_modern_device *mdev)
397+
void vp_modern_get_extended_features(struct virtio_pci_modern_device *mdev,
398+
u64 *features)
397399
{
398400
struct virtio_pci_common_cfg __iomem *cfg = mdev->common;
401+
int i;
399402

400-
u64 features;
403+
virtio_features_zero(features);
404+
for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) {
405+
u64 cur;
401406

402-
vp_iowrite32(0, &cfg->device_feature_select);
403-
features = vp_ioread32(&cfg->device_feature);
404-
vp_iowrite32(1, &cfg->device_feature_select);
405-
features |= ((u64)vp_ioread32(&cfg->device_feature) << 32);
406-
407-
return features;
407+
vp_iowrite32(i, &cfg->device_feature_select);
408+
cur = vp_ioread32(&cfg->device_feature);
409+
features[i >> 1] |= cur << (32 * (i & 1));
410+
}
408411
}
409-
EXPORT_SYMBOL_GPL(vp_modern_get_features);
412+
EXPORT_SYMBOL_GPL(vp_modern_get_extended_features);
410413

411414
/*
412415
* vp_modern_get_driver_features - get driver features from device
413416
* @mdev: the modern virtio-pci device
417+
* @features: the features array to be filled
414418
*
415-
* Returns the driver features read from the device
419+
* Fill the specified features array with the driver features read from the
420+
* device
416421
*/
417-
u64 vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev)
422+
void
423+
vp_modern_get_driver_extended_features(struct virtio_pci_modern_device *mdev,
424+
u64 *features)
418425
{
419426
struct virtio_pci_common_cfg __iomem *cfg = mdev->common;
427+
int i;
420428

421-
u64 features;
422-
423-
vp_iowrite32(0, &cfg->guest_feature_select);
424-
features = vp_ioread32(&cfg->guest_feature);
425-
vp_iowrite32(1, &cfg->guest_feature_select);
426-
features |= ((u64)vp_ioread32(&cfg->guest_feature) << 32);
429+
virtio_features_zero(features);
430+
for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) {
431+
u64 cur;
427432

428-
return features;
433+
vp_iowrite32(i, &cfg->guest_feature_select);
434+
cur = vp_ioread32(&cfg->guest_feature);
435+
features[i >> 1] |= cur << (32 * (i & 1));
436+
}
429437
}
430-
EXPORT_SYMBOL_GPL(vp_modern_get_driver_features);
438+
EXPORT_SYMBOL_GPL(vp_modern_get_driver_extended_features);
431439

432440
/*
433-
* vp_modern_set_features - set features to device
441+
* vp_modern_set_extended_features - set features to device
434442
* @mdev: the modern virtio-pci device
435443
* @features: the features set to device
436444
*/
437-
void vp_modern_set_features(struct virtio_pci_modern_device *mdev,
438-
u64 features)
445+
void vp_modern_set_extended_features(struct virtio_pci_modern_device *mdev,
446+
const u64 *features)
439447
{
440448
struct virtio_pci_common_cfg __iomem *cfg = mdev->common;
449+
int i;
450+
451+
for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) {
452+
u32 cur = features[i >> 1] >> (32 * (i & 1));
441453

442-
vp_iowrite32(0, &cfg->guest_feature_select);
443-
vp_iowrite32((u32)features, &cfg->guest_feature);
444-
vp_iowrite32(1, &cfg->guest_feature_select);
445-
vp_iowrite32(features >> 32, &cfg->guest_feature);
454+
vp_iowrite32(i, &cfg->guest_feature_select);
455+
vp_iowrite32(cur, &cfg->guest_feature);
456+
}
446457
}
447-
EXPORT_SYMBOL_GPL(vp_modern_set_features);
458+
EXPORT_SYMBOL_GPL(vp_modern_set_extended_features);
448459

449460
/*
450461
* vp_modern_generation - get the device genreation

include/linux/virtio_pci_modern.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#define _LINUX_VIRTIO_PCI_MODERN_H
44

55
#include <linux/pci.h>
6+
#include <linux/virtio_config.h>
67
#include <linux/virtio_pci.h>
78

89
/**
@@ -95,10 +96,44 @@ static inline void vp_iowrite64_twopart(u64 val,
9596
vp_iowrite32(val >> 32, hi);
9697
}
9798

98-
u64 vp_modern_get_features(struct virtio_pci_modern_device *mdev);
99-
u64 vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev);
100-
void vp_modern_set_features(struct virtio_pci_modern_device *mdev,
101-
u64 features);
99+
void
100+
vp_modern_get_driver_extended_features(struct virtio_pci_modern_device *mdev,
101+
u64 *features);
102+
void vp_modern_get_extended_features(struct virtio_pci_modern_device *mdev,
103+
u64 *features);
104+
void vp_modern_set_extended_features(struct virtio_pci_modern_device *mdev,
105+
const u64 *features);
106+
107+
static inline u64
108+
vp_modern_get_features(struct virtio_pci_modern_device *mdev)
109+
{
110+
u64 features_array[VIRTIO_FEATURES_DWORDS];
111+
112+
vp_modern_get_extended_features(mdev, features_array);
113+
return features_array[0];
114+
}
115+
116+
static inline u64
117+
vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev)
118+
{
119+
u64 features_array[VIRTIO_FEATURES_DWORDS];
120+
int i;
121+
122+
vp_modern_get_driver_extended_features(mdev, features_array);
123+
for (i = 1; i < VIRTIO_FEATURES_DWORDS; ++i)
124+
WARN_ON_ONCE(features_array[i]);
125+
return features_array[0];
126+
}
127+
128+
static inline void
129+
vp_modern_set_features(struct virtio_pci_modern_device *mdev, u64 features)
130+
{
131+
u64 features_array[VIRTIO_FEATURES_DWORDS];
132+
133+
virtio_features_from_u64(features_array, features);
134+
vp_modern_set_extended_features(mdev, features_array);
135+
}
136+
102137
u32 vp_modern_generation(struct virtio_pci_modern_device *mdev);
103138
u8 vp_modern_get_status(struct virtio_pci_modern_device *mdev);
104139
void vp_modern_set_status(struct virtio_pci_modern_device *mdev,

0 commit comments

Comments
 (0)