diff options
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 15 |
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 | ||
203 | static void kvm_free_assigned_irq(struct kvm *kvm, | 216 | static void kvm_free_assigned_irq(struct kvm *kvm, |