root/arch/powerpc/sysdev/xics/ics-rtas.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ics_rtas_unmask_irq
  2. ics_rtas_startup
  3. ics_rtas_mask_real_irq
  4. ics_rtas_mask_irq
  5. ics_rtas_set_affinity
  6. ics_rtas_map
  7. ics_rtas_mask_unknown
  8. ics_rtas_get_server
  9. ics_rtas_host_match
  10. ics_rtas_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/types.h>
   3 #include <linux/kernel.h>
   4 #include <linux/irq.h>
   5 #include <linux/smp.h>
   6 #include <linux/interrupt.h>
   7 #include <linux/init.h>
   8 #include <linux/cpu.h>
   9 #include <linux/of.h>
  10 #include <linux/spinlock.h>
  11 #include <linux/msi.h>
  12 
  13 #include <asm/prom.h>
  14 #include <asm/smp.h>
  15 #include <asm/machdep.h>
  16 #include <asm/irq.h>
  17 #include <asm/errno.h>
  18 #include <asm/xics.h>
  19 #include <asm/rtas.h>
  20 
  21 /* RTAS service tokens */
  22 static int ibm_get_xive;
  23 static int ibm_set_xive;
  24 static int ibm_int_on;
  25 static int ibm_int_off;
  26 
  27 static int ics_rtas_map(struct ics *ics, unsigned int virq);
  28 static void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec);
  29 static long ics_rtas_get_server(struct ics *ics, unsigned long vec);
  30 static int ics_rtas_host_match(struct ics *ics, struct device_node *node);
  31 
  32 /* Only one global & state struct ics */
  33 static struct ics ics_rtas = {
  34         .map            = ics_rtas_map,
  35         .mask_unknown   = ics_rtas_mask_unknown,
  36         .get_server     = ics_rtas_get_server,
  37         .host_match     = ics_rtas_host_match,
  38 };
  39 
  40 static void ics_rtas_unmask_irq(struct irq_data *d)
  41 {
  42         unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
  43         int call_status;
  44         int server;
  45 
  46         pr_devel("xics: unmask virq %d [hw 0x%x]\n", d->irq, hw_irq);
  47 
  48         if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
  49                 return;
  50 
  51         server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0);
  52 
  53         call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hw_irq, server,
  54                                 DEFAULT_PRIORITY);
  55         if (call_status != 0) {
  56                 printk(KERN_ERR
  57                         "%s: ibm_set_xive irq %u server %x returned %d\n",
  58                         __func__, hw_irq, server, call_status);
  59                 return;
  60         }
  61 
  62         /* Now unmask the interrupt (often a no-op) */
  63         call_status = rtas_call(ibm_int_on, 1, 1, NULL, hw_irq);
  64         if (call_status != 0) {
  65                 printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
  66                         __func__, hw_irq, call_status);
  67                 return;
  68         }
  69 }
  70 
  71 static unsigned int ics_rtas_startup(struct irq_data *d)
  72 {
  73 #ifdef CONFIG_PCI_MSI
  74         /*
  75          * The generic MSI code returns with the interrupt disabled on the
  76          * card, using the MSI mask bits. Firmware doesn't appear to unmask
  77          * at that level, so we do it here by hand.
  78          */
  79         if (irq_data_get_msi_desc(d))
  80                 pci_msi_unmask_irq(d);
  81 #endif
  82         /* unmask it */
  83         ics_rtas_unmask_irq(d);
  84         return 0;
  85 }
  86 
  87 static void ics_rtas_mask_real_irq(unsigned int hw_irq)
  88 {
  89         int call_status;
  90 
  91         if (hw_irq == XICS_IPI)
  92                 return;
  93 
  94         call_status = rtas_call(ibm_int_off, 1, 1, NULL, hw_irq);
  95         if (call_status != 0) {
  96                 printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
  97                         __func__, hw_irq, call_status);
  98                 return;
  99         }
 100 
 101         /* Have to set XIVE to 0xff to be able to remove a slot */
 102         call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hw_irq,
 103                                 xics_default_server, 0xff);
 104         if (call_status != 0) {
 105                 printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
 106                         __func__, hw_irq, call_status);
 107                 return;
 108         }
 109 }
 110 
 111 static void ics_rtas_mask_irq(struct irq_data *d)
 112 {
 113         unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
 114 
 115         pr_devel("xics: mask virq %d [hw 0x%x]\n", d->irq, hw_irq);
 116 
 117         if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
 118                 return;
 119         ics_rtas_mask_real_irq(hw_irq);
 120 }
 121 
 122 static int ics_rtas_set_affinity(struct irq_data *d,
 123                                  const struct cpumask *cpumask,
 124                                  bool force)
 125 {
 126         unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
 127         int status;
 128         int xics_status[2];
 129         int irq_server;
 130 
 131         if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
 132                 return -1;
 133 
 134         status = rtas_call(ibm_get_xive, 1, 3, xics_status, hw_irq);
 135 
 136         if (status) {
 137                 printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
 138                         __func__, hw_irq, status);
 139                 return -1;
 140         }
 141 
 142         irq_server = xics_get_irq_server(d->irq, cpumask, 1);
 143         if (irq_server == -1) {
 144                 pr_warn("%s: No online cpus in the mask %*pb for irq %d\n",
 145                         __func__, cpumask_pr_args(cpumask), d->irq);
 146                 return -1;
 147         }
 148 
 149         status = rtas_call(ibm_set_xive, 3, 1, NULL,
 150                            hw_irq, irq_server, xics_status[1]);
 151 
 152         if (status) {
 153                 printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
 154                         __func__, hw_irq, status);
 155                 return -1;
 156         }
 157 
 158         return IRQ_SET_MASK_OK;
 159 }
 160 
 161 static struct irq_chip ics_rtas_irq_chip = {
 162         .name = "XICS",
 163         .irq_startup = ics_rtas_startup,
 164         .irq_mask = ics_rtas_mask_irq,
 165         .irq_unmask = ics_rtas_unmask_irq,
 166         .irq_eoi = NULL, /* Patched at init time */
 167         .irq_set_affinity = ics_rtas_set_affinity,
 168         .irq_set_type = xics_set_irq_type,
 169         .irq_retrigger = xics_retrigger,
 170 };
 171 
 172 static int ics_rtas_map(struct ics *ics, unsigned int virq)
 173 {
 174         unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
 175         int status[2];
 176         int rc;
 177 
 178         if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
 179                 return -EINVAL;
 180 
 181         /* Check if RTAS knows about this interrupt */
 182         rc = rtas_call(ibm_get_xive, 1, 3, status, hw_irq);
 183         if (rc)
 184                 return -ENXIO;
 185 
 186         irq_set_chip_and_handler(virq, &ics_rtas_irq_chip, handle_fasteoi_irq);
 187         irq_set_chip_data(virq, &ics_rtas);
 188 
 189         return 0;
 190 }
 191 
 192 static void ics_rtas_mask_unknown(struct ics *ics, unsigned long vec)
 193 {
 194         ics_rtas_mask_real_irq(vec);
 195 }
 196 
 197 static long ics_rtas_get_server(struct ics *ics, unsigned long vec)
 198 {
 199         int rc, status[2];
 200 
 201         rc = rtas_call(ibm_get_xive, 1, 3, status, vec);
 202         if (rc)
 203                 return -1;
 204         return status[0];
 205 }
 206 
 207 static int ics_rtas_host_match(struct ics *ics, struct device_node *node)
 208 {
 209         /* IBM machines have interrupt parents of various funky types for things
 210          * like vdevices, events, etc... The trick we use here is to match
 211          * everything here except the legacy 8259 which is compatible "chrp,iic"
 212          */
 213         return !of_device_is_compatible(node, "chrp,iic");
 214 }
 215 
 216 __init int ics_rtas_init(void)
 217 {
 218         ibm_get_xive = rtas_token("ibm,get-xive");
 219         ibm_set_xive = rtas_token("ibm,set-xive");
 220         ibm_int_on  = rtas_token("ibm,int-on");
 221         ibm_int_off = rtas_token("ibm,int-off");
 222 
 223         /* We enable the RTAS "ICS" if RTAS is present with the
 224          * appropriate tokens
 225          */
 226         if (ibm_get_xive == RTAS_UNKNOWN_SERVICE ||
 227             ibm_set_xive == RTAS_UNKNOWN_SERVICE)
 228                 return -ENODEV;
 229 
 230         /* We need to patch our irq chip's EOI to point to the
 231          * right ICP
 232          */
 233         ics_rtas_irq_chip.irq_eoi = icp_ops->eoi;
 234 
 235         /* Register ourselves */
 236         xics_register_ics(&ics_rtas);
 237 
 238         return 0;
 239 }
 240 

/* [<][>][^][v][top][bottom][index][help] */