diff options
Diffstat (limited to 'drivers/virtio/virtio.c')
-rw-r--r-- | drivers/virtio/virtio.c | 65 |
1 files changed, 18 insertions, 47 deletions
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 69d7ea02cd48..b535483bc556 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c | |||
@@ -102,9 +102,13 @@ static int virtio_dev_remove(struct device *_d) | |||
102 | struct virtio_driver *drv = container_of(dev->dev.driver, | 102 | struct virtio_driver *drv = container_of(dev->dev.driver, |
103 | struct virtio_driver, driver); | 103 | struct virtio_driver, driver); |
104 | 104 | ||
105 | dev->config->set_status(dev, dev->config->get_status(dev) | ||
106 | & ~VIRTIO_CONFIG_S_DRIVER); | ||
107 | drv->remove(dev); | 105 | drv->remove(dev); |
106 | |||
107 | /* Driver should have reset device. */ | ||
108 | BUG_ON(dev->config->get_status(dev)); | ||
109 | |||
110 | /* Acknowledge the device's existence again. */ | ||
111 | add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); | ||
108 | return 0; | 112 | return 0; |
109 | } | 113 | } |
110 | 114 | ||
@@ -130,6 +134,10 @@ int register_virtio_device(struct virtio_device *dev) | |||
130 | dev->dev.bus = &virtio_bus; | 134 | dev->dev.bus = &virtio_bus; |
131 | sprintf(dev->dev.bus_id, "%u", dev->index); | 135 | sprintf(dev->dev.bus_id, "%u", dev->index); |
132 | 136 | ||
137 | /* We always start by resetting the device, in case a previous | ||
138 | * driver messed it up. This also tests that code path a little. */ | ||
139 | dev->config->reset(dev); | ||
140 | |||
133 | /* Acknowledge that we've seen the device. */ | 141 | /* Acknowledge that we've seen the device. */ |
134 | add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); | 142 | add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); |
135 | 143 | ||
@@ -148,55 +156,18 @@ void unregister_virtio_device(struct virtio_device *dev) | |||
148 | } | 156 | } |
149 | EXPORT_SYMBOL_GPL(unregister_virtio_device); | 157 | EXPORT_SYMBOL_GPL(unregister_virtio_device); |
150 | 158 | ||
151 | int __virtio_config_val(struct virtio_device *vdev, | ||
152 | u8 type, void *val, size_t size) | ||
153 | { | ||
154 | void *token; | ||
155 | unsigned int len; | ||
156 | |||
157 | token = vdev->config->find(vdev, type, &len); | ||
158 | if (!token) | ||
159 | return -ENOENT; | ||
160 | |||
161 | if (len != size) | ||
162 | return -EIO; | ||
163 | |||
164 | vdev->config->get(vdev, token, val, size); | ||
165 | return 0; | ||
166 | } | ||
167 | EXPORT_SYMBOL_GPL(__virtio_config_val); | ||
168 | |||
169 | int virtio_use_bit(struct virtio_device *vdev, | ||
170 | void *token, unsigned int len, unsigned int bitnum) | ||
171 | { | ||
172 | unsigned long bits[16]; | ||
173 | |||
174 | /* This makes it convenient to pass-through find() results. */ | ||
175 | if (!token) | ||
176 | return 0; | ||
177 | |||
178 | /* bit not in range of this bitfield? */ | ||
179 | if (bitnum * 8 >= len / 2) | ||
180 | return 0; | ||
181 | |||
182 | /* Giant feature bitfields are silly. */ | ||
183 | BUG_ON(len > sizeof(bits)); | ||
184 | vdev->config->get(vdev, token, bits, len); | ||
185 | |||
186 | if (!test_bit(bitnum, bits)) | ||
187 | return 0; | ||
188 | |||
189 | /* Set acknowledge bit, and write it back. */ | ||
190 | set_bit(bitnum + len * 8 / 2, bits); | ||
191 | vdev->config->set(vdev, token, bits, len); | ||
192 | return 1; | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(virtio_use_bit); | ||
195 | |||
196 | static int virtio_init(void) | 159 | static int virtio_init(void) |
197 | { | 160 | { |
198 | if (bus_register(&virtio_bus) != 0) | 161 | if (bus_register(&virtio_bus) != 0) |
199 | panic("virtio bus registration failed"); | 162 | panic("virtio bus registration failed"); |
200 | return 0; | 163 | return 0; |
201 | } | 164 | } |
165 | |||
166 | static void __exit virtio_exit(void) | ||
167 | { | ||
168 | bus_unregister(&virtio_bus); | ||
169 | } | ||
202 | core_initcall(virtio_init); | 170 | core_initcall(virtio_init); |
171 | module_exit(virtio_exit); | ||
172 | |||
173 | MODULE_LICENSE("GPL"); | ||