aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/assigned-dev.c
diff options
context:
space:
mode:
authorMichal Marek <mmarek@suse.cz>2010-10-27 18:15:57 -0400
committerMichal Marek <mmarek@suse.cz>2010-10-27 18:15:57 -0400
commitb74b953b998bcc2db91b694446f3a2619ec32de6 (patch)
tree6ce24caabd730f6ae9287ed0676ec32e6ff31e9d /virt/kvm/assigned-dev.c
parentabb438526201c6a79949ad45375c051b6681c253 (diff)
parentf6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff)
Merge commit 'v2.6.36' into kbuild/misc
Update to be able to fix a recent change to scripts/basic/docproc.c (commit eda603f).
Diffstat (limited to 'virt/kvm/assigned-dev.c')
-rw-r--r--virt/kvm/assigned-dev.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
index f73de631e3ee..7c98928b09d9 100644
--- a/virt/kvm/assigned-dev.c
+++ b/virt/kvm/assigned-dev.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Kernel-based Virtual Machine - device assignment support 2 * Kernel-based Virtual Machine - device assignment support
3 * 3 *
4 * Copyright (C) 2006-9 Red Hat, Inc 4 * Copyright (C) 2010 Red Hat, Inc. and/or its affiliates.
5 * 5 *
6 * This work is licensed under the terms of the GNU GPL, version 2. See 6 * This work is licensed under the terms of the GNU GPL, version 2. See
7 * the COPYING file in the top-level directory. 7 * the COPYING file in the top-level directory.
@@ -16,6 +16,7 @@
16#include <linux/spinlock.h> 16#include <linux/spinlock.h>
17#include <linux/pci.h> 17#include <linux/pci.h>
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/slab.h>
19#include "irq.h" 20#include "irq.h"
20 21
21static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, 22static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
@@ -57,12 +58,10 @@ static int find_index_from_host_irq(struct kvm_assigned_dev_kernel
57static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work) 58static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
58{ 59{
59 struct kvm_assigned_dev_kernel *assigned_dev; 60 struct kvm_assigned_dev_kernel *assigned_dev;
60 struct kvm *kvm;
61 int i; 61 int i;
62 62
63 assigned_dev = container_of(work, struct kvm_assigned_dev_kernel, 63 assigned_dev = container_of(work, struct kvm_assigned_dev_kernel,
64 interrupt_work); 64 interrupt_work);
65 kvm = assigned_dev->kvm;
66 65
67 spin_lock_irq(&assigned_dev->assigned_dev_lock); 66 spin_lock_irq(&assigned_dev->assigned_dev_lock);
68 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) { 67 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
@@ -315,12 +314,16 @@ static int assigned_device_enable_host_msix(struct kvm *kvm,
315 kvm_assigned_dev_intr, 0, 314 kvm_assigned_dev_intr, 0,
316 "kvm_assigned_msix_device", 315 "kvm_assigned_msix_device",
317 (void *)dev); 316 (void *)dev);
318 /* FIXME: free requested_irq's on failure */
319 if (r) 317 if (r)
320 return r; 318 goto err;
321 } 319 }
322 320
323 return 0; 321 return 0;
322err:
323 for (i -= 1; i >= 0; i--)
324 free_irq(dev->host_msix_entries[i].vector, (void *)dev);
325 pci_disable_msix(dev->dev);
326 return r;
324} 327}
325 328
326#endif 329#endif
@@ -443,9 +446,6 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
443 struct kvm_assigned_dev_kernel *match; 446 struct kvm_assigned_dev_kernel *match;
444 unsigned long host_irq_type, guest_irq_type; 447 unsigned long host_irq_type, guest_irq_type;
445 448
446 if (!capable(CAP_SYS_RAWIO))
447 return -EPERM;
448
449 if (!irqchip_in_kernel(kvm)) 449 if (!irqchip_in_kernel(kvm))
450 return r; 450 return r;
451 451
@@ -504,12 +504,12 @@ out:
504static int kvm_vm_ioctl_assign_device(struct kvm *kvm, 504static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
505 struct kvm_assigned_pci_dev *assigned_dev) 505 struct kvm_assigned_pci_dev *assigned_dev)
506{ 506{
507 int r = 0; 507 int r = 0, idx;
508 struct kvm_assigned_dev_kernel *match; 508 struct kvm_assigned_dev_kernel *match;
509 struct pci_dev *dev; 509 struct pci_dev *dev;
510 510
511 mutex_lock(&kvm->lock); 511 mutex_lock(&kvm->lock);
512 down_read(&kvm->slots_lock); 512 idx = srcu_read_lock(&kvm->srcu);
513 513
514 match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, 514 match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
515 assigned_dev->assigned_dev_id); 515 assigned_dev->assigned_dev_id);
@@ -526,7 +526,8 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
526 r = -ENOMEM; 526 r = -ENOMEM;
527 goto out; 527 goto out;
528 } 528 }
529 dev = pci_get_bus_and_slot(assigned_dev->busnr, 529 dev = pci_get_domain_bus_and_slot(assigned_dev->segnr,
530 assigned_dev->busnr,
530 assigned_dev->devfn); 531 assigned_dev->devfn);
531 if (!dev) { 532 if (!dev) {
532 printk(KERN_INFO "%s: host device not found\n", __func__); 533 printk(KERN_INFO "%s: host device not found\n", __func__);
@@ -548,6 +549,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
548 pci_reset_function(dev); 549 pci_reset_function(dev);
549 550
550 match->assigned_dev_id = assigned_dev->assigned_dev_id; 551 match->assigned_dev_id = assigned_dev->assigned_dev_id;
552 match->host_segnr = assigned_dev->segnr;
551 match->host_busnr = assigned_dev->busnr; 553 match->host_busnr = assigned_dev->busnr;
552 match->host_devfn = assigned_dev->devfn; 554 match->host_devfn = assigned_dev->devfn;
553 match->flags = assigned_dev->flags; 555 match->flags = assigned_dev->flags;
@@ -573,7 +575,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
573 } 575 }
574 576
575out: 577out:
576 up_read(&kvm->slots_lock); 578 srcu_read_unlock(&kvm->srcu, idx);
577 mutex_unlock(&kvm->lock); 579 mutex_unlock(&kvm->lock);
578 return r; 580 return r;
579out_list_del: 581out_list_del:
@@ -585,7 +587,7 @@ out_put:
585 pci_dev_put(dev); 587 pci_dev_put(dev);
586out_free: 588out_free:
587 kfree(match); 589 kfree(match);
588 up_read(&kvm->slots_lock); 590 srcu_read_unlock(&kvm->srcu, idx);
589 mutex_unlock(&kvm->lock); 591 mutex_unlock(&kvm->lock);
590 return r; 592 return r;
591} 593}