aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/virtio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/virtio')
-rw-r--r--drivers/virtio/virtio.c38
-rw-r--r--drivers/virtio/virtio_balloon.c12
-rw-r--r--drivers/virtio/virtio_pci.c34
-rw-r--r--drivers/virtio/virtio_ring.c5
4 files changed, 66 insertions, 23 deletions
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index b535483bc556..13866789b356 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -80,19 +80,51 @@ static void add_status(struct virtio_device *dev, unsigned status)
80 dev->config->set_status(dev, dev->config->get_status(dev) | status); 80 dev->config->set_status(dev, dev->config->get_status(dev) | status);
81} 81}
82 82
83void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
84 unsigned int fbit)
85{
86 unsigned int i;
87 struct virtio_driver *drv = container_of(vdev->dev.driver,
88 struct virtio_driver, driver);
89
90 for (i = 0; i < drv->feature_table_size; i++)
91 if (drv->feature_table[i] == fbit)
92 return;
93 BUG();
94}
95EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature);
96
83static int virtio_dev_probe(struct device *_d) 97static int virtio_dev_probe(struct device *_d)
84{ 98{
85 int err; 99 int err, i;
86 struct virtio_device *dev = container_of(_d,struct virtio_device,dev); 100 struct virtio_device *dev = container_of(_d,struct virtio_device,dev);
87 struct virtio_driver *drv = container_of(dev->dev.driver, 101 struct virtio_driver *drv = container_of(dev->dev.driver,
88 struct virtio_driver, driver); 102 struct virtio_driver, driver);
103 u32 device_features;
89 104
105 /* We have a driver! */
90 add_status(dev, VIRTIO_CONFIG_S_DRIVER); 106 add_status(dev, VIRTIO_CONFIG_S_DRIVER);
107
108 /* Figure out what features the device supports. */
109 device_features = dev->config->get_features(dev);
110
111 /* Features supported by both device and driver into dev->features. */
112 memset(dev->features, 0, sizeof(dev->features));
113 for (i = 0; i < drv->feature_table_size; i++) {
114 unsigned int f = drv->feature_table[i];
115 BUG_ON(f >= 32);
116 if (device_features & (1 << f))
117 set_bit(f, dev->features);
118 }
119
91 err = drv->probe(dev); 120 err = drv->probe(dev);
92 if (err) 121 if (err)
93 add_status(dev, VIRTIO_CONFIG_S_FAILED); 122 add_status(dev, VIRTIO_CONFIG_S_FAILED);
94 else 123 else {
95 add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); 124 add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
125 /* They should never have set feature bits beyond 32 */
126 dev->config->set_features(dev, dev->features[0]);
127 }
96 return err; 128 return err;
97} 129}
98 130
@@ -114,6 +146,8 @@ static int virtio_dev_remove(struct device *_d)
114 146
115int register_virtio_driver(struct virtio_driver *driver) 147int register_virtio_driver(struct virtio_driver *driver)
116{ 148{
149 /* Catch this early. */
150 BUG_ON(driver->feature_table_size && !driver->feature_table);
117 driver->driver.bus = &virtio_bus; 151 driver->driver.bus = &virtio_bus;
118 driver->driver.probe = virtio_dev_probe; 152 driver->driver.probe = virtio_dev_probe;
119 driver->driver.remove = virtio_dev_remove; 153 driver->driver.remove = virtio_dev_remove;
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 0b3efc31ee6d..bfef604160d1 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -155,9 +155,9 @@ static void virtballoon_changed(struct virtio_device *vdev)
155static inline s64 towards_target(struct virtio_balloon *vb) 155static inline s64 towards_target(struct virtio_balloon *vb)
156{ 156{
157 u32 v; 157 u32 v;
158 __virtio_config_val(vb->vdev, 158 vb->vdev->config->get(vb->vdev,
159 offsetof(struct virtio_balloon_config, num_pages), 159 offsetof(struct virtio_balloon_config, num_pages),
160 &v); 160 &v, sizeof(v));
161 return v - vb->num_pages; 161 return v - vb->num_pages;
162} 162}
163 163
@@ -227,7 +227,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
227 } 227 }
228 228
229 vb->tell_host_first 229 vb->tell_host_first
230 = vdev->config->feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); 230 = virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
231 231
232 return 0; 232 return 0;
233 233
@@ -259,7 +259,11 @@ static void virtballoon_remove(struct virtio_device *vdev)
259 kfree(vb); 259 kfree(vb);
260} 260}
261 261
262static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST };
263
262static struct virtio_driver virtio_balloon = { 264static struct virtio_driver virtio_balloon = {
265 .feature_table = features,
266 .feature_table_size = ARRAY_SIZE(features),
263 .driver.name = KBUILD_MODNAME, 267 .driver.name = KBUILD_MODNAME,
264 .driver.owner = THIS_MODULE, 268 .driver.owner = THIS_MODULE,
265 .id_table = id_table, 269 .id_table = id_table,
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index c0df924766a7..27e9fc9117cd 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)
87 return container_of(vdev, struct virtio_pci_device, vdev); 87 return container_of(vdev, struct virtio_pci_device, vdev);
88} 88}
89 89
90/* virtio config->feature() implementation */ 90/* virtio config->get_features() implementation */
91static bool vp_feature(struct virtio_device *vdev, unsigned bit) 91static u32 vp_get_features(struct virtio_device *vdev)
92{
93 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
94
95 /* When someone needs more than 32 feature bits, we'll need to
96 * steal a bit to indicate that the rest are somewhere else. */
97 return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
98}
99
100/* virtio config->set_features() implementation */
101static void vp_set_features(struct virtio_device *vdev, u32 features)
92{ 102{
93 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 103 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
94 u32 mask;
95
96 /* Since this function is supposed to have the side effect of
97 * enabling a queried feature, we simulate that by doing a read
98 * from the host feature bitmask and then writing to the guest
99 * feature bitmask */
100 mask = ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
101 if (mask & (1 << bit)) {
102 mask |= (1 << bit);
103 iowrite32(mask, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
104 }
105 104
106 return !!(mask & (1 << bit)); 105 iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
107} 106}
108 107
109/* virtio config->get() implementation */ 108/* virtio config->get() implementation */
@@ -145,14 +144,14 @@ static void vp_set_status(struct virtio_device *vdev, u8 status)
145 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 144 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
146 /* We should never be setting status to 0. */ 145 /* We should never be setting status to 0. */
147 BUG_ON(status == 0); 146 BUG_ON(status == 0);
148 return iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS); 147 iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
149} 148}
150 149
151static void vp_reset(struct virtio_device *vdev) 150static void vp_reset(struct virtio_device *vdev)
152{ 151{
153 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 152 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
154 /* 0 status means a reset. */ 153 /* 0 status means a reset. */
155 return iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS); 154 iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
156} 155}
157 156
158/* the notify function used when creating a virt queue */ 157/* the notify function used when creating a virt queue */
@@ -293,7 +292,6 @@ static void vp_del_vq(struct virtqueue *vq)
293} 292}
294 293
295static struct virtio_config_ops virtio_pci_config_ops = { 294static struct virtio_config_ops virtio_pci_config_ops = {
296 .feature = vp_feature,
297 .get = vp_get, 295 .get = vp_get,
298 .set = vp_set, 296 .set = vp_set,
299 .get_status = vp_get_status, 297 .get_status = vp_get_status,
@@ -301,6 +299,8 @@ static struct virtio_config_ops virtio_pci_config_ops = {
301 .reset = vp_reset, 299 .reset = vp_reset,
302 .find_vq = vp_find_vq, 300 .find_vq = vp_find_vq,
303 .del_vq = vp_del_vq, 301 .del_vq = vp_del_vq,
302 .get_features = vp_get_features,
303 .set_features = vp_set_features,
304}; 304};
305 305
306/* the PCI probing function */ 306/* the PCI probing function */
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index c2fa5c630813..937a49d6772c 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -184,6 +184,11 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
184 184
185 START_USE(vq); 185 START_USE(vq);
186 186
187 if (unlikely(vq->broken)) {
188 END_USE(vq);
189 return NULL;
190 }
191
187 if (!more_used(vq)) { 192 if (!more_used(vq)) {
188 pr_debug("No more buffers in queue\n"); 193 pr_debug("No more buffers in queue\n");
189 END_USE(vq); 194 END_USE(vq);