summaryrefslogtreecommitdiff
path: root/drivers/virtio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/virtio')
-rw-r--r--drivers/virtio/virtio.c43
-rw-r--r--drivers/virtio/virtio_debug.c27
-rw-r--r--drivers/virtio/virtio_pci_modern.c10
-rw-r--r--drivers/virtio/virtio_pci_modern_dev.c69
-rw-r--r--drivers/virtio/virtio_vdpa.c9
5 files changed, 91 insertions, 67 deletions
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 95d5d7993e5b..5c48788cdbec 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -53,7 +53,7 @@ static ssize_t features_show(struct device *_d,
/* We actually represent this as a bitstring, as it could be
* arbitrary length in future. */
- for (i = 0; i < sizeof(dev->features)*8; i++)
+ for (i = 0; i < VIRTIO_FEATURES_MAX; i++)
len += sysfs_emit_at(buf, len, "%c",
__virtio_test_bit(dev, i) ? '1' : '0');
len += sysfs_emit_at(buf, len, "\n");
@@ -272,22 +272,22 @@ static int virtio_dev_probe(struct device *_d)
int err, i;
struct virtio_device *dev = dev_to_virtio(_d);
struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
- u64 device_features;
- u64 driver_features;
+ u64 device_features[VIRTIO_FEATURES_DWORDS];
+ u64 driver_features[VIRTIO_FEATURES_DWORDS];
u64 driver_features_legacy;
/* We have a driver! */
virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
/* Figure out what features the device supports. */
- device_features = dev->config->get_features(dev);
+ virtio_get_features(dev, device_features);
/* Figure out what features the driver supports. */
- driver_features = 0;
+ virtio_features_zero(driver_features);
for (i = 0; i < drv->feature_table_size; i++) {
unsigned int f = drv->feature_table[i];
- BUG_ON(f >= 64);
- driver_features |= (1ULL << f);
+ if (!WARN_ON_ONCE(f >= VIRTIO_FEATURES_MAX))
+ virtio_features_set_bit(driver_features, f);
}
/* Some drivers have a separate feature table for virtio v1.0 */
@@ -295,24 +295,29 @@ static int virtio_dev_probe(struct device *_d)
driver_features_legacy = 0;
for (i = 0; i < drv->feature_table_size_legacy; i++) {
unsigned int f = drv->feature_table_legacy[i];
- BUG_ON(f >= 64);
- driver_features_legacy |= (1ULL << f);
+ if (!WARN_ON_ONCE(f >= 64))
+ driver_features_legacy |= (1ULL << f);
}
} else {
- driver_features_legacy = driver_features;
+ driver_features_legacy = driver_features[0];
}
- if (device_features & (1ULL << VIRTIO_F_VERSION_1))
- dev->features = driver_features & device_features;
- else
- dev->features = driver_features_legacy & device_features;
+ if (virtio_features_test_bit(device_features, VIRTIO_F_VERSION_1)) {
+ for (i = 0; i < VIRTIO_FEATURES_DWORDS; ++i)
+ dev->features_array[i] = driver_features[i] &
+ device_features[i];
+ } else {
+ virtio_features_from_u64(dev->features_array,
+ driver_features_legacy &
+ device_features[0]);
+ }
/* When debugging, user may filter some features by hand. */
virtio_debug_device_filter_features(dev);
/* Transport features always preserved to pass to finalize_features. */
for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)
- if (device_features & (1ULL << i))
+ if (virtio_features_test_bit(device_features, i))
__virtio_set_bit(dev, i);
err = dev->config->finalize_features(dev);
@@ -320,14 +325,15 @@ static int virtio_dev_probe(struct device *_d)
goto err;
if (drv->validate) {
- u64 features = dev->features;
+ u64 features[VIRTIO_FEATURES_DWORDS];
+ virtio_features_copy(features, dev->features_array);
err = drv->validate(dev);
if (err)
goto err;
/* Did validation change any features? Then write them again. */
- if (features != dev->features) {
+ if (!virtio_features_equal(features, dev->features_array)) {
err = dev->config->finalize_features(dev);
if (err)
goto err;
@@ -701,6 +707,9 @@ EXPORT_SYMBOL_GPL(virtio_device_reset_done);
static int virtio_init(void)
{
+ BUILD_BUG_ON(offsetof(struct virtio_device, features) !=
+ offsetof(struct virtio_device, features_array[0]));
+
if (bus_register(&virtio_bus) != 0)
panic("virtio bus registration failed");
virtio_debug_init();
diff --git a/drivers/virtio/virtio_debug.c b/drivers/virtio/virtio_debug.c
index 95c8fc7705bb..d58713ddf2e5 100644
--- a/drivers/virtio/virtio_debug.c
+++ b/drivers/virtio/virtio_debug.c
@@ -8,13 +8,13 @@ static struct dentry *virtio_debugfs_dir;
static int virtio_debug_device_features_show(struct seq_file *s, void *data)
{
+ u64 device_features[VIRTIO_FEATURES_DWORDS];
struct virtio_device *dev = s->private;
- u64 device_features;
unsigned int i;
- device_features = dev->config->get_features(dev);
- for (i = 0; i < BITS_PER_LONG_LONG; i++) {
- if (device_features & (1ULL << i))
+ virtio_get_features(dev, device_features);
+ for (i = 0; i < VIRTIO_FEATURES_MAX; i++) {
+ if (virtio_features_test_bit(device_features, i))
seq_printf(s, "%u\n", i);
}
return 0;
@@ -26,8 +26,8 @@ static int virtio_debug_filter_features_show(struct seq_file *s, void *data)
struct virtio_device *dev = s->private;
unsigned int i;
- for (i = 0; i < BITS_PER_LONG_LONG; i++) {
- if (dev->debugfs_filter_features & (1ULL << i))
+ for (i = 0; i < VIRTIO_FEATURES_MAX; i++) {
+ if (virtio_features_test_bit(dev->debugfs_filter_features, i))
seq_printf(s, "%u\n", i);
}
return 0;
@@ -39,7 +39,7 @@ static int virtio_debug_filter_features_clear(void *data, u64 val)
struct virtio_device *dev = data;
if (val == 1)
- dev->debugfs_filter_features = 0;
+ virtio_features_zero(dev->debugfs_filter_features);
return 0;
}
@@ -50,9 +50,10 @@ static int virtio_debug_filter_feature_add(void *data, u64 val)
{
struct virtio_device *dev = data;
- if (val >= BITS_PER_LONG_LONG)
+ if (val >= VIRTIO_FEATURES_MAX)
return -EINVAL;
- dev->debugfs_filter_features |= BIT_ULL_MASK(val);
+
+ virtio_features_set_bit(dev->debugfs_filter_features, val);
return 0;
}
@@ -63,9 +64,10 @@ static int virtio_debug_filter_feature_del(void *data, u64 val)
{
struct virtio_device *dev = data;
- if (val >= BITS_PER_LONG_LONG)
+ if (val >= VIRTIO_FEATURES_MAX)
return -EINVAL;
- dev->debugfs_filter_features &= ~BIT_ULL_MASK(val);
+
+ virtio_features_clear_bit(dev->debugfs_filter_features, val);
return 0;
}
@@ -91,7 +93,8 @@ EXPORT_SYMBOL_GPL(virtio_debug_device_init);
void virtio_debug_device_filter_features(struct virtio_device *dev)
{
- dev->features &= ~dev->debugfs_filter_features;
+ virtio_features_andnot(dev->features_array, dev->features_array,
+ dev->debugfs_filter_features);
}
EXPORT_SYMBOL_GPL(virtio_debug_device_filter_features);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 7182f43ed055..dd0e65f71d41 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -22,11 +22,11 @@
#define VIRTIO_AVQ_SGS_MAX 4
-static u64 vp_get_features(struct virtio_device *vdev)
+static void vp_get_features(struct virtio_device *vdev, u64 *features)
{
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
- return vp_modern_get_features(&vp_dev->mdev);
+ vp_modern_get_extended_features(&vp_dev->mdev, features);
}
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)
if (vp_check_common_size(vdev))
return -EINVAL;
- vp_modern_set_features(&vp_dev->mdev, vdev->features);
+ vp_modern_set_extended_features(&vp_dev->mdev, vdev->features_array);
return 0;
}
@@ -1234,7 +1234,7 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
.find_vqs = vp_modern_find_vqs,
.del_vqs = vp_del_vqs,
.synchronize_cbs = vp_synchronize_vectors,
- .get_features = vp_get_features,
+ .get_extended_features = vp_get_features,
.finalize_features = vp_finalize_features,
.bus_name = vp_bus_name,
.set_vq_affinity = vp_set_vq_affinity,
@@ -1254,7 +1254,7 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
.find_vqs = vp_modern_find_vqs,
.del_vqs = vp_del_vqs,
.synchronize_cbs = vp_synchronize_vectors,
- .get_features = vp_get_features,
+ .get_extended_features = vp_get_features,
.finalize_features = vp_finalize_features,
.bus_name = vp_bus_name,
.set_vq_affinity = vp_set_vq_affinity,
diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c
index 0d3dbfaf4b23..d665f8f73ea8 100644
--- a/drivers/virtio/virtio_pci_modern_dev.c
+++ b/drivers/virtio/virtio_pci_modern_dev.c
@@ -388,63 +388,74 @@ void vp_modern_remove(struct virtio_pci_modern_device *mdev)
EXPORT_SYMBOL_GPL(vp_modern_remove);
/*
- * vp_modern_get_features - get features from device
+ * vp_modern_get_extended_features - get features from device
* @mdev: the modern virtio-pci device
+ * @features: the features array to be filled
*
- * Returns the features read from the device
+ * Fill the specified features array with the features read from the device
*/
-u64 vp_modern_get_features(struct virtio_pci_modern_device *mdev)
+void vp_modern_get_extended_features(struct virtio_pci_modern_device *mdev,
+ u64 *features)
{
struct virtio_pci_common_cfg __iomem *cfg = mdev->common;
+ int i;
- u64 features;
+ virtio_features_zero(features);
+ for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) {
+ u64 cur;
- vp_iowrite32(0, &cfg->device_feature_select);
- features = vp_ioread32(&cfg->device_feature);
- vp_iowrite32(1, &cfg->device_feature_select);
- features |= ((u64)vp_ioread32(&cfg->device_feature) << 32);
-
- return features;
+ vp_iowrite32(i, &cfg->device_feature_select);
+ cur = vp_ioread32(&cfg->device_feature);
+ features[i >> 1] |= cur << (32 * (i & 1));
+ }
}
-EXPORT_SYMBOL_GPL(vp_modern_get_features);
+EXPORT_SYMBOL_GPL(vp_modern_get_extended_features);
/*
* vp_modern_get_driver_features - get driver features from device
* @mdev: the modern virtio-pci device
+ * @features: the features array to be filled
*
- * Returns the driver features read from the device
+ * Fill the specified features array with the driver features read from the
+ * device
*/
-u64 vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev)
+void
+vp_modern_get_driver_extended_features(struct virtio_pci_modern_device *mdev,
+ u64 *features)
{
struct virtio_pci_common_cfg __iomem *cfg = mdev->common;
+ int i;
- u64 features;
-
- vp_iowrite32(0, &cfg->guest_feature_select);
- features = vp_ioread32(&cfg->guest_feature);
- vp_iowrite32(1, &cfg->guest_feature_select);
- features |= ((u64)vp_ioread32(&cfg->guest_feature) << 32);
+ virtio_features_zero(features);
+ for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) {
+ u64 cur;
- return features;
+ vp_iowrite32(i, &cfg->guest_feature_select);
+ cur = vp_ioread32(&cfg->guest_feature);
+ features[i >> 1] |= cur << (32 * (i & 1));
+ }
}
-EXPORT_SYMBOL_GPL(vp_modern_get_driver_features);
+EXPORT_SYMBOL_GPL(vp_modern_get_driver_extended_features);
/*
- * vp_modern_set_features - set features to device
+ * vp_modern_set_extended_features - set features to device
* @mdev: the modern virtio-pci device
* @features: the features set to device
*/
-void vp_modern_set_features(struct virtio_pci_modern_device *mdev,
- u64 features)
+void vp_modern_set_extended_features(struct virtio_pci_modern_device *mdev,
+ const u64 *features)
{
struct virtio_pci_common_cfg __iomem *cfg = mdev->common;
+ int i;
+
+ for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) {
+ u32 cur = features[i >> 1] >> (32 * (i & 1));
- vp_iowrite32(0, &cfg->guest_feature_select);
- vp_iowrite32((u32)features, &cfg->guest_feature);
- vp_iowrite32(1, &cfg->guest_feature_select);
- vp_iowrite32(features >> 32, &cfg->guest_feature);
+ vp_iowrite32(i, &cfg->guest_feature_select);
+ vp_iowrite32(cur, &cfg->guest_feature);
+ }
}
-EXPORT_SYMBOL_GPL(vp_modern_set_features);
+EXPORT_SYMBOL_GPL(vp_modern_set_extended_features);
/*
* vp_modern_generation - get the device genreation
diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
index 1f60c9d5cb18..a7b297dae489 100644
--- a/drivers/virtio/virtio_vdpa.c
+++ b/drivers/virtio/virtio_vdpa.c
@@ -329,20 +329,21 @@ create_affinity_masks(unsigned int nvecs, struct irq_affinity *affd)
for (i = 0, usedvecs = 0; i < affd->nr_sets; i++) {
unsigned int this_vecs = affd->set_size[i];
+ unsigned int nr_masks;
int j;
- struct cpumask *result = group_cpus_evenly(this_vecs);
+ struct cpumask *result = group_cpus_evenly(this_vecs, &nr_masks);
if (!result) {
kfree(masks);
return NULL;
}
- for (j = 0; j < this_vecs; j++)
+ for (j = 0; j < nr_masks; j++)
cpumask_copy(&masks[curvec + j], &result[j]);
kfree(result);
- curvec += this_vecs;
- usedvecs += this_vecs;
+ curvec += nr_masks;
+ usedvecs += nr_masks;
}
/* Fill out vectors at the end that don't need affinity */