aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/virtio_blk.c8
-rw-r--r--drivers/lguest/lguest_device.c48
-rw-r--r--drivers/net/virtio_net.c22
-rw-r--r--drivers/virtio/virtio.c38
-rw-r--r--drivers/virtio/virtio_balloon.c6
-rw-r--r--drivers/virtio/virtio_pci.c30
-rw-r--r--include/linux/virtio.h7
-rw-r--r--include/linux/virtio_config.h36
8 files changed, 142 insertions, 53 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index cc6d39383a3f..78be6b8c89e0 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -242,7 +242,7 @@ static int virtblk_probe(struct virtio_device *vdev)
242 index++; 242 index++;
243 243
244 /* If barriers are supported, tell block layer that queue is ordered */ 244 /* If barriers are supported, tell block layer that queue is ordered */
245 if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER)) 245 if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER))
246 blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); 246 blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
247 247
248 /* Host must always specify the capacity. */ 248 /* Host must always specify the capacity. */
@@ -308,7 +308,13 @@ static struct virtio_device_id id_table[] = {
308 { 0 }, 308 { 0 },
309}; 309};
310 310
311static unsigned int features[] = {
312 VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
313};
314
311static struct virtio_driver virtio_blk = { 315static struct virtio_driver virtio_blk = {
316 .feature_table = features,
317 .feature_table_size = ARRAY_SIZE(features),
312 .driver.name = KBUILD_MODNAME, 318 .driver.name = KBUILD_MODNAME,
313 .driver.owner = THIS_MODULE, 319 .driver.owner = THIS_MODULE,
314 .id_table = id_table, 320 .id_table = id_table,
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 2bc9bf7e88e5..7a643a6ee9a1 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -85,27 +85,34 @@ static unsigned desc_size(const struct lguest_device_desc *desc)
85 + desc->config_len; 85 + desc->config_len;
86} 86}
87 87
88/* This tests (and acknowleges) a feature bit. */ 88/* This gets the device's feature bits. */
89static bool lg_feature(struct virtio_device *vdev, unsigned fbit) 89static u32 lg_get_features(struct virtio_device *vdev)
90{ 90{
91 unsigned int i;
92 u32 features = 0;
93 struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
94 u8 *in_features = lg_features(desc);
95
96 /* We do this the slow but generic way. */
97 for (i = 0; i < min(desc->feature_len * 8, 32); i++)
98 if (in_features[i / 8] & (1 << (i % 8)))
99 features |= (1 << i);
100
101 return features;
102}
103
104static void lg_set_features(struct virtio_device *vdev, u32 features)
105{
106 unsigned int i;
91 struct lguest_device_desc *desc = to_lgdev(vdev)->desc; 107 struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
92 u8 *features; 108 /* Second half of bitmap is features we accept. */
93 109 u8 *out_features = lg_features(desc) + desc->feature_len;
94 /* Obviously if they ask for a feature off the end of our feature 110
95 * bitmap, it's not set. */ 111 memset(out_features, 0, desc->feature_len);
96 if (fbit / 8 > desc->feature_len) 112 for (i = 0; i < min(desc->feature_len * 8, 32); i++) {
97 return false; 113 if (features & (1 << i))
98 114 out_features[i / 8] |= (1 << (i % 8));
99 /* The feature bitmap comes after the virtqueues. */ 115 }
100 features = lg_features(desc);
101 if (!(features[fbit / 8] & (1 << (fbit % 8))))
102 return false;
103
104 /* We set the matching bit in the other half of the bitmap to tell the
105 * Host we want to use this feature. We don't use this yet, but we
106 * could in future. */
107 features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8));
108 return true;
109} 116}
110 117
111/* Once they've found a field, getting a copy of it is easy. */ 118/* Once they've found a field, getting a copy of it is easy. */
@@ -286,7 +293,8 @@ static void lg_del_vq(struct virtqueue *vq)
286 293
287/* The ops structure which hooks everything together. */ 294/* The ops structure which hooks everything together. */
288static struct virtio_config_ops lguest_config_ops = { 295static struct virtio_config_ops lguest_config_ops = {
289 .feature = lg_feature, 296 .get_features = lg_get_features,
297 .set_features = lg_set_features,
290 .get = lg_get, 298 .get = lg_get,
291 .set = lg_set, 299 .set = lg_set,
292 .get_status = lg_get_status, 300 .get_status = lg_get_status,
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index ad43421ab6f1..f926b5ab3d09 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -378,26 +378,26 @@ static int virtnet_probe(struct virtio_device *vdev)
378 SET_NETDEV_DEV(dev, &vdev->dev); 378 SET_NETDEV_DEV(dev, &vdev->dev);
379 379
380 /* Do we support "hardware" checksums? */ 380 /* Do we support "hardware" checksums? */
381 if (csum && vdev->config->feature(vdev, VIRTIO_NET_F_CSUM)) { 381 if (csum && virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
382 /* This opens up the world of extra features. */ 382 /* This opens up the world of extra features. */
383 dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; 383 dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
384 if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_GSO)) { 384 if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
385 dev->features |= NETIF_F_TSO | NETIF_F_UFO 385 dev->features |= NETIF_F_TSO | NETIF_F_UFO
386 | NETIF_F_TSO_ECN | NETIF_F_TSO6; 386 | NETIF_F_TSO_ECN | NETIF_F_TSO6;
387 } 387 }
388 /* Individual feature bits: what can host handle? */ 388 /* Individual feature bits: what can host handle? */
389 if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_HOST_TSO4)) 389 if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4))
390 dev->features |= NETIF_F_TSO; 390 dev->features |= NETIF_F_TSO;
391 if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_HOST_TSO6)) 391 if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6))
392 dev->features |= NETIF_F_TSO6; 392 dev->features |= NETIF_F_TSO6;
393 if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_HOST_ECN)) 393 if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
394 dev->features |= NETIF_F_TSO_ECN; 394 dev->features |= NETIF_F_TSO_ECN;
395 if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_HOST_UFO)) 395 if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
396 dev->features |= NETIF_F_UFO; 396 dev->features |= NETIF_F_UFO;
397 } 397 }
398 398
399 /* Configuration may specify what MAC to use. Otherwise random. */ 399 /* Configuration may specify what MAC to use. Otherwise random. */
400 if (vdev->config->feature(vdev, VIRTIO_NET_F_MAC)) { 400 if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
401 vdev->config->get(vdev, 401 vdev->config->get(vdev,
402 offsetof(struct virtio_net_config, mac), 402 offsetof(struct virtio_net_config, mac),
403 dev->dev_addr, dev->addr_len); 403 dev->dev_addr, dev->addr_len);
@@ -486,7 +486,15 @@ static struct virtio_device_id id_table[] = {
486 { 0 }, 486 { 0 },
487}; 487};
488 488
489static unsigned int features[] = {
490 VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
491 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
492 VIRTIO_NET_F_HOST_ECN,
493};
494
489static struct virtio_driver virtio_net = { 495static struct virtio_driver virtio_net = {
496 .feature_table = features,
497 .feature_table_size = ARRAY_SIZE(features),
490 .driver.name = KBUILD_MODNAME, 498 .driver.name = KBUILD_MODNAME,
491 .driver.owner = THIS_MODULE, 499 .driver.owner = THIS_MODULE,
492 .id_table = id_table, 500 .id_table = id_table,
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 fef88d84cef6..bfef604160d1 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -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 de102a614e97..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 */
@@ -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/include/linux/virtio.h b/include/linux/virtio.h
index e7d10845b3c1..06005fa9e982 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -76,6 +76,7 @@ struct virtqueue_ops {
76 * @dev: underlying device. 76 * @dev: underlying device.
77 * @id: the device type identification (used to match it with a driver). 77 * @id: the device type identification (used to match it with a driver).
78 * @config: the configuration ops for this device. 78 * @config: the configuration ops for this device.
79 * @features: the features supported by both driver and device.
79 * @priv: private pointer for the driver's use. 80 * @priv: private pointer for the driver's use.
80 */ 81 */
81struct virtio_device 82struct virtio_device
@@ -84,6 +85,8 @@ struct virtio_device
84 struct device dev; 85 struct device dev;
85 struct virtio_device_id id; 86 struct virtio_device_id id;
86 struct virtio_config_ops *config; 87 struct virtio_config_ops *config;
88 /* Note that this is a Linux set_bit-style bitmap. */
89 unsigned long features[1];
87 void *priv; 90 void *priv;
88}; 91};
89 92
@@ -94,6 +97,8 @@ void unregister_virtio_device(struct virtio_device *dev);
94 * virtio_driver - operations for a virtio I/O driver 97 * virtio_driver - operations for a virtio I/O driver
95 * @driver: underlying device driver (populate name and owner). 98 * @driver: underlying device driver (populate name and owner).
96 * @id_table: the ids serviced by this driver. 99 * @id_table: the ids serviced by this driver.
100 * @feature_table: an array of feature numbers supported by this device.
101 * @feature_table_size: number of entries in the feature table array.
97 * @probe: the function to call when a device is found. Returns a token for 102 * @probe: the function to call when a device is found. Returns a token for
98 * remove, or PTR_ERR(). 103 * remove, or PTR_ERR().
99 * @remove: the function when a device is removed. 104 * @remove: the function when a device is removed.
@@ -103,6 +108,8 @@ void unregister_virtio_device(struct virtio_device *dev);
103struct virtio_driver { 108struct virtio_driver {
104 struct device_driver driver; 109 struct device_driver driver;
105 const struct virtio_device_id *id_table; 110 const struct virtio_device_id *id_table;
111 const unsigned int *feature_table;
112 unsigned int feature_table_size;
106 int (*probe)(struct virtio_device *dev); 113 int (*probe)(struct virtio_device *dev);
107 void (*remove)(struct virtio_device *dev); 114 void (*remove)(struct virtio_device *dev);
108 void (*config_changed)(struct virtio_device *dev); 115 void (*config_changed)(struct virtio_device *dev);
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 475572e976fe..50db245c81ad 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -20,11 +20,6 @@
20 20
21/** 21/**
22 * virtio_config_ops - operations for configuring a virtio device 22 * virtio_config_ops - operations for configuring a virtio device
23 * @feature: search for a feature in this config
24 * vdev: the virtio_device
25 * bit: the feature bit
26 * Returns true if the feature is supported. Acknowledges the feature
27 * so the host can see it.
28 * @get: read the value of a configuration field 23 * @get: read the value of a configuration field
29 * vdev: the virtio_device 24 * vdev: the virtio_device
30 * offset: the offset of the configuration field 25 * offset: the offset of the configuration field
@@ -50,10 +45,15 @@
50 * callback: the virqtueue callback 45 * callback: the virqtueue callback
51 * Returns the new virtqueue or ERR_PTR() (eg. -ENOENT). 46 * Returns the new virtqueue or ERR_PTR() (eg. -ENOENT).
52 * @del_vq: free a virtqueue found by find_vq(). 47 * @del_vq: free a virtqueue found by find_vq().
48 * @get_features: get the array of feature bits for this device.
49 * vdev: the virtio_device
50 * Returns the first 32 feature bits (all we currently need).
51 * @set_features: confirm what device features we'll be using.
52 * vdev: the virtio_device
53 * feature: the first 32 feature bits
53 */ 54 */
54struct virtio_config_ops 55struct virtio_config_ops
55{ 56{
56 bool (*feature)(struct virtio_device *vdev, unsigned bit);
57 void (*get)(struct virtio_device *vdev, unsigned offset, 57 void (*get)(struct virtio_device *vdev, unsigned offset,
58 void *buf, unsigned len); 58 void *buf, unsigned len);
59 void (*set)(struct virtio_device *vdev, unsigned offset, 59 void (*set)(struct virtio_device *vdev, unsigned offset,
@@ -65,8 +65,30 @@ struct virtio_config_ops
65 unsigned index, 65 unsigned index,
66 void (*callback)(struct virtqueue *)); 66 void (*callback)(struct virtqueue *));
67 void (*del_vq)(struct virtqueue *vq); 67 void (*del_vq)(struct virtqueue *vq);
68 u32 (*get_features)(struct virtio_device *vdev);
69 void (*set_features)(struct virtio_device *vdev, u32 features);
68}; 70};
69 71
72/* If driver didn't advertise the feature, it will never appear. */
73void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
74 unsigned int fbit);
75
76/**
77 * virtio_has_feature - helper to determine if this device has this feature.
78 * @vdev: the device
79 * @fbit: the feature bit
80 */
81static inline bool virtio_has_feature(const struct virtio_device *vdev,
82 unsigned int fbit)
83{
84 /* Did you forget to fix assumptions on max features? */
85 if (__builtin_constant_p(fbit))
86 BUILD_BUG_ON(fbit >= 32);
87
88 virtio_check_driver_offered_feature(vdev, fbit);
89 return test_bit(fbit, vdev->features);
90}
91
70/** 92/**
71 * virtio_config_val - look for a feature and get a virtio config entry. 93 * virtio_config_val - look for a feature and get a virtio config entry.
72 * @vdev: the virtio device 94 * @vdev: the virtio device
@@ -84,7 +106,7 @@ static inline int virtio_config_buf(struct virtio_device *vdev,
84 unsigned int offset, 106 unsigned int offset,
85 void *buf, unsigned len) 107 void *buf, unsigned len)
86{ 108{
87 if (!vdev->config->feature(vdev, fbit)) 109 if (!virtio_has_feature(vdev, fbit))
88 return -ENOENT; 110 return -ENOENT;
89 111
90 vdev->config->get(vdev, offset, buf, len); 112 vdev->config->get(vdev, offset, buf, len);