OSDN Git Service

x86/hpet: Enhance HPET IRQ to support hierarchical irqdomains
[uclinux-h8/linux.git] / arch / x86 / kernel / hpet.c
index 3acbff4..e3bc180 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/cpu.h>
 #include <linux/pm.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 
 #include <asm/fixmap.h>
 #include <asm/hpet.h>
@@ -305,8 +306,6 @@ static void hpet_legacy_clockevent_register(void)
        printk(KERN_DEBUG "hpet clockevent registered\n");
 }
 
-static int hpet_setup_msi_irq(unsigned int irq);
-
 static void hpet_set_mode(enum clock_event_mode mode,
                          struct clock_event_device *evt, int timer)
 {
@@ -357,7 +356,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
                        hpet_enable_legacy_int();
                } else {
                        struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-                       hpet_setup_msi_irq(hdev->irq);
+                       irq_domain_activate_irq(irq_get_irq_data(hdev->irq));
                        disable_irq(hdev->irq);
                        irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
                        enable_irq(hdev->irq);
@@ -423,6 +422,7 @@ static int hpet_legacy_next_event(unsigned long delta,
 
 static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
 static struct hpet_dev *hpet_devs;
+static struct irq_domain *hpet_domain;
 
 void hpet_msi_unmask(struct irq_data *data)
 {
@@ -473,31 +473,6 @@ static int hpet_msi_next_event(unsigned long delta,
        return hpet_next_event(delta, evt, hdev->num);
 }
 
-static int hpet_setup_msi_irq(unsigned int irq)
-{
-       if (x86_msi.setup_hpet_msi(irq, hpet_blockid)) {
-               irq_free_hwirq(irq);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int hpet_assign_irq(struct hpet_dev *dev)
-{
-       unsigned int irq = irq_alloc_hwirq(-1);
-
-       if (!irq)
-               return -EINVAL;
-
-       irq_set_handler_data(irq, dev);
-
-       if (hpet_setup_msi_irq(irq))
-               return -EINVAL;
-
-       dev->irq = irq;
-       return 0;
-}
-
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
        struct hpet_dev *dev = (struct hpet_dev *)data;
@@ -540,9 +515,6 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
        if (!(hdev->flags & HPET_DEV_VALID))
                return;
 
-       if (hpet_setup_msi_irq(hdev->irq))
-               return;
-
        hdev->cpu = cpu;
        per_cpu(cpu_hpet_dev, cpu) = hdev;
        evt->name = hdev->name;
@@ -574,7 +546,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
        unsigned int id;
        unsigned int num_timers;
        unsigned int num_timers_used = 0;
-       int i;
+       int i, irq;
 
        if (hpet_msi_disable)
                return;
@@ -587,6 +559,10 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
        num_timers++; /* Value read out starts from 0 */
        hpet_print_config();
 
+       hpet_domain = hpet_create_irq_domain(hpet_blockid);
+       if (!hpet_domain)
+               return;
+
        hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL);
        if (!hpet_devs)
                return;
@@ -601,15 +577,16 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
                if (!(cfg & HPET_TN_FSB_CAP))
                        continue;
 
+               irq = hpet_assign_irq(hpet_domain, hdev, hdev->num);
+               if (irq < 0)
+                       continue;
+
+               sprintf(hdev->name, "hpet%d", i);
+               hdev->num = i;
+               hdev->irq = irq;
                hdev->flags = 0;
                if (cfg & HPET_TN_PERIODIC_CAP)
                        hdev->flags |= HPET_DEV_PERI_CAP;
-               hdev->num = i;
-
-               sprintf(hdev->name, "hpet%d", i);
-               if (hpet_assign_irq(hdev))
-                       continue;
-
                hdev->flags |= HPET_DEV_FSB_CAP;
                hdev->flags |= HPET_DEV_VALID;
                num_timers_used++;
@@ -709,10 +686,6 @@ static int hpet_cpuhp_notify(struct notifier_block *n,
 }
 #else
 
-static int hpet_setup_msi_irq(unsigned int irq)
-{
-       return 0;
-}
 static void hpet_msi_capability_lookup(unsigned int start_timer)
 {
        return;