]> Pileus Git - ~andy/linux/blobdiff - virt/kvm/irq_comm.c
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi...
[~andy/linux] / virt / kvm / irq_comm.c
index 656fa455e154abedceba3883cf865adfa73f873b..e9073cf4d0406c0faaec2faf0d87015f962494ad 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/kvm_host.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <trace/events/kvm.h>
 
 #include <asm/msidef.h>
@@ -172,7 +173,6 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level)
        struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS];
        int ret = -1, i = 0;
        struct kvm_irq_routing_table *irq_rt;
-       struct hlist_node *n;
 
        trace_kvm_set_irq(irq, level, irq_source_id);
 
@@ -183,7 +183,7 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level)
        rcu_read_lock();
        irq_rt = rcu_dereference(kvm->irq_routing);
        if (irq < irq_rt->nr_rt_entries)
-               hlist_for_each_entry(e, n, &irq_rt->map[irq], link)
+               hlist_for_each_entry(e, &irq_rt->map[irq], link)
                        irq_set[i++] = *e;
        rcu_read_unlock();
 
@@ -211,7 +211,6 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
        struct kvm_kernel_irq_routing_entry *e;
        int ret = -EINVAL;
        struct kvm_irq_routing_table *irq_rt;
-       struct hlist_node *n;
 
        trace_kvm_set_irq(irq, level, irq_source_id);
 
@@ -226,7 +225,7 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
        rcu_read_lock();
        irq_rt = rcu_dereference(kvm->irq_routing);
        if (irq < irq_rt->nr_rt_entries)
-               hlist_for_each_entry(e, n, &irq_rt->map[irq], link) {
+               hlist_for_each_entry(e, &irq_rt->map[irq], link) {
                        if (likely(e->type == KVM_IRQ_ROUTING_MSI))
                                ret = kvm_set_msi_inatomic(e, kvm);
                        else
@@ -237,10 +236,30 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
        return ret;
 }
 
+bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin)
+{
+       struct kvm_irq_ack_notifier *kian;
+       int gsi;
+
+       rcu_read_lock();
+       gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin];
+       if (gsi != -1)
+               hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
+                                        link)
+                       if (kian->gsi == gsi) {
+                               rcu_read_unlock();
+                               return true;
+                       }
+
+       rcu_read_unlock();
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(kvm_irq_has_notifier);
+
 void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
 {
        struct kvm_irq_ack_notifier *kian;
-       struct hlist_node *n;
        int gsi;
 
        trace_kvm_ack_irq(irqchip, pin);
@@ -248,7 +267,7 @@ void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
        rcu_read_lock();
        gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin];
        if (gsi != -1)
-               hlist_for_each_entry_rcu(kian, n, &kvm->irq_ack_notifier_list,
+               hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
                                         link)
                        if (kian->gsi == gsi)
                                kian->irq_acked(kian);
@@ -261,6 +280,7 @@ void kvm_register_irq_ack_notifier(struct kvm *kvm,
        mutex_lock(&kvm->irq_lock);
        hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list);
        mutex_unlock(&kvm->irq_lock);
+       kvm_ioapic_make_eoibitmap_request(kvm);
 }
 
 void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
@@ -270,6 +290,7 @@ void kvm_unregister_irq_ack_notifier(struct kvm *kvm,
        hlist_del_init_rcu(&kian->link);
        mutex_unlock(&kvm->irq_lock);
        synchronize_rcu();
+       kvm_ioapic_make_eoibitmap_request(kvm);
 }
 
 int kvm_request_irq_source_id(struct kvm *kvm)
@@ -344,13 +365,12 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
                             bool mask)
 {
        struct kvm_irq_mask_notifier *kimn;
-       struct hlist_node *n;
        int gsi;
 
        rcu_read_lock();
        gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin];
        if (gsi != -1)
-               hlist_for_each_entry_rcu(kimn, n, &kvm->mask_notifier_list, link)
+               hlist_for_each_entry_rcu(kimn, &kvm->mask_notifier_list, link)
                        if (kimn->irq == gsi)
                                kimn->func(kimn, mask);
        rcu_read_unlock();
@@ -371,13 +391,12 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
        int delta;
        unsigned max_pin;
        struct kvm_kernel_irq_routing_entry *ei;
-       struct hlist_node *n;
 
        /*
         * Do not allow GSI to be mapped to the same irqchip more than once.
         * Allow only one to one mapping between GSI and MSI.
         */
-       hlist_for_each_entry(ei, n, &rt->map[ue->gsi], link)
+       hlist_for_each_entry(ei, &rt->map[ue->gsi], link)
                if (ei->type == KVM_IRQ_ROUTING_MSI ||
                    ue->type == KVM_IRQ_ROUTING_MSI ||
                    ue->u.irqchip.irqchip == ei->irqchip.irqchip)