aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/kvm_main.c
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2009-04-29 22:58:42 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:32:43 -0400
commit968a6347936f9421b5bc5358b579e811c52726bc (patch)
tree0067fd4925db6763c701d9534e54b4b61be1712d /virt/kvm/kvm_main.c
parent017cb99e875f2d8ff375cbb576c794b081cd0bd5 (diff)
KVM: No disable_irq for MSI/MSI-X interrupt on device assignment
Disable interrupt at interrupt handler and enable it when guest ack is for the level triggered interrupt, to prevent reinjected interrupt. MSI/MSI-X don't need it. One possible problem is multiply same vector interrupt injected between irq handler and scheduled work handler would be merged as one for MSI/MSI-X. But AFAIK, the drivers handle it well. The patch fixed the oplin card performance issue(MSI-X performance is half of MSI/INTx). Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r--virt/kvm/kvm_main.c22
1 files changed, 8 insertions, 14 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index dee321e58894..2d9bc439d9a9 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -120,7 +120,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
120{ 120{
121 struct kvm_assigned_dev_kernel *assigned_dev; 121 struct kvm_assigned_dev_kernel *assigned_dev;
122 struct kvm *kvm; 122 struct kvm *kvm;
123 int irq, i; 123 int i;
124 124
125 assigned_dev = container_of(work, struct kvm_assigned_dev_kernel, 125 assigned_dev = container_of(work, struct kvm_assigned_dev_kernel,
126 interrupt_work); 126 interrupt_work);
@@ -143,20 +143,10 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
143 kvm_set_irq(assigned_dev->kvm, 143 kvm_set_irq(assigned_dev->kvm,
144 assigned_dev->irq_source_id, 144 assigned_dev->irq_source_id,
145 guest_entries[i].vector, 1); 145 guest_entries[i].vector, 1);
146 irq = assigned_dev->host_msix_entries[i].vector;
147 if (irq != 0)
148 enable_irq(irq);
149 assigned_dev->host_irq_disabled = false;
150 } 146 }
151 } else { 147 } else
152 kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id, 148 kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
153 assigned_dev->guest_irq, 1); 149 assigned_dev->guest_irq, 1);
154 if (assigned_dev->irq_requested_type &
155 KVM_DEV_IRQ_GUEST_MSI) {
156 enable_irq(assigned_dev->host_irq);
157 assigned_dev->host_irq_disabled = false;
158 }
159 }
160 150
161 spin_unlock_irq(&assigned_dev->assigned_dev_lock); 151 spin_unlock_irq(&assigned_dev->assigned_dev_lock);
162 mutex_unlock(&assigned_dev->kvm->lock); 152 mutex_unlock(&assigned_dev->kvm->lock);
@@ -179,8 +169,10 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
179 169
180 schedule_work(&assigned_dev->interrupt_work); 170 schedule_work(&assigned_dev->interrupt_work);
181 171
182 disable_irq_nosync(irq); 172 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_GUEST_INTX) {
183 assigned_dev->host_irq_disabled = true; 173 disable_irq_nosync(irq);
174 assigned_dev->host_irq_disabled = true;
175 }
184 176
185out: 177out:
186 spin_unlock_irqrestore(&assigned_dev->assigned_dev_lock, flags); 178 spin_unlock_irqrestore(&assigned_dev->assigned_dev_lock, flags);
@@ -417,6 +409,7 @@ static int assigned_device_enable_guest_msi(struct kvm *kvm,
417{ 409{
418 dev->guest_irq = irq->guest_irq; 410 dev->guest_irq = irq->guest_irq;
419 dev->ack_notifier.gsi = -1; 411 dev->ack_notifier.gsi = -1;
412 dev->host_irq_disabled = false;
420 return 0; 413 return 0;
421} 414}
422#endif 415#endif
@@ -427,6 +420,7 @@ static int assigned_device_enable_guest_msix(struct kvm *kvm,
427{ 420{
428 dev->guest_irq = irq->guest_irq; 421 dev->guest_irq = irq->guest_irq;
429 dev->ack_notifier.gsi = -1; 422 dev->ack_notifier.gsi = -1;
423 dev->host_irq_disabled = false;
430 return 0; 424 return 0;
431} 425}
432#endif 426#endif