aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/kvm_host.h1
-rw-r--r--virt/kvm/kvm_main.c15
2 files changed, 15 insertions, 1 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 8091a4d90ddf..eafabd5c66b2 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -307,6 +307,7 @@ struct kvm_assigned_dev_kernel {
307 int host_busnr; 307 int host_busnr;
308 int host_devfn; 308 int host_devfn;
309 int host_irq; 309 int host_irq;
310 bool host_irq_disabled;
310 int guest_irq; 311 int guest_irq;
311 struct msi_msg guest_msi; 312 struct msi_msg guest_msi;
312#define KVM_ASSIGNED_DEV_GUEST_INTX (1 << 0) 313#define KVM_ASSIGNED_DEV_GUEST_INTX (1 << 0)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index eb70ca6c7145..fc6127cbea1f 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -170,6 +170,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
170 KVM_ASSIGNED_DEV_GUEST_MSI) { 170 KVM_ASSIGNED_DEV_GUEST_MSI) {
171 assigned_device_msi_dispatch(assigned_dev); 171 assigned_device_msi_dispatch(assigned_dev);
172 enable_irq(assigned_dev->host_irq); 172 enable_irq(assigned_dev->host_irq);
173 assigned_dev->host_irq_disabled = false;
173 } 174 }
174 mutex_unlock(&assigned_dev->kvm->lock); 175 mutex_unlock(&assigned_dev->kvm->lock);
175 kvm_put_kvm(assigned_dev->kvm); 176 kvm_put_kvm(assigned_dev->kvm);
@@ -181,8 +182,12 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
181 (struct kvm_assigned_dev_kernel *) dev_id; 182 (struct kvm_assigned_dev_kernel *) dev_id;
182 183
183 kvm_get_kvm(assigned_dev->kvm); 184 kvm_get_kvm(assigned_dev->kvm);
185
184 schedule_work(&assigned_dev->interrupt_work); 186 schedule_work(&assigned_dev->interrupt_work);
187
185 disable_irq_nosync(irq); 188 disable_irq_nosync(irq);
189 assigned_dev->host_irq_disabled = true;
190
186 return IRQ_HANDLED; 191 return IRQ_HANDLED;
187} 192}
188 193
@@ -196,8 +201,16 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
196 201
197 dev = container_of(kian, struct kvm_assigned_dev_kernel, 202 dev = container_of(kian, struct kvm_assigned_dev_kernel,
198 ack_notifier); 203 ack_notifier);
204
199 kvm_set_irq(dev->kvm, dev->irq_source_id, dev->guest_irq, 0); 205 kvm_set_irq(dev->kvm, dev->irq_source_id, dev->guest_irq, 0);
200 enable_irq(dev->host_irq); 206
207 /* The guest irq may be shared so this ack may be
208 * from another device.
209 */
210 if (dev->host_irq_disabled) {
211 enable_irq(dev->host_irq);
212 dev->host_irq_disabled = false;
213 }
201} 214}
202 215
203static void kvm_free_assigned_irq(struct kvm *kvm, 216static void kvm_free_assigned_irq(struct kvm *kvm,