Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio_pci: split vp_try_to_find_vqs into INTx and MSI-X variants

There is basically no shared logic between the INTx and MSI-X case in
vp_try_to_find_vqs, so split the function into two and clean them up
a little bit.

Also remove the fairly pointless vp_request_intx wrapper while we're at it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

authored by

Christoph Hellwig and committed by
Michael S. Tsirkin
a3cbec69 66f2f555

+57 -40
+57 -40
drivers/virtio/virtio_pci_common.c
··· 167 167 return err; 168 168 } 169 169 170 - static int vp_request_intx(struct virtio_device *vdev) 171 - { 172 - int err; 173 - struct virtio_pci_device *vp_dev = to_vp_device(vdev); 174 - 175 - err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, 176 - IRQF_SHARED, dev_name(&vdev->dev), vp_dev); 177 - if (!err) 178 - vp_dev->intx_enabled = 1; 179 - return err; 180 - } 181 - 182 170 static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index, 183 171 void (*callback)(struct virtqueue *vq), 184 172 const char *name, ··· 265 277 vp_dev->vqs = NULL; 266 278 } 267 279 268 - static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, 280 + static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, 269 281 struct virtqueue *vqs[], 270 282 vq_callback_t *callbacks[], 271 283 const char * const names[], 272 - bool use_msix, 273 284 bool per_vq_vectors) 274 285 { 275 286 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 276 287 u16 msix_vec; 277 288 int i, err, nvectors, allocated_vectors; 278 289 279 - vp_dev->vqs = kmalloc(nvqs * sizeof *vp_dev->vqs, GFP_KERNEL); 290 + vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); 280 291 if (!vp_dev->vqs) 281 292 return -ENOMEM; 282 293 283 - if (!use_msix) { 284 - /* Old style: one normal interrupt for change and all vqs. */ 285 - err = vp_request_intx(vdev); 286 - if (err) 287 - goto error_find; 294 + if (per_vq_vectors) { 295 + /* Best option: one for change interrupt, one per vq. */ 296 + nvectors = 1; 297 + for (i = 0; i < nvqs; ++i) 298 + if (callbacks[i]) 299 + ++nvectors; 288 300 } else { 289 - if (per_vq_vectors) { 290 - /* Best option: one for change interrupt, one per vq. */ 291 - nvectors = 1; 292 - for (i = 0; i < nvqs; ++i) 293 - if (callbacks[i]) 294 - ++nvectors; 295 - } else { 296 - /* Second best: one for change, shared for all vqs. */ 297 - nvectors = 2; 298 - } 299 - 300 - err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); 301 - if (err) 302 - goto error_find; 301 + /* Second best: one for change, shared for all vqs. */ 302 + nvectors = 2; 303 303 } 304 + 305 + err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); 306 + if (err) 307 + goto error_find; 304 308 305 309 vp_dev->per_vq_vectors = per_vq_vectors; 306 310 allocated_vectors = vp_dev->msix_used_vectors; ··· 300 320 if (!names[i]) { 301 321 vqs[i] = NULL; 302 322 continue; 303 - } else if (!callbacks[i] || !vp_dev->msix_enabled) 323 + } 324 + 325 + if (!callbacks[i]) 304 326 msix_vec = VIRTIO_MSI_NO_VECTOR; 305 327 else if (vp_dev->per_vq_vectors) 306 328 msix_vec = allocated_vectors++; ··· 336 354 return err; 337 355 } 338 356 357 + static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs, 358 + struct virtqueue *vqs[], vq_callback_t *callbacks[], 359 + const char * const names[]) 360 + { 361 + struct virtio_pci_device *vp_dev = to_vp_device(vdev); 362 + int i, err; 363 + 364 + vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); 365 + if (!vp_dev->vqs) 366 + return -ENOMEM; 367 + 368 + err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, 369 + dev_name(&vdev->dev), vp_dev); 370 + if (err) 371 + goto out_del_vqs; 372 + 373 + vp_dev->intx_enabled = 1; 374 + vp_dev->per_vq_vectors = false; 375 + for (i = 0; i < nvqs; ++i) { 376 + if (!names[i]) { 377 + vqs[i] = NULL; 378 + continue; 379 + } 380 + vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], 381 + VIRTIO_MSI_NO_VECTOR); 382 + if (IS_ERR(vqs[i])) { 383 + err = PTR_ERR(vqs[i]); 384 + goto out_del_vqs; 385 + } 386 + } 387 + 388 + return 0; 389 + out_del_vqs: 390 + vp_del_vqs(vdev); 391 + return err; 392 + } 393 + 339 394 /* the config->find_vqs() implementation */ 340 395 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, 341 396 struct virtqueue *vqs[], ··· 382 363 int err; 383 364 384 365 /* Try MSI-X with one vector per queue. */ 385 - err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, true, true); 366 + err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true); 386 367 if (!err) 387 368 return 0; 388 369 /* Fallback: MSI-X with one vector for config, one shared for queues. */ 389 - err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, 390 - true, false); 370 + err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false); 391 371 if (!err) 392 372 return 0; 393 373 /* Finally fall back to regular interrupts. */ 394 - return vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, 395 - false, false); 374 + return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names); 396 375 } 397 376 398 377 const char *vp_bus_name(struct virtio_device *vdev)