diff options
Diffstat (limited to 'drivers/virtio/virtio_pci.c')
-rw-r--r-- | drivers/virtio/virtio_pci.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index c7dc37c7cce9..265fdf2d1276 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
@@ -75,7 +75,7 @@ MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); | |||
75 | * would make more sense for virtio to not insist on having it's own device. */ | 75 | * would make more sense for virtio to not insist on having it's own device. */ |
76 | static struct device virtio_pci_root = { | 76 | static struct device virtio_pci_root = { |
77 | .parent = NULL, | 77 | .parent = NULL, |
78 | .bus_id = "virtio-pci", | 78 | .init_name = "virtio-pci", |
79 | }; | 79 | }; |
80 | 80 | ||
81 | /* Convert a generic virtio device to our structure */ | 81 | /* Convert a generic virtio device to our structure */ |
@@ -216,7 +216,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
216 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 216 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
217 | struct virtio_pci_vq_info *info; | 217 | struct virtio_pci_vq_info *info; |
218 | struct virtqueue *vq; | 218 | struct virtqueue *vq; |
219 | unsigned long flags; | 219 | unsigned long flags, size; |
220 | u16 num; | 220 | u16 num; |
221 | int err; | 221 | int err; |
222 | 222 | ||
@@ -237,19 +237,20 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
237 | info->queue_index = index; | 237 | info->queue_index = index; |
238 | info->num = num; | 238 | info->num = num; |
239 | 239 | ||
240 | info->queue = kzalloc(PAGE_ALIGN(vring_size(num,PAGE_SIZE)), GFP_KERNEL); | 240 | size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); |
241 | info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); | ||
241 | if (info->queue == NULL) { | 242 | if (info->queue == NULL) { |
242 | err = -ENOMEM; | 243 | err = -ENOMEM; |
243 | goto out_info; | 244 | goto out_info; |
244 | } | 245 | } |
245 | 246 | ||
246 | /* activate the queue */ | 247 | /* activate the queue */ |
247 | iowrite32(virt_to_phys(info->queue) >> PAGE_SHIFT, | 248 | iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, |
248 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 249 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
249 | 250 | ||
250 | /* create the vring */ | 251 | /* create the vring */ |
251 | vq = vring_new_virtqueue(info->num, vdev, info->queue, | 252 | vq = vring_new_virtqueue(info->num, VIRTIO_PCI_VRING_ALIGN, |
252 | vp_notify, callback); | 253 | vdev, info->queue, vp_notify, callback); |
253 | if (!vq) { | 254 | if (!vq) { |
254 | err = -ENOMEM; | 255 | err = -ENOMEM; |
255 | goto out_activate_queue; | 256 | goto out_activate_queue; |
@@ -266,7 +267,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
266 | 267 | ||
267 | out_activate_queue: | 268 | out_activate_queue: |
268 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 269 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
269 | kfree(info->queue); | 270 | free_pages_exact(info->queue, size); |
270 | out_info: | 271 | out_info: |
271 | kfree(info); | 272 | kfree(info); |
272 | return ERR_PTR(err); | 273 | return ERR_PTR(err); |
@@ -277,7 +278,7 @@ static void vp_del_vq(struct virtqueue *vq) | |||
277 | { | 278 | { |
278 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | 279 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); |
279 | struct virtio_pci_vq_info *info = vq->priv; | 280 | struct virtio_pci_vq_info *info = vq->priv; |
280 | unsigned long flags; | 281 | unsigned long flags, size; |
281 | 282 | ||
282 | spin_lock_irqsave(&vp_dev->lock, flags); | 283 | spin_lock_irqsave(&vp_dev->lock, flags); |
283 | list_del(&info->node); | 284 | list_del(&info->node); |
@@ -289,7 +290,8 @@ static void vp_del_vq(struct virtqueue *vq) | |||
289 | iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); | 290 | iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); |
290 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 291 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
291 | 292 | ||
292 | kfree(info->queue); | 293 | size = PAGE_ALIGN(vring_size(info->num, VIRTIO_PCI_VRING_ALIGN)); |
294 | free_pages_exact(info->queue, size); | ||
293 | kfree(info); | 295 | kfree(info); |
294 | } | 296 | } |
295 | 297 | ||
@@ -305,6 +307,20 @@ static struct virtio_config_ops virtio_pci_config_ops = { | |||
305 | .finalize_features = vp_finalize_features, | 307 | .finalize_features = vp_finalize_features, |
306 | }; | 308 | }; |
307 | 309 | ||
310 | static void virtio_pci_release_dev(struct device *_d) | ||
311 | { | ||
312 | struct virtio_device *dev = container_of(_d, struct virtio_device, dev); | ||
313 | struct virtio_pci_device *vp_dev = to_vp_device(dev); | ||
314 | struct pci_dev *pci_dev = vp_dev->pci_dev; | ||
315 | |||
316 | free_irq(pci_dev->irq, vp_dev); | ||
317 | pci_set_drvdata(pci_dev, NULL); | ||
318 | pci_iounmap(pci_dev, vp_dev->ioaddr); | ||
319 | pci_release_regions(pci_dev); | ||
320 | pci_disable_device(pci_dev); | ||
321 | kfree(vp_dev); | ||
322 | } | ||
323 | |||
308 | /* the PCI probing function */ | 324 | /* the PCI probing function */ |
309 | static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, | 325 | static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, |
310 | const struct pci_device_id *id) | 326 | const struct pci_device_id *id) |
@@ -328,6 +344,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, | |||
328 | return -ENOMEM; | 344 | return -ENOMEM; |
329 | 345 | ||
330 | vp_dev->vdev.dev.parent = &virtio_pci_root; | 346 | vp_dev->vdev.dev.parent = &virtio_pci_root; |
347 | vp_dev->vdev.dev.release = virtio_pci_release_dev; | ||
331 | vp_dev->vdev.config = &virtio_pci_config_ops; | 348 | vp_dev->vdev.config = &virtio_pci_config_ops; |
332 | vp_dev->pci_dev = pci_dev; | 349 | vp_dev->pci_dev = pci_dev; |
333 | INIT_LIST_HEAD(&vp_dev->virtqueues); | 350 | INIT_LIST_HEAD(&vp_dev->virtqueues); |
@@ -357,7 +374,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, | |||
357 | 374 | ||
358 | /* register a handler for the queue with the PCI device's interrupt */ | 375 | /* register a handler for the queue with the PCI device's interrupt */ |
359 | err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, | 376 | err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, |
360 | vp_dev->vdev.dev.bus_id, vp_dev); | 377 | dev_name(&vp_dev->vdev.dev), vp_dev); |
361 | if (err) | 378 | if (err) |
362 | goto out_set_drvdata; | 379 | goto out_set_drvdata; |
363 | 380 | ||
@@ -387,12 +404,6 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev) | |||
387 | struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); | 404 | struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); |
388 | 405 | ||
389 | unregister_virtio_device(&vp_dev->vdev); | 406 | unregister_virtio_device(&vp_dev->vdev); |
390 | free_irq(pci_dev->irq, vp_dev); | ||
391 | pci_set_drvdata(pci_dev, NULL); | ||
392 | pci_iounmap(pci_dev, vp_dev->ioaddr); | ||
393 | pci_release_regions(pci_dev); | ||
394 | pci_disable_device(pci_dev); | ||
395 | kfree(vp_dev); | ||
396 | } | 407 | } |
397 | 408 | ||
398 | #ifdef CONFIG_PM | 409 | #ifdef CONFIG_PM |