diff options
| -rw-r--r-- | drivers/virtio/virtio_pci_common.h | 6 | ||||
| -rw-r--r-- | drivers/virtio/virtio_pci_legacy.c | 42 | ||||
| -rw-r--r-- | drivers/virtio/virtio_pci_modern.c | 61 |
3 files changed, 33 insertions, 76 deletions
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h index 2cc252270b2d..28263200ed42 100644 --- a/drivers/virtio/virtio_pci_common.h +++ b/drivers/virtio/virtio_pci_common.h | |||
| @@ -35,12 +35,6 @@ struct virtio_pci_vq_info { | |||
| 35 | /* the actual virtqueue */ | 35 | /* the actual virtqueue */ |
| 36 | struct virtqueue *vq; | 36 | struct virtqueue *vq; |
| 37 | 37 | ||
| 38 | /* the number of entries in the queue */ | ||
| 39 | int num; | ||
| 40 | |||
| 41 | /* the virtual address of the ring queue */ | ||
| 42 | void *queue; | ||
| 43 | |||
| 44 | /* the list node for the virtqueues list */ | 38 | /* the list node for the virtqueues list */ |
| 45 | struct list_head node; | 39 | struct list_head node; |
| 46 | 40 | ||
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c index 48bc9797e530..8c4e61783441 100644 --- a/drivers/virtio/virtio_pci_legacy.c +++ b/drivers/virtio/virtio_pci_legacy.c | |||
| @@ -119,7 +119,6 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |||
| 119 | u16 msix_vec) | 119 | u16 msix_vec) |
| 120 | { | 120 | { |
| 121 | struct virtqueue *vq; | 121 | struct virtqueue *vq; |
| 122 | unsigned long size; | ||
| 123 | u16 num; | 122 | u16 num; |
| 124 | int err; | 123 | int err; |
| 125 | 124 | ||
| @@ -131,27 +130,19 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |||
| 131 | if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) | 130 | if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) |
| 132 | return ERR_PTR(-ENOENT); | 131 | return ERR_PTR(-ENOENT); |
| 133 | 132 | ||
| 134 | info->num = num; | ||
| 135 | info->msix_vector = msix_vec; | 133 | info->msix_vector = msix_vec; |
| 136 | 134 | ||
| 137 | size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); | 135 | /* create the vring */ |
| 138 | info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); | 136 | vq = vring_create_virtqueue(index, num, |
| 139 | if (info->queue == NULL) | 137 | VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, |
| 138 | true, false, vp_notify, callback, name); | ||
| 139 | if (!vq) | ||
| 140 | return ERR_PTR(-ENOMEM); | 140 | return ERR_PTR(-ENOMEM); |
| 141 | 141 | ||
| 142 | /* activate the queue */ | 142 | /* activate the queue */ |
| 143 | iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, | 143 | iowrite32(virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, |
| 144 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 144 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
| 145 | 145 | ||
| 146 | /* create the vring */ | ||
| 147 | vq = vring_new_virtqueue(index, info->num, | ||
| 148 | VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, | ||
| 149 | true, info->queue, vp_notify, callback, name); | ||
| 150 | if (!vq) { | ||
| 151 | err = -ENOMEM; | ||
| 152 | goto out_activate_queue; | ||
| 153 | } | ||
| 154 | |||
| 155 | vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY; | 146 | vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY; |
| 156 | 147 | ||
| 157 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { | 148 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { |
| @@ -159,17 +150,15 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |||
| 159 | msix_vec = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | 150 | msix_vec = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); |
| 160 | if (msix_vec == VIRTIO_MSI_NO_VECTOR) { | 151 | if (msix_vec == VIRTIO_MSI_NO_VECTOR) { |
| 161 | err = -EBUSY; | 152 | err = -EBUSY; |
| 162 | goto out_assign; | 153 | goto out_deactivate; |
| 163 | } | 154 | } |
| 164 | } | 155 | } |
| 165 | 156 | ||
| 166 | return vq; | 157 | return vq; |
| 167 | 158 | ||
| 168 | out_assign: | 159 | out_deactivate: |
| 169 | vring_del_virtqueue(vq); | ||
| 170 | out_activate_queue: | ||
| 171 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 160 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
| 172 | free_pages_exact(info->queue, size); | 161 | vring_del_virtqueue(vq); |
| 173 | return ERR_PTR(err); | 162 | return ERR_PTR(err); |
| 174 | } | 163 | } |
| 175 | 164 | ||
| @@ -177,7 +166,6 @@ static void del_vq(struct virtio_pci_vq_info *info) | |||
| 177 | { | 166 | { |
| 178 | struct virtqueue *vq = info->vq; | 167 | struct virtqueue *vq = info->vq; |
| 179 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | 168 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); |
| 180 | unsigned long size; | ||
| 181 | 169 | ||
| 182 | iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); | 170 | iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); |
| 183 | 171 | ||
| @@ -188,13 +176,10 @@ static void del_vq(struct virtio_pci_vq_info *info) | |||
| 188 | ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR); | 176 | ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR); |
| 189 | } | 177 | } |
| 190 | 178 | ||
| 191 | vring_del_virtqueue(vq); | ||
| 192 | |||
| 193 | /* Select and deactivate the queue */ | 179 | /* Select and deactivate the queue */ |
| 194 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | 180 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
| 195 | 181 | ||
| 196 | size = PAGE_ALIGN(vring_size(info->num, VIRTIO_PCI_VRING_ALIGN)); | 182 | vring_del_virtqueue(vq); |
| 197 | free_pages_exact(info->queue, size); | ||
| 198 | } | 183 | } |
| 199 | 184 | ||
| 200 | static const struct virtio_config_ops virtio_pci_config_ops = { | 185 | static const struct virtio_config_ops virtio_pci_config_ops = { |
| @@ -227,6 +212,13 @@ int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) | |||
| 227 | return -ENODEV; | 212 | return -ENODEV; |
| 228 | } | 213 | } |
| 229 | 214 | ||
| 215 | rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64)); | ||
| 216 | if (rc) | ||
| 217 | rc = dma_set_mask_and_coherent(&pci_dev->dev, | ||
| 218 | DMA_BIT_MASK(32)); | ||
| 219 | if (rc) | ||
| 220 | dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n"); | ||
| 221 | |||
| 230 | rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy"); | 222 | rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy"); |
| 231 | if (rc) | 223 | if (rc) |
| 232 | return rc; | 224 | return rc; |
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 7760fc1a2218..f6f28cc7eb45 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c | |||
| @@ -287,31 +287,6 @@ static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) | |||
| 287 | return vp_ioread16(&vp_dev->common->msix_config); | 287 | return vp_ioread16(&vp_dev->common->msix_config); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | static size_t vring_pci_size(u16 num) | ||
| 291 | { | ||
| 292 | /* We only need a cacheline separation. */ | ||
| 293 | return PAGE_ALIGN(vring_size(num, SMP_CACHE_BYTES)); | ||
| 294 | } | ||
| 295 | |||
| 296 | static void *alloc_virtqueue_pages(int *num) | ||
| 297 | { | ||
| 298 | void *pages; | ||
| 299 | |||
| 300 | /* TODO: allocate each queue chunk individually */ | ||
| 301 | for (; *num && vring_pci_size(*num) > PAGE_SIZE; *num /= 2) { | ||
| 302 | pages = alloc_pages_exact(vring_pci_size(*num), | ||
| 303 | GFP_KERNEL|__GFP_ZERO|__GFP_NOWARN); | ||
| 304 | if (pages) | ||
| 305 | return pages; | ||
| 306 | } | ||
| 307 | |||
| 308 | if (!*num) | ||
| 309 | return NULL; | ||
| 310 | |||
| 311 | /* Try to get a single page. You are my only hope! */ | ||
| 312 | return alloc_pages_exact(vring_pci_size(*num), GFP_KERNEL|__GFP_ZERO); | ||
| 313 | } | ||
| 314 | |||
| 315 | static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | 290 | static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, |
| 316 | struct virtio_pci_vq_info *info, | 291 | struct virtio_pci_vq_info *info, |
| 317 | unsigned index, | 292 | unsigned index, |
| @@ -343,29 +318,22 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |||
| 343 | /* get offset of notification word for this vq */ | 318 | /* get offset of notification word for this vq */ |
| 344 | off = vp_ioread16(&cfg->queue_notify_off); | 319 | off = vp_ioread16(&cfg->queue_notify_off); |
| 345 | 320 | ||
| 346 | info->num = num; | ||
| 347 | info->msix_vector = msix_vec; | 321 | info->msix_vector = msix_vec; |
| 348 | 322 | ||
| 349 | info->queue = alloc_virtqueue_pages(&info->num); | ||
| 350 | if (info->queue == NULL) | ||
| 351 | return ERR_PTR(-ENOMEM); | ||
| 352 | |||
| 353 | /* create the vring */ | 323 | /* create the vring */ |
| 354 | vq = vring_new_virtqueue(index, info->num, | 324 | vq = vring_create_virtqueue(index, num, |
| 355 | SMP_CACHE_BYTES, &vp_dev->vdev, | 325 | SMP_CACHE_BYTES, &vp_dev->vdev, |
| 356 | true, info->queue, vp_notify, callback, name); | 326 | true, true, vp_notify, callback, name); |
| 357 | if (!vq) { | 327 | if (!vq) |
| 358 | err = -ENOMEM; | 328 | return ERR_PTR(-ENOMEM); |
| 359 | goto err_new_queue; | ||
| 360 | } | ||
| 361 | 329 | ||
| 362 | /* activate the queue */ | 330 | /* activate the queue */ |
| 363 | vp_iowrite16(num, &cfg->queue_size); | 331 | vp_iowrite16(virtqueue_get_vring_size(vq), &cfg->queue_size); |
| 364 | vp_iowrite64_twopart(virt_to_phys(info->queue), | 332 | vp_iowrite64_twopart(virtqueue_get_desc_addr(vq), |
| 365 | &cfg->queue_desc_lo, &cfg->queue_desc_hi); | 333 | &cfg->queue_desc_lo, &cfg->queue_desc_hi); |
| 366 | vp_iowrite64_twopart(virt_to_phys(virtqueue_get_avail(vq)), | 334 | vp_iowrite64_twopart(virtqueue_get_avail_addr(vq), |
| 367 | &cfg->queue_avail_lo, &cfg->queue_avail_hi); | 335 | &cfg->queue_avail_lo, &cfg->queue_avail_hi); |
| 368 | vp_iowrite64_twopart(virt_to_phys(virtqueue_get_used(vq)), | 336 | vp_iowrite64_twopart(virtqueue_get_used_addr(vq), |
| 369 | &cfg->queue_used_lo, &cfg->queue_used_hi); | 337 | &cfg->queue_used_lo, &cfg->queue_used_hi); |
| 370 | 338 | ||
| 371 | if (vp_dev->notify_base) { | 339 | if (vp_dev->notify_base) { |
| @@ -410,8 +378,6 @@ err_assign_vector: | |||
| 410 | pci_iounmap(vp_dev->pci_dev, (void __iomem __force *)vq->priv); | 378 | pci_iounmap(vp_dev->pci_dev, (void __iomem __force *)vq->priv); |
| 411 | err_map_notify: | 379 | err_map_notify: |
| 412 | vring_del_virtqueue(vq); | 380 | vring_del_virtqueue(vq); |
| 413 | err_new_queue: | ||
| 414 | free_pages_exact(info->queue, vring_pci_size(info->num)); | ||
| 415 | return ERR_PTR(err); | 381 | return ERR_PTR(err); |
| 416 | } | 382 | } |
| 417 | 383 | ||
| @@ -456,8 +422,6 @@ static void del_vq(struct virtio_pci_vq_info *info) | |||
| 456 | pci_iounmap(vp_dev->pci_dev, (void __force __iomem *)vq->priv); | 422 | pci_iounmap(vp_dev->pci_dev, (void __force __iomem *)vq->priv); |
| 457 | 423 | ||
| 458 | vring_del_virtqueue(vq); | 424 | vring_del_virtqueue(vq); |
| 459 | |||
| 460 | free_pages_exact(info->queue, vring_pci_size(info->num)); | ||
| 461 | } | 425 | } |
| 462 | 426 | ||
| 463 | static const struct virtio_config_ops virtio_pci_config_nodev_ops = { | 427 | static const struct virtio_config_ops virtio_pci_config_nodev_ops = { |
| @@ -641,6 +605,13 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev) | |||
| 641 | return -EINVAL; | 605 | return -EINVAL; |
| 642 | } | 606 | } |
| 643 | 607 | ||
| 608 | err = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64)); | ||
| 609 | if (err) | ||
| 610 | err = dma_set_mask_and_coherent(&pci_dev->dev, | ||
| 611 | DMA_BIT_MASK(32)); | ||
| 612 | if (err) | ||
| 613 | dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n"); | ||
| 614 | |||
| 644 | /* Device capability is only mandatory for devices that have | 615 | /* Device capability is only mandatory for devices that have |
| 645 | * device-specific configuration. | 616 | * device-specific configuration. |
| 646 | */ | 617 | */ |
