aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/virtio/virtio_pci.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2008-05-02 21:50:50 -0500
committerRusty Russell <rusty@rustcorp.com.au>2008-05-02 21:50:50 +1000
commitc45a6816c19dee67b8f725e6646d428901a6dc24 (patch)
tree096e3263fd14e140685bcc3082394ff15f5aeddb /drivers/virtio/virtio_pci.c
parent72e61eb40b55dd57031ec5971e810649f82b0259 (diff)
downloadkernel_samsung_smdk4412-c45a6816c19dee67b8f725e6646d428901a6dc24.tar.gz
kernel_samsung_smdk4412-c45a6816c19dee67b8f725e6646d428901a6dc24.tar.bz2
kernel_samsung_smdk4412-c45a6816c19dee67b8f725e6646d428901a6dc24.zip
virtio: explicit advertisement of driver features
A recent proposed feature addition to the virtio block driver revealed some flaws in the API: in particular, we assume that feature negotiation is complete once a driver's probe function returns. There is nothing in the API to require this, however, and even I didn't notice when it was violated. So instead, we require the driver to specify what features it supports in a table, we can then move the feature negotiation into the virtio core. The intersection of device and driver features are presented in a new 'features' bitmap in the struct virtio_device. Note that this highlights the difference between Linux unsigned-long bitmaps where each unsigned long is in native endian, and a straight-forward little-endian array of bytes. Drivers can still remove feature bits in their probe routine if they really have to. API changes: - dev->config->feature() no longer gets and acks a feature. - drivers should advertise their features in the 'feature_table' field - use virtio_has_feature() for extra sanity when checking feature bits Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/virtio/virtio_pci.c')
-rw-r--r--drivers/virtio/virtio_pci.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index de102a614e9..27e9fc9117c 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -87,23 +87,22 @@ static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
return container_of(vdev, struct virtio_pci_device, vdev);
}
-/* virtio config->feature() implementation */
-static bool vp_feature(struct virtio_device *vdev, unsigned bit)
+/* virtio config->get_features() implementation */
+static u32 vp_get_features(struct virtio_device *vdev)
+{
+ struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+
+ /* When someone needs more than 32 feature bits, we'll need to
+ * steal a bit to indicate that the rest are somewhere else. */
+ return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
+}
+
+/* virtio config->set_features() implementation */
+static void vp_set_features(struct virtio_device *vdev, u32 features)
{
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
- u32 mask;
-
- /* Since this function is supposed to have the side effect of
- * enabling a queried feature, we simulate that by doing a read
- * from the host feature bitmask and then writing to the guest
- * feature bitmask */
- mask = ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
- if (mask & (1 << bit)) {
- mask |= (1 << bit);
- iowrite32(mask, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
- }
- return !!(mask & (1 << bit));
+ iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
}
/* virtio config->get() implementation */
@@ -293,7 +292,6 @@ static void vp_del_vq(struct virtqueue *vq)
}
static struct virtio_config_ops virtio_pci_config_ops = {
- .feature = vp_feature,
.get = vp_get,
.set = vp_set,
.get_status = vp_get_status,
@@ -301,6 +299,8 @@ static struct virtio_config_ops virtio_pci_config_ops = {
.reset = vp_reset,
.find_vq = vp_find_vq,
.del_vq = vp_del_vq,
+ .get_features = vp_get_features,
+ .set_features = vp_set_features,
};
/* the PCI probing function */