sparc64: Always allocate the send mondo blocks, even on non-sun4v.
[firefly-linux-kernel-4.4.55.git] / arch / sparc64 / kernel / irq.c
index eb88bd6e674ef7e05a1af6480539e99b860c62cb..ba43d85e8dded537cfeb4a23c510456e4f2c956f 100644 (file)
@@ -1,6 +1,6 @@
 /* irq.c: UltraSparc IRQ handling/init/registry.
  *
- * Copyright (C) 1997, 2007  David S. Miller  (davem@davemloft.net)
+ * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1998  Eddie C. Dost    (ecd@skynet.be)
  * Copyright (C) 1998  Jakub Jelinek    (jj@ultra.linux.cz)
  */
@@ -308,6 +308,7 @@ static void sun4u_irq_enable(unsigned int virt_irq)
                         IMAP_AID_SAFARI | IMAP_NID_SAFARI);
                val |= tid | IMAP_VALID;
                upa_writeq(val, imap);
+               upa_writeq(ICLR_IDLE, data->iclr);
        }
 }
 
@@ -620,8 +621,9 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
 unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 {
        struct irq_handler_data *data;
-       struct ino_bucket *bucket;
        unsigned long hv_err, cookie;
+       struct ino_bucket *bucket;
+       struct irq_desc *desc;
        unsigned int virt_irq;
 
        bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
@@ -642,6 +644,13 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
        if (unlikely(!data))
                return 0;
 
+       /* In order to make the LDC channel startup sequence easier,
+        * especially wrt. locking, we do not let request_irq() enable
+        * the interrupt.
+        */
+       desc = irq_desc + virt_irq;
+       desc->status |= IRQ_NOAUTOEN;
+
        set_irq_chip_data(virt_irq, data);
 
        /* Catch accidental accesses to these things.  IMAP/ICLR handling
@@ -906,12 +915,18 @@ static void __init sun4v_init_mondo_queues(void)
                alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask);
                alloc_one_kbuf(&tb->nonresum_kernel_buf_pa,
                               tb->nonresum_qmask);
+       }
+}
+
+static void __init init_send_mondo_info(void)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               struct trap_per_cpu *tb = &trap_block[cpu];
 
                init_cpu_send_mondo_info(tb);
        }
-
-       /* Load up the boot cpu's entries.  */
-       sun4v_register_mondo_queues(hard_smp_processor_id());
 }
 
 static struct irqaction timer_irq_action = {
@@ -940,6 +955,13 @@ void __init init_IRQ(void)
        if (tlb_type == hypervisor)
                sun4v_init_mondo_queues();
 
+       init_send_mondo_info();
+
+       if (tlb_type == hypervisor) {
+               /* Load up the boot cpu's entries.  */
+               sun4v_register_mondo_queues(hard_smp_processor_id());
+       }
+
        /* We need to clear any IRQ's pending in the soft interrupt
         * registers, a spurious one could be left around from the
         * PROM timer which we just disabled.