diff options
author | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-07-27 07:54:08 -0400 |
---|---|---|
committer | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-07-27 07:54:08 -0400 |
commit | eda3d8f5604860aae1bb9996bb5efc4213778369 (patch) | |
tree | 9d3887d2665bcc5f5abf200758794545c7b2c69b /drivers/virtio | |
parent | 87a9f704658a40940e740b1d73d861667e9164d3 (diff) | |
parent | 8be1a6d6c77ab4532e4476fdb8177030ef48b52c (diff) |
Merge commit 'upstream/master'
Diffstat (limited to 'drivers/virtio')
-rw-r--r-- | drivers/virtio/virtio.c | 26 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 13 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 23 |
3 files changed, 45 insertions, 17 deletions
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 7084e7e146c0..5b78fd0aff0a 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
@@ -71,13 +71,6 @@ static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) | |||
71 | dev->id.device, dev->id.vendor); | 71 | dev->id.device, dev->id.vendor); |
72 | } | 72 | } |
73 | 73 | ||
74 | static struct bus_type virtio_bus = { | ||
75 | .name = "virtio", | ||
76 | .match = virtio_dev_match, | ||
77 | .dev_attrs = virtio_dev_attrs, | ||
78 | .uevent = virtio_uevent, | ||
79 | }; | ||
80 | |||
81 | static void add_status(struct virtio_device *dev, unsigned status) | 74 | static void add_status(struct virtio_device *dev, unsigned status) |
82 | { | 75 | { |
83 | dev->config->set_status(dev, dev->config->get_status(dev) | status); | 76 | dev->config->set_status(dev, dev->config->get_status(dev) | status); |
@@ -120,12 +113,16 @@ static int virtio_dev_probe(struct device *_d) | |||
120 | set_bit(f, dev->features); | 113 | set_bit(f, dev->features); |
121 | } | 114 | } |
122 | 115 | ||
116 | /* Transport features always preserved to pass to finalize_features. */ | ||
117 | for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) | ||
118 | if (device_features & (1 << i)) | ||
119 | set_bit(i, dev->features); | ||
120 | |||
123 | err = drv->probe(dev); | 121 | err = drv->probe(dev); |
124 | if (err) | 122 | if (err) |
125 | add_status(dev, VIRTIO_CONFIG_S_FAILED); | 123 | add_status(dev, VIRTIO_CONFIG_S_FAILED); |
126 | else { | 124 | else { |
127 | /* They should never have set feature bits beyond 32 */ | 125 | dev->config->finalize_features(dev); |
128 | dev->config->set_features(dev, dev->features[0]); | ||
129 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); | 126 | add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); |
130 | } | 127 | } |
131 | return err; | 128 | return err; |
@@ -147,13 +144,20 @@ static int virtio_dev_remove(struct device *_d) | |||
147 | return 0; | 144 | return 0; |
148 | } | 145 | } |
149 | 146 | ||
147 | static struct bus_type virtio_bus = { | ||
148 | .name = "virtio", | ||
149 | .match = virtio_dev_match, | ||
150 | .dev_attrs = virtio_dev_attrs, | ||
151 | .uevent = virtio_uevent, | ||
152 | .probe = virtio_dev_probe, | ||
153 | .remove = virtio_dev_remove, | ||
154 | }; | ||
155 | |||
150 | int register_virtio_driver(struct virtio_driver *driver) | 156 | int register_virtio_driver(struct virtio_driver *driver) |
151 | { | 157 | { |
152 | /* Catch this early. */ | 158 | /* Catch this early. */ |
153 | BUG_ON(driver->feature_table_size && !driver->feature_table); | 159 | BUG_ON(driver->feature_table_size && !driver->feature_table); |
154 | driver->driver.bus = &virtio_bus; | 160 | driver->driver.bus = &virtio_bus; |
155 | driver->driver.probe = virtio_dev_probe; | ||
156 | driver->driver.remove = virtio_dev_remove; | ||
157 | return driver_register(&driver->driver); | 161 | return driver_register(&driver->driver); |
158 | } | 162 | } |
159 | EXPORT_SYMBOL_GPL(register_virtio_driver); | 163 | EXPORT_SYMBOL_GPL(register_virtio_driver); |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index eae7236310e4..c7dc37c7cce9 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
@@ -94,12 +94,17 @@ static u32 vp_get_features(struct virtio_device *vdev) | |||
94 | return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); | 94 | return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); |
95 | } | 95 | } |
96 | 96 | ||
97 | /* virtio config->set_features() implementation */ | 97 | /* virtio config->finalize_features() implementation */ |
98 | static void vp_set_features(struct virtio_device *vdev, u32 features) | 98 | static void vp_finalize_features(struct virtio_device *vdev) |
99 | { | 99 | { |
100 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 100 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
101 | 101 | ||
102 | iowrite32(features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); | 102 | /* Give virtio_ring a chance to accept features. */ |
103 | vring_transport_features(vdev); | ||
104 | |||
105 | /* We only support 32 feature bits. */ | ||
106 | BUILD_BUG_ON(ARRAY_SIZE(vdev->features) != 1); | ||
107 | iowrite32(vdev->features[0], vp_dev->ioaddr+VIRTIO_PCI_GUEST_FEATURES); | ||
103 | } | 108 | } |
104 | 109 | ||
105 | /* virtio config->get() implementation */ | 110 | /* virtio config->get() implementation */ |
@@ -297,7 +302,7 @@ static struct virtio_config_ops virtio_pci_config_ops = { | |||
297 | .find_vq = vp_find_vq, | 302 | .find_vq = vp_find_vq, |
298 | .del_vq = vp_del_vq, | 303 | .del_vq = vp_del_vq, |
299 | .get_features = vp_get_features, | 304 | .get_features = vp_get_features, |
300 | .set_features = vp_set_features, | 305 | .finalize_features = vp_finalize_features, |
301 | }; | 306 | }; |
302 | 307 | ||
303 | /* the PCI probing function */ | 308 | /* the PCI probing function */ |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 72bf8bc09014..6eb5303fed11 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | #include <linux/virtio.h> | 19 | #include <linux/virtio.h> |
20 | #include <linux/virtio_ring.h> | 20 | #include <linux/virtio_ring.h> |
21 | #include <linux/virtio_config.h> | ||
21 | #include <linux/device.h> | 22 | #include <linux/device.h> |
22 | 23 | ||
23 | #ifdef DEBUG | 24 | #ifdef DEBUG |
@@ -87,8 +88,11 @@ static int vring_add_buf(struct virtqueue *_vq, | |||
87 | if (vq->num_free < out + in) { | 88 | if (vq->num_free < out + in) { |
88 | pr_debug("Can't add buf len %i - avail = %i\n", | 89 | pr_debug("Can't add buf len %i - avail = %i\n", |
89 | out + in, vq->num_free); | 90 | out + in, vq->num_free); |
90 | /* We notify *even if* VRING_USED_F_NO_NOTIFY is set here. */ | 91 | /* FIXME: for historical reasons, we force a notify here if |
91 | vq->notify(&vq->vq); | 92 | * there are outgoing parts to the buffer. Presumably the |
93 | * host should service the ring ASAP. */ | ||
94 | if (out) | ||
95 | vq->notify(&vq->vq); | ||
92 | END_USE(vq); | 96 | END_USE(vq); |
93 | return -ENOSPC; | 97 | return -ENOSPC; |
94 | } | 98 | } |
@@ -320,4 +324,19 @@ void vring_del_virtqueue(struct virtqueue *vq) | |||
320 | } | 324 | } |
321 | EXPORT_SYMBOL_GPL(vring_del_virtqueue); | 325 | EXPORT_SYMBOL_GPL(vring_del_virtqueue); |
322 | 326 | ||
327 | /* Manipulates transport-specific feature bits. */ | ||
328 | void vring_transport_features(struct virtio_device *vdev) | ||
329 | { | ||
330 | unsigned int i; | ||
331 | |||
332 | for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) { | ||
333 | switch (i) { | ||
334 | default: | ||
335 | /* We don't understand this bit. */ | ||
336 | clear_bit(i, vdev->features); | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | EXPORT_SYMBOL_GPL(vring_transport_features); | ||
341 | |||
323 | MODULE_LICENSE("GPL"); | 342 | MODULE_LICENSE("GPL"); |