1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2013-2017 ARM Limited, All Rights Reserved.
4*4882a593Smuzhiyun * Author: Marc Zyngier <marc.zyngier@arm.com>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/acpi.h>
8*4882a593Smuzhiyun #include <linux/acpi_iort.h>
9*4882a593Smuzhiyun #include <linux/bitfield.h>
10*4882a593Smuzhiyun #include <linux/bitmap.h>
11*4882a593Smuzhiyun #include <linux/cpu.h>
12*4882a593Smuzhiyun #include <linux/crash_dump.h>
13*4882a593Smuzhiyun #include <linux/delay.h>
14*4882a593Smuzhiyun #include <linux/dma-iommu.h>
15*4882a593Smuzhiyun #include <linux/efi.h>
16*4882a593Smuzhiyun #include <linux/interrupt.h>
17*4882a593Smuzhiyun #include <linux/iopoll.h>
18*4882a593Smuzhiyun #include <linux/irqdomain.h>
19*4882a593Smuzhiyun #include <linux/list.h>
20*4882a593Smuzhiyun #include <linux/log2.h>
21*4882a593Smuzhiyun #include <linux/memblock.h>
22*4882a593Smuzhiyun #include <linux/mm.h>
23*4882a593Smuzhiyun #include <linux/msi.h>
24*4882a593Smuzhiyun #include <linux/of.h>
25*4882a593Smuzhiyun #include <linux/of_address.h>
26*4882a593Smuzhiyun #include <linux/of_irq.h>
27*4882a593Smuzhiyun #include <linux/of_pci.h>
28*4882a593Smuzhiyun #include <linux/of_platform.h>
29*4882a593Smuzhiyun #include <linux/percpu.h>
30*4882a593Smuzhiyun #include <linux/slab.h>
31*4882a593Smuzhiyun #include <linux/syscore_ops.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include <linux/irqchip.h>
34*4882a593Smuzhiyun #include <linux/irqchip/arm-gic-v3.h>
35*4882a593Smuzhiyun #include <linux/irqchip/arm-gic-v4.h>
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #include <asm/cputype.h>
38*4882a593Smuzhiyun #include <asm/exception.h>
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #include "irq-gic-common.h"
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0)
43*4882a593Smuzhiyun #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
44*4882a593Smuzhiyun #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
47*4882a593Smuzhiyun #define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1)
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun static u32 lpi_id_bits;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun /*
52*4882a593Smuzhiyun * We allocate memory for PROPBASE to cover 2 ^ lpi_id_bits LPIs to
53*4882a593Smuzhiyun * deal with (one configuration byte per interrupt). PENDBASE has to
54*4882a593Smuzhiyun * be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
55*4882a593Smuzhiyun */
56*4882a593Smuzhiyun #define LPI_NRBITS lpi_id_bits
57*4882a593Smuzhiyun #define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K)
58*4882a593Smuzhiyun #define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun #define LPI_PROP_DEFAULT_PRIO GICD_INT_DEF_PRI
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /*
63*4882a593Smuzhiyun * Collection structure - just an ID, and a redistributor address to
64*4882a593Smuzhiyun * ping. We use one per CPU as a bag of interrupts assigned to this
65*4882a593Smuzhiyun * CPU.
66*4882a593Smuzhiyun */
67*4882a593Smuzhiyun struct its_collection {
68*4882a593Smuzhiyun u64 target_address;
69*4882a593Smuzhiyun u16 col_id;
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /*
73*4882a593Smuzhiyun * The ITS_BASER structure - contains memory information, cached
74*4882a593Smuzhiyun * value of BASER register configuration and ITS page size.
75*4882a593Smuzhiyun */
76*4882a593Smuzhiyun struct its_baser {
77*4882a593Smuzhiyun void *base;
78*4882a593Smuzhiyun u64 val;
79*4882a593Smuzhiyun u32 order;
80*4882a593Smuzhiyun u32 psz;
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun struct its_device;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /*
86*4882a593Smuzhiyun * The ITS structure - contains most of the infrastructure, with the
87*4882a593Smuzhiyun * top-level MSI domain, the command queue, the collections, and the
88*4882a593Smuzhiyun * list of devices writing to it.
89*4882a593Smuzhiyun *
90*4882a593Smuzhiyun * dev_alloc_lock has to be taken for device allocations, while the
91*4882a593Smuzhiyun * spinlock must be taken to parse data structures such as the device
92*4882a593Smuzhiyun * list.
93*4882a593Smuzhiyun */
94*4882a593Smuzhiyun struct its_node {
95*4882a593Smuzhiyun raw_spinlock_t lock;
96*4882a593Smuzhiyun struct mutex dev_alloc_lock;
97*4882a593Smuzhiyun struct list_head entry;
98*4882a593Smuzhiyun void __iomem *base;
99*4882a593Smuzhiyun void __iomem *sgir_base;
100*4882a593Smuzhiyun phys_addr_t phys_base;
101*4882a593Smuzhiyun struct its_cmd_block *cmd_base;
102*4882a593Smuzhiyun struct its_cmd_block *cmd_write;
103*4882a593Smuzhiyun struct its_baser tables[GITS_BASER_NR_REGS];
104*4882a593Smuzhiyun struct its_collection *collections;
105*4882a593Smuzhiyun struct fwnode_handle *fwnode_handle;
106*4882a593Smuzhiyun u64 (*get_msi_base)(struct its_device *its_dev);
107*4882a593Smuzhiyun u64 typer;
108*4882a593Smuzhiyun u64 cbaser_save;
109*4882a593Smuzhiyun u32 ctlr_save;
110*4882a593Smuzhiyun u32 mpidr;
111*4882a593Smuzhiyun struct list_head its_device_list;
112*4882a593Smuzhiyun u64 flags;
113*4882a593Smuzhiyun unsigned long list_nr;
114*4882a593Smuzhiyun int numa_node;
115*4882a593Smuzhiyun unsigned int msi_domain_flags;
116*4882a593Smuzhiyun u32 pre_its_base; /* for Socionext Synquacer */
117*4882a593Smuzhiyun int vlpi_redist_offset;
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun #define is_v4(its) (!!((its)->typer & GITS_TYPER_VLPIS))
121*4882a593Smuzhiyun #define is_v4_1(its) (!!((its)->typer & GITS_TYPER_VMAPP))
122*4882a593Smuzhiyun #define device_ids(its) (FIELD_GET(GITS_TYPER_DEVBITS, (its)->typer) + 1)
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun #define ITS_ITT_ALIGN SZ_256
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /* The maximum number of VPEID bits supported by VLPI commands */
127*4882a593Smuzhiyun #define ITS_MAX_VPEID_BITS \
128*4882a593Smuzhiyun ({ \
129*4882a593Smuzhiyun int nvpeid = 16; \
130*4882a593Smuzhiyun if (gic_rdists->has_rvpeid && \
131*4882a593Smuzhiyun gic_rdists->gicd_typer2 & GICD_TYPER2_VIL) \
132*4882a593Smuzhiyun nvpeid = 1 + (gic_rdists->gicd_typer2 & \
133*4882a593Smuzhiyun GICD_TYPER2_VID); \
134*4882a593Smuzhiyun \
135*4882a593Smuzhiyun nvpeid; \
136*4882a593Smuzhiyun })
137*4882a593Smuzhiyun #define ITS_MAX_VPEID (1 << (ITS_MAX_VPEID_BITS))
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* Convert page order to size in bytes */
140*4882a593Smuzhiyun #define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o))
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun struct event_lpi_map {
143*4882a593Smuzhiyun unsigned long *lpi_map;
144*4882a593Smuzhiyun u16 *col_map;
145*4882a593Smuzhiyun irq_hw_number_t lpi_base;
146*4882a593Smuzhiyun int nr_lpis;
147*4882a593Smuzhiyun raw_spinlock_t vlpi_lock;
148*4882a593Smuzhiyun struct its_vm *vm;
149*4882a593Smuzhiyun struct its_vlpi_map *vlpi_maps;
150*4882a593Smuzhiyun int nr_vlpis;
151*4882a593Smuzhiyun };
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /*
154*4882a593Smuzhiyun * The ITS view of a device - belongs to an ITS, owns an interrupt
155*4882a593Smuzhiyun * translation table, and a list of interrupts. If it some of its
156*4882a593Smuzhiyun * LPIs are injected into a guest (GICv4), the event_map.vm field
157*4882a593Smuzhiyun * indicates which one.
158*4882a593Smuzhiyun */
159*4882a593Smuzhiyun struct its_device {
160*4882a593Smuzhiyun struct list_head entry;
161*4882a593Smuzhiyun struct its_node *its;
162*4882a593Smuzhiyun struct event_lpi_map event_map;
163*4882a593Smuzhiyun void *itt;
164*4882a593Smuzhiyun u32 itt_sz;
165*4882a593Smuzhiyun u32 nr_ites;
166*4882a593Smuzhiyun u32 device_id;
167*4882a593Smuzhiyun bool shared;
168*4882a593Smuzhiyun };
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun static struct {
171*4882a593Smuzhiyun raw_spinlock_t lock;
172*4882a593Smuzhiyun struct its_device *dev;
173*4882a593Smuzhiyun struct its_vpe **vpes;
174*4882a593Smuzhiyun int next_victim;
175*4882a593Smuzhiyun } vpe_proxy;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun struct cpu_lpi_count {
178*4882a593Smuzhiyun atomic_t managed;
179*4882a593Smuzhiyun atomic_t unmanaged;
180*4882a593Smuzhiyun };
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun static DEFINE_PER_CPU(struct cpu_lpi_count, cpu_lpi_count);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun static LIST_HEAD(its_nodes);
185*4882a593Smuzhiyun static DEFINE_RAW_SPINLOCK(its_lock);
186*4882a593Smuzhiyun static struct rdists *gic_rdists;
187*4882a593Smuzhiyun static struct irq_domain *its_parent;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun static unsigned long its_list_map;
190*4882a593Smuzhiyun static u16 vmovp_seq_num;
191*4882a593Smuzhiyun static DEFINE_RAW_SPINLOCK(vmovp_lock);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun static DEFINE_IDA(its_vpeid_ida);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun #define gic_data_rdist() (raw_cpu_ptr(gic_rdists->rdist))
196*4882a593Smuzhiyun #define gic_data_rdist_cpu(cpu) (per_cpu_ptr(gic_rdists->rdist, cpu))
197*4882a593Smuzhiyun #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
198*4882a593Smuzhiyun #define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K)
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun /*
201*4882a593Smuzhiyun * Skip ITSs that have no vLPIs mapped, unless we're on GICv4.1, as we
202*4882a593Smuzhiyun * always have vSGIs mapped.
203*4882a593Smuzhiyun */
require_its_list_vmovp(struct its_vm * vm,struct its_node * its)204*4882a593Smuzhiyun static bool require_its_list_vmovp(struct its_vm *vm, struct its_node *its)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun return (gic_rdists->has_rvpeid || vm->vlpi_count[its->list_nr]);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
get_its_list(struct its_vm * vm)209*4882a593Smuzhiyun static u16 get_its_list(struct its_vm *vm)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun struct its_node *its;
212*4882a593Smuzhiyun unsigned long its_list = 0;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
215*4882a593Smuzhiyun if (!is_v4(its))
216*4882a593Smuzhiyun continue;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun if (require_its_list_vmovp(vm, its))
219*4882a593Smuzhiyun __set_bit(its->list_nr, &its_list);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun return (u16)its_list;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
its_get_event_id(struct irq_data * d)225*4882a593Smuzhiyun static inline u32 its_get_event_id(struct irq_data *d)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
228*4882a593Smuzhiyun return d->hwirq - its_dev->event_map.lpi_base;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
dev_event_to_col(struct its_device * its_dev,u32 event)231*4882a593Smuzhiyun static struct its_collection *dev_event_to_col(struct its_device *its_dev,
232*4882a593Smuzhiyun u32 event)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun struct its_node *its = its_dev->its;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun return its->collections + its_dev->event_map.col_map[event];
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
dev_event_to_vlpi_map(struct its_device * its_dev,u32 event)239*4882a593Smuzhiyun static struct its_vlpi_map *dev_event_to_vlpi_map(struct its_device *its_dev,
240*4882a593Smuzhiyun u32 event)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun if (WARN_ON_ONCE(event >= its_dev->event_map.nr_lpis))
243*4882a593Smuzhiyun return NULL;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun return &its_dev->event_map.vlpi_maps[event];
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
get_vlpi_map(struct irq_data * d)248*4882a593Smuzhiyun static struct its_vlpi_map *get_vlpi_map(struct irq_data *d)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun if (irqd_is_forwarded_to_vcpu(d)) {
251*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
252*4882a593Smuzhiyun u32 event = its_get_event_id(d);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun return dev_event_to_vlpi_map(its_dev, event);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun return NULL;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
vpe_to_cpuid_lock(struct its_vpe * vpe,unsigned long * flags)260*4882a593Smuzhiyun static int vpe_to_cpuid_lock(struct its_vpe *vpe, unsigned long *flags)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun raw_spin_lock_irqsave(&vpe->vpe_lock, *flags);
263*4882a593Smuzhiyun return vpe->col_idx;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
vpe_to_cpuid_unlock(struct its_vpe * vpe,unsigned long flags)266*4882a593Smuzhiyun static void vpe_to_cpuid_unlock(struct its_vpe *vpe, unsigned long flags)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&vpe->vpe_lock, flags);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
irq_to_cpuid_lock(struct irq_data * d,unsigned long * flags)271*4882a593Smuzhiyun static int irq_to_cpuid_lock(struct irq_data *d, unsigned long *flags)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun struct its_vlpi_map *map = get_vlpi_map(d);
274*4882a593Smuzhiyun int cpu;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if (map) {
277*4882a593Smuzhiyun cpu = vpe_to_cpuid_lock(map->vpe, flags);
278*4882a593Smuzhiyun } else {
279*4882a593Smuzhiyun /* Physical LPIs are already locked via the irq_desc lock */
280*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
281*4882a593Smuzhiyun cpu = its_dev->event_map.col_map[its_get_event_id(d)];
282*4882a593Smuzhiyun /* Keep GCC quiet... */
283*4882a593Smuzhiyun *flags = 0;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun return cpu;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
irq_to_cpuid_unlock(struct irq_data * d,unsigned long flags)289*4882a593Smuzhiyun static void irq_to_cpuid_unlock(struct irq_data *d, unsigned long flags)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun struct its_vlpi_map *map = get_vlpi_map(d);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun if (map)
294*4882a593Smuzhiyun vpe_to_cpuid_unlock(map->vpe, flags);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
valid_col(struct its_collection * col)297*4882a593Smuzhiyun static struct its_collection *valid_col(struct its_collection *col)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(15, 0)))
300*4882a593Smuzhiyun return NULL;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun return col;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
valid_vpe(struct its_node * its,struct its_vpe * vpe)305*4882a593Smuzhiyun static struct its_vpe *valid_vpe(struct its_node *its, struct its_vpe *vpe)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun if (valid_col(its->collections + vpe->col_idx))
308*4882a593Smuzhiyun return vpe;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun return NULL;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun /*
314*4882a593Smuzhiyun * ITS command descriptors - parameters to be encoded in a command
315*4882a593Smuzhiyun * block.
316*4882a593Smuzhiyun */
317*4882a593Smuzhiyun struct its_cmd_desc {
318*4882a593Smuzhiyun union {
319*4882a593Smuzhiyun struct {
320*4882a593Smuzhiyun struct its_device *dev;
321*4882a593Smuzhiyun u32 event_id;
322*4882a593Smuzhiyun } its_inv_cmd;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun struct {
325*4882a593Smuzhiyun struct its_device *dev;
326*4882a593Smuzhiyun u32 event_id;
327*4882a593Smuzhiyun } its_clear_cmd;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun struct {
330*4882a593Smuzhiyun struct its_device *dev;
331*4882a593Smuzhiyun u32 event_id;
332*4882a593Smuzhiyun } its_int_cmd;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun struct {
335*4882a593Smuzhiyun struct its_device *dev;
336*4882a593Smuzhiyun int valid;
337*4882a593Smuzhiyun } its_mapd_cmd;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun struct {
340*4882a593Smuzhiyun struct its_collection *col;
341*4882a593Smuzhiyun int valid;
342*4882a593Smuzhiyun } its_mapc_cmd;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun struct {
345*4882a593Smuzhiyun struct its_device *dev;
346*4882a593Smuzhiyun u32 phys_id;
347*4882a593Smuzhiyun u32 event_id;
348*4882a593Smuzhiyun } its_mapti_cmd;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun struct {
351*4882a593Smuzhiyun struct its_device *dev;
352*4882a593Smuzhiyun struct its_collection *col;
353*4882a593Smuzhiyun u32 event_id;
354*4882a593Smuzhiyun } its_movi_cmd;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun struct {
357*4882a593Smuzhiyun struct its_device *dev;
358*4882a593Smuzhiyun u32 event_id;
359*4882a593Smuzhiyun } its_discard_cmd;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun struct {
362*4882a593Smuzhiyun struct its_collection *col;
363*4882a593Smuzhiyun } its_invall_cmd;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun struct {
366*4882a593Smuzhiyun struct its_vpe *vpe;
367*4882a593Smuzhiyun } its_vinvall_cmd;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun struct {
370*4882a593Smuzhiyun struct its_vpe *vpe;
371*4882a593Smuzhiyun struct its_collection *col;
372*4882a593Smuzhiyun bool valid;
373*4882a593Smuzhiyun } its_vmapp_cmd;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun struct {
376*4882a593Smuzhiyun struct its_vpe *vpe;
377*4882a593Smuzhiyun struct its_device *dev;
378*4882a593Smuzhiyun u32 virt_id;
379*4882a593Smuzhiyun u32 event_id;
380*4882a593Smuzhiyun bool db_enabled;
381*4882a593Smuzhiyun } its_vmapti_cmd;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun struct {
384*4882a593Smuzhiyun struct its_vpe *vpe;
385*4882a593Smuzhiyun struct its_device *dev;
386*4882a593Smuzhiyun u32 event_id;
387*4882a593Smuzhiyun bool db_enabled;
388*4882a593Smuzhiyun } its_vmovi_cmd;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun struct {
391*4882a593Smuzhiyun struct its_vpe *vpe;
392*4882a593Smuzhiyun struct its_collection *col;
393*4882a593Smuzhiyun u16 seq_num;
394*4882a593Smuzhiyun u16 its_list;
395*4882a593Smuzhiyun } its_vmovp_cmd;
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun struct {
398*4882a593Smuzhiyun struct its_vpe *vpe;
399*4882a593Smuzhiyun } its_invdb_cmd;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun struct {
402*4882a593Smuzhiyun struct its_vpe *vpe;
403*4882a593Smuzhiyun u8 sgi;
404*4882a593Smuzhiyun u8 priority;
405*4882a593Smuzhiyun bool enable;
406*4882a593Smuzhiyun bool group;
407*4882a593Smuzhiyun bool clear;
408*4882a593Smuzhiyun } its_vsgi_cmd;
409*4882a593Smuzhiyun };
410*4882a593Smuzhiyun };
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /*
413*4882a593Smuzhiyun * The ITS command block, which is what the ITS actually parses.
414*4882a593Smuzhiyun */
415*4882a593Smuzhiyun struct its_cmd_block {
416*4882a593Smuzhiyun union {
417*4882a593Smuzhiyun u64 raw_cmd[4];
418*4882a593Smuzhiyun __le64 raw_cmd_le[4];
419*4882a593Smuzhiyun };
420*4882a593Smuzhiyun };
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun #define ITS_CMD_QUEUE_SZ SZ_64K
423*4882a593Smuzhiyun #define ITS_CMD_QUEUE_NR_ENTRIES (ITS_CMD_QUEUE_SZ / sizeof(struct its_cmd_block))
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun typedef struct its_collection *(*its_cmd_builder_t)(struct its_node *,
426*4882a593Smuzhiyun struct its_cmd_block *,
427*4882a593Smuzhiyun struct its_cmd_desc *);
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun typedef struct its_vpe *(*its_cmd_vbuilder_t)(struct its_node *,
430*4882a593Smuzhiyun struct its_cmd_block *,
431*4882a593Smuzhiyun struct its_cmd_desc *);
432*4882a593Smuzhiyun
its_mask_encode(u64 * raw_cmd,u64 val,int h,int l)433*4882a593Smuzhiyun static void its_mask_encode(u64 *raw_cmd, u64 val, int h, int l)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun u64 mask = GENMASK_ULL(h, l);
436*4882a593Smuzhiyun *raw_cmd &= ~mask;
437*4882a593Smuzhiyun *raw_cmd |= (val << l) & mask;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
its_encode_cmd(struct its_cmd_block * cmd,u8 cmd_nr)440*4882a593Smuzhiyun static void its_encode_cmd(struct its_cmd_block *cmd, u8 cmd_nr)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], cmd_nr, 7, 0);
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
its_encode_devid(struct its_cmd_block * cmd,u32 devid)445*4882a593Smuzhiyun static void its_encode_devid(struct its_cmd_block *cmd, u32 devid)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], devid, 63, 32);
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
its_encode_event_id(struct its_cmd_block * cmd,u32 id)450*4882a593Smuzhiyun static void its_encode_event_id(struct its_cmd_block *cmd, u32 id)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[1], id, 31, 0);
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
its_encode_phys_id(struct its_cmd_block * cmd,u32 phys_id)455*4882a593Smuzhiyun static void its_encode_phys_id(struct its_cmd_block *cmd, u32 phys_id)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[1], phys_id, 63, 32);
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
its_encode_size(struct its_cmd_block * cmd,u8 size)460*4882a593Smuzhiyun static void its_encode_size(struct its_cmd_block *cmd, u8 size)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[1], size, 4, 0);
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
its_encode_itt(struct its_cmd_block * cmd,u64 itt_addr)465*4882a593Smuzhiyun static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 51, 8);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
its_encode_valid(struct its_cmd_block * cmd,int valid)470*4882a593Smuzhiyun static void its_encode_valid(struct its_cmd_block *cmd, int valid)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[2], !!valid, 63, 63);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
its_encode_target(struct its_cmd_block * cmd,u64 target_addr)475*4882a593Smuzhiyun static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 51, 16);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
its_encode_collection(struct its_cmd_block * cmd,u16 col)480*4882a593Smuzhiyun static void its_encode_collection(struct its_cmd_block *cmd, u16 col)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[2], col, 15, 0);
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
its_encode_vpeid(struct its_cmd_block * cmd,u16 vpeid)485*4882a593Smuzhiyun static void its_encode_vpeid(struct its_cmd_block *cmd, u16 vpeid)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[1], vpeid, 47, 32);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
its_encode_virt_id(struct its_cmd_block * cmd,u32 virt_id)490*4882a593Smuzhiyun static void its_encode_virt_id(struct its_cmd_block *cmd, u32 virt_id)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[2], virt_id, 31, 0);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
its_encode_db_phys_id(struct its_cmd_block * cmd,u32 db_phys_id)495*4882a593Smuzhiyun static void its_encode_db_phys_id(struct its_cmd_block *cmd, u32 db_phys_id)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[2], db_phys_id, 63, 32);
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun
its_encode_db_valid(struct its_cmd_block * cmd,bool db_valid)500*4882a593Smuzhiyun static void its_encode_db_valid(struct its_cmd_block *cmd, bool db_valid)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[2], db_valid, 0, 0);
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
its_encode_seq_num(struct its_cmd_block * cmd,u16 seq_num)505*4882a593Smuzhiyun static void its_encode_seq_num(struct its_cmd_block *cmd, u16 seq_num)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], seq_num, 47, 32);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
its_encode_its_list(struct its_cmd_block * cmd,u16 its_list)510*4882a593Smuzhiyun static void its_encode_its_list(struct its_cmd_block *cmd, u16 its_list)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[1], its_list, 15, 0);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
its_encode_vpt_addr(struct its_cmd_block * cmd,u64 vpt_pa)515*4882a593Smuzhiyun static void its_encode_vpt_addr(struct its_cmd_block *cmd, u64 vpt_pa)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 51, 16);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
its_encode_vpt_size(struct its_cmd_block * cmd,u8 vpt_size)520*4882a593Smuzhiyun static void its_encode_vpt_size(struct its_cmd_block *cmd, u8 vpt_size)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[3], vpt_size, 4, 0);
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
its_encode_vconf_addr(struct its_cmd_block * cmd,u64 vconf_pa)525*4882a593Smuzhiyun static void its_encode_vconf_addr(struct its_cmd_block *cmd, u64 vconf_pa)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], vconf_pa >> 16, 51, 16);
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
its_encode_alloc(struct its_cmd_block * cmd,bool alloc)530*4882a593Smuzhiyun static void its_encode_alloc(struct its_cmd_block *cmd, bool alloc)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], alloc, 8, 8);
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
its_encode_ptz(struct its_cmd_block * cmd,bool ptz)535*4882a593Smuzhiyun static void its_encode_ptz(struct its_cmd_block *cmd, bool ptz)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], ptz, 9, 9);
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun
its_encode_vmapp_default_db(struct its_cmd_block * cmd,u32 vpe_db_lpi)540*4882a593Smuzhiyun static void its_encode_vmapp_default_db(struct its_cmd_block *cmd,
541*4882a593Smuzhiyun u32 vpe_db_lpi)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[1], vpe_db_lpi, 31, 0);
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
its_encode_vmovp_default_db(struct its_cmd_block * cmd,u32 vpe_db_lpi)546*4882a593Smuzhiyun static void its_encode_vmovp_default_db(struct its_cmd_block *cmd,
547*4882a593Smuzhiyun u32 vpe_db_lpi)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[3], vpe_db_lpi, 31, 0);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
its_encode_db(struct its_cmd_block * cmd,bool db)552*4882a593Smuzhiyun static void its_encode_db(struct its_cmd_block *cmd, bool db)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[2], db, 63, 63);
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
its_encode_sgi_intid(struct its_cmd_block * cmd,u8 sgi)557*4882a593Smuzhiyun static void its_encode_sgi_intid(struct its_cmd_block *cmd, u8 sgi)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], sgi, 35, 32);
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
its_encode_sgi_priority(struct its_cmd_block * cmd,u8 prio)562*4882a593Smuzhiyun static void its_encode_sgi_priority(struct its_cmd_block *cmd, u8 prio)
563*4882a593Smuzhiyun {
564*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], prio >> 4, 23, 20);
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun
its_encode_sgi_group(struct its_cmd_block * cmd,bool grp)567*4882a593Smuzhiyun static void its_encode_sgi_group(struct its_cmd_block *cmd, bool grp)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], grp, 10, 10);
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun
its_encode_sgi_clear(struct its_cmd_block * cmd,bool clr)572*4882a593Smuzhiyun static void its_encode_sgi_clear(struct its_cmd_block *cmd, bool clr)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], clr, 9, 9);
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
its_encode_sgi_enable(struct its_cmd_block * cmd,bool en)577*4882a593Smuzhiyun static void its_encode_sgi_enable(struct its_cmd_block *cmd, bool en)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun its_mask_encode(&cmd->raw_cmd[0], en, 8, 8);
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun
its_fixup_cmd(struct its_cmd_block * cmd)582*4882a593Smuzhiyun static inline void its_fixup_cmd(struct its_cmd_block *cmd)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun /* Let's fixup BE commands */
585*4882a593Smuzhiyun cmd->raw_cmd_le[0] = cpu_to_le64(cmd->raw_cmd[0]);
586*4882a593Smuzhiyun cmd->raw_cmd_le[1] = cpu_to_le64(cmd->raw_cmd[1]);
587*4882a593Smuzhiyun cmd->raw_cmd_le[2] = cpu_to_le64(cmd->raw_cmd[2]);
588*4882a593Smuzhiyun cmd->raw_cmd_le[3] = cpu_to_le64(cmd->raw_cmd[3]);
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
its_build_mapd_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)591*4882a593Smuzhiyun static struct its_collection *its_build_mapd_cmd(struct its_node *its,
592*4882a593Smuzhiyun struct its_cmd_block *cmd,
593*4882a593Smuzhiyun struct its_cmd_desc *desc)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun unsigned long itt_addr;
596*4882a593Smuzhiyun u8 size = ilog2(desc->its_mapd_cmd.dev->nr_ites);
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun itt_addr = virt_to_phys(desc->its_mapd_cmd.dev->itt);
599*4882a593Smuzhiyun itt_addr = ALIGN(itt_addr, ITS_ITT_ALIGN);
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_MAPD);
602*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_mapd_cmd.dev->device_id);
603*4882a593Smuzhiyun its_encode_size(cmd, size - 1);
604*4882a593Smuzhiyun its_encode_itt(cmd, itt_addr);
605*4882a593Smuzhiyun its_encode_valid(cmd, desc->its_mapd_cmd.valid);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun its_fixup_cmd(cmd);
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun return NULL;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun
its_build_mapc_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)612*4882a593Smuzhiyun static struct its_collection *its_build_mapc_cmd(struct its_node *its,
613*4882a593Smuzhiyun struct its_cmd_block *cmd,
614*4882a593Smuzhiyun struct its_cmd_desc *desc)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_MAPC);
617*4882a593Smuzhiyun its_encode_collection(cmd, desc->its_mapc_cmd.col->col_id);
618*4882a593Smuzhiyun its_encode_target(cmd, desc->its_mapc_cmd.col->target_address);
619*4882a593Smuzhiyun its_encode_valid(cmd, desc->its_mapc_cmd.valid);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun its_fixup_cmd(cmd);
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun return desc->its_mapc_cmd.col;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
its_build_mapti_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)626*4882a593Smuzhiyun static struct its_collection *its_build_mapti_cmd(struct its_node *its,
627*4882a593Smuzhiyun struct its_cmd_block *cmd,
628*4882a593Smuzhiyun struct its_cmd_desc *desc)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun struct its_collection *col;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun col = dev_event_to_col(desc->its_mapti_cmd.dev,
633*4882a593Smuzhiyun desc->its_mapti_cmd.event_id);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_MAPTI);
636*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_mapti_cmd.dev->device_id);
637*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_mapti_cmd.event_id);
638*4882a593Smuzhiyun its_encode_phys_id(cmd, desc->its_mapti_cmd.phys_id);
639*4882a593Smuzhiyun its_encode_collection(cmd, col->col_id);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun its_fixup_cmd(cmd);
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun return valid_col(col);
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
its_build_movi_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)646*4882a593Smuzhiyun static struct its_collection *its_build_movi_cmd(struct its_node *its,
647*4882a593Smuzhiyun struct its_cmd_block *cmd,
648*4882a593Smuzhiyun struct its_cmd_desc *desc)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun struct its_collection *col;
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun col = dev_event_to_col(desc->its_movi_cmd.dev,
653*4882a593Smuzhiyun desc->its_movi_cmd.event_id);
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_MOVI);
656*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_movi_cmd.dev->device_id);
657*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_movi_cmd.event_id);
658*4882a593Smuzhiyun its_encode_collection(cmd, desc->its_movi_cmd.col->col_id);
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun its_fixup_cmd(cmd);
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun return valid_col(col);
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
its_build_discard_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)665*4882a593Smuzhiyun static struct its_collection *its_build_discard_cmd(struct its_node *its,
666*4882a593Smuzhiyun struct its_cmd_block *cmd,
667*4882a593Smuzhiyun struct its_cmd_desc *desc)
668*4882a593Smuzhiyun {
669*4882a593Smuzhiyun struct its_collection *col;
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun col = dev_event_to_col(desc->its_discard_cmd.dev,
672*4882a593Smuzhiyun desc->its_discard_cmd.event_id);
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_DISCARD);
675*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_discard_cmd.dev->device_id);
676*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_discard_cmd.event_id);
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun its_fixup_cmd(cmd);
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun return valid_col(col);
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
its_build_inv_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)683*4882a593Smuzhiyun static struct its_collection *its_build_inv_cmd(struct its_node *its,
684*4882a593Smuzhiyun struct its_cmd_block *cmd,
685*4882a593Smuzhiyun struct its_cmd_desc *desc)
686*4882a593Smuzhiyun {
687*4882a593Smuzhiyun struct its_collection *col;
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun col = dev_event_to_col(desc->its_inv_cmd.dev,
690*4882a593Smuzhiyun desc->its_inv_cmd.event_id);
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_INV);
693*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id);
694*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_inv_cmd.event_id);
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun its_fixup_cmd(cmd);
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun return valid_col(col);
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun
its_build_int_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)701*4882a593Smuzhiyun static struct its_collection *its_build_int_cmd(struct its_node *its,
702*4882a593Smuzhiyun struct its_cmd_block *cmd,
703*4882a593Smuzhiyun struct its_cmd_desc *desc)
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun struct its_collection *col;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun col = dev_event_to_col(desc->its_int_cmd.dev,
708*4882a593Smuzhiyun desc->its_int_cmd.event_id);
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_INT);
711*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_int_cmd.dev->device_id);
712*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_int_cmd.event_id);
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun its_fixup_cmd(cmd);
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun return valid_col(col);
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
its_build_clear_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)719*4882a593Smuzhiyun static struct its_collection *its_build_clear_cmd(struct its_node *its,
720*4882a593Smuzhiyun struct its_cmd_block *cmd,
721*4882a593Smuzhiyun struct its_cmd_desc *desc)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun struct its_collection *col;
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun col = dev_event_to_col(desc->its_clear_cmd.dev,
726*4882a593Smuzhiyun desc->its_clear_cmd.event_id);
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_CLEAR);
729*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_clear_cmd.dev->device_id);
730*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_clear_cmd.event_id);
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun its_fixup_cmd(cmd);
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun return valid_col(col);
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun
its_build_invall_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)737*4882a593Smuzhiyun static struct its_collection *its_build_invall_cmd(struct its_node *its,
738*4882a593Smuzhiyun struct its_cmd_block *cmd,
739*4882a593Smuzhiyun struct its_cmd_desc *desc)
740*4882a593Smuzhiyun {
741*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_INVALL);
742*4882a593Smuzhiyun its_encode_collection(cmd, desc->its_invall_cmd.col->col_id);
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun its_fixup_cmd(cmd);
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun return desc->its_invall_cmd.col;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
its_build_vinvall_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)749*4882a593Smuzhiyun static struct its_vpe *its_build_vinvall_cmd(struct its_node *its,
750*4882a593Smuzhiyun struct its_cmd_block *cmd,
751*4882a593Smuzhiyun struct its_cmd_desc *desc)
752*4882a593Smuzhiyun {
753*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_VINVALL);
754*4882a593Smuzhiyun its_encode_vpeid(cmd, desc->its_vinvall_cmd.vpe->vpe_id);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun its_fixup_cmd(cmd);
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun return valid_vpe(its, desc->its_vinvall_cmd.vpe);
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
its_build_vmapp_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)761*4882a593Smuzhiyun static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
762*4882a593Smuzhiyun struct its_cmd_block *cmd,
763*4882a593Smuzhiyun struct its_cmd_desc *desc)
764*4882a593Smuzhiyun {
765*4882a593Smuzhiyun unsigned long vpt_addr, vconf_addr;
766*4882a593Smuzhiyun u64 target;
767*4882a593Smuzhiyun bool alloc;
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_VMAPP);
770*4882a593Smuzhiyun its_encode_vpeid(cmd, desc->its_vmapp_cmd.vpe->vpe_id);
771*4882a593Smuzhiyun its_encode_valid(cmd, desc->its_vmapp_cmd.valid);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (!desc->its_vmapp_cmd.valid) {
774*4882a593Smuzhiyun if (is_v4_1(its)) {
775*4882a593Smuzhiyun alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count);
776*4882a593Smuzhiyun its_encode_alloc(cmd, alloc);
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun goto out;
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun vpt_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
783*4882a593Smuzhiyun target = desc->its_vmapp_cmd.col->target_address + its->vlpi_redist_offset;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun its_encode_target(cmd, target);
786*4882a593Smuzhiyun its_encode_vpt_addr(cmd, vpt_addr);
787*4882a593Smuzhiyun its_encode_vpt_size(cmd, LPI_NRBITS - 1);
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun if (!is_v4_1(its))
790*4882a593Smuzhiyun goto out;
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun vconf_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->its_vm->vprop_page));
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun alloc = !atomic_fetch_inc(&desc->its_vmapp_cmd.vpe->vmapp_count);
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun its_encode_alloc(cmd, alloc);
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /* We can only signal PTZ when alloc==1. Why do we have two bits? */
799*4882a593Smuzhiyun its_encode_ptz(cmd, alloc);
800*4882a593Smuzhiyun its_encode_vconf_addr(cmd, vconf_addr);
801*4882a593Smuzhiyun its_encode_vmapp_default_db(cmd, desc->its_vmapp_cmd.vpe->vpe_db_lpi);
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun out:
804*4882a593Smuzhiyun its_fixup_cmd(cmd);
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun return valid_vpe(its, desc->its_vmapp_cmd.vpe);
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun
its_build_vmapti_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)809*4882a593Smuzhiyun static struct its_vpe *its_build_vmapti_cmd(struct its_node *its,
810*4882a593Smuzhiyun struct its_cmd_block *cmd,
811*4882a593Smuzhiyun struct its_cmd_desc *desc)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun u32 db;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun if (!is_v4_1(its) && desc->its_vmapti_cmd.db_enabled)
816*4882a593Smuzhiyun db = desc->its_vmapti_cmd.vpe->vpe_db_lpi;
817*4882a593Smuzhiyun else
818*4882a593Smuzhiyun db = 1023;
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_VMAPTI);
821*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_vmapti_cmd.dev->device_id);
822*4882a593Smuzhiyun its_encode_vpeid(cmd, desc->its_vmapti_cmd.vpe->vpe_id);
823*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_vmapti_cmd.event_id);
824*4882a593Smuzhiyun its_encode_db_phys_id(cmd, db);
825*4882a593Smuzhiyun its_encode_virt_id(cmd, desc->its_vmapti_cmd.virt_id);
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun its_fixup_cmd(cmd);
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun return valid_vpe(its, desc->its_vmapti_cmd.vpe);
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun
its_build_vmovi_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)832*4882a593Smuzhiyun static struct its_vpe *its_build_vmovi_cmd(struct its_node *its,
833*4882a593Smuzhiyun struct its_cmd_block *cmd,
834*4882a593Smuzhiyun struct its_cmd_desc *desc)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun u32 db;
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun if (!is_v4_1(its) && desc->its_vmovi_cmd.db_enabled)
839*4882a593Smuzhiyun db = desc->its_vmovi_cmd.vpe->vpe_db_lpi;
840*4882a593Smuzhiyun else
841*4882a593Smuzhiyun db = 1023;
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_VMOVI);
844*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_vmovi_cmd.dev->device_id);
845*4882a593Smuzhiyun its_encode_vpeid(cmd, desc->its_vmovi_cmd.vpe->vpe_id);
846*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_vmovi_cmd.event_id);
847*4882a593Smuzhiyun its_encode_db_phys_id(cmd, db);
848*4882a593Smuzhiyun its_encode_db_valid(cmd, true);
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun its_fixup_cmd(cmd);
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun return valid_vpe(its, desc->its_vmovi_cmd.vpe);
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun
its_build_vmovp_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)855*4882a593Smuzhiyun static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
856*4882a593Smuzhiyun struct its_cmd_block *cmd,
857*4882a593Smuzhiyun struct its_cmd_desc *desc)
858*4882a593Smuzhiyun {
859*4882a593Smuzhiyun u64 target;
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun target = desc->its_vmovp_cmd.col->target_address + its->vlpi_redist_offset;
862*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_VMOVP);
863*4882a593Smuzhiyun its_encode_seq_num(cmd, desc->its_vmovp_cmd.seq_num);
864*4882a593Smuzhiyun its_encode_its_list(cmd, desc->its_vmovp_cmd.its_list);
865*4882a593Smuzhiyun its_encode_vpeid(cmd, desc->its_vmovp_cmd.vpe->vpe_id);
866*4882a593Smuzhiyun its_encode_target(cmd, target);
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun if (is_v4_1(its)) {
869*4882a593Smuzhiyun its_encode_db(cmd, true);
870*4882a593Smuzhiyun its_encode_vmovp_default_db(cmd, desc->its_vmovp_cmd.vpe->vpe_db_lpi);
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun its_fixup_cmd(cmd);
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun return valid_vpe(its, desc->its_vmovp_cmd.vpe);
876*4882a593Smuzhiyun }
877*4882a593Smuzhiyun
its_build_vinv_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)878*4882a593Smuzhiyun static struct its_vpe *its_build_vinv_cmd(struct its_node *its,
879*4882a593Smuzhiyun struct its_cmd_block *cmd,
880*4882a593Smuzhiyun struct its_cmd_desc *desc)
881*4882a593Smuzhiyun {
882*4882a593Smuzhiyun struct its_vlpi_map *map;
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun map = dev_event_to_vlpi_map(desc->its_inv_cmd.dev,
885*4882a593Smuzhiyun desc->its_inv_cmd.event_id);
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_INV);
888*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id);
889*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_inv_cmd.event_id);
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun its_fixup_cmd(cmd);
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun return valid_vpe(its, map->vpe);
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun
its_build_vint_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)896*4882a593Smuzhiyun static struct its_vpe *its_build_vint_cmd(struct its_node *its,
897*4882a593Smuzhiyun struct its_cmd_block *cmd,
898*4882a593Smuzhiyun struct its_cmd_desc *desc)
899*4882a593Smuzhiyun {
900*4882a593Smuzhiyun struct its_vlpi_map *map;
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun map = dev_event_to_vlpi_map(desc->its_int_cmd.dev,
903*4882a593Smuzhiyun desc->its_int_cmd.event_id);
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_INT);
906*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_int_cmd.dev->device_id);
907*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_int_cmd.event_id);
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun its_fixup_cmd(cmd);
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun return valid_vpe(its, map->vpe);
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun
its_build_vclear_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)914*4882a593Smuzhiyun static struct its_vpe *its_build_vclear_cmd(struct its_node *its,
915*4882a593Smuzhiyun struct its_cmd_block *cmd,
916*4882a593Smuzhiyun struct its_cmd_desc *desc)
917*4882a593Smuzhiyun {
918*4882a593Smuzhiyun struct its_vlpi_map *map;
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun map = dev_event_to_vlpi_map(desc->its_clear_cmd.dev,
921*4882a593Smuzhiyun desc->its_clear_cmd.event_id);
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_CLEAR);
924*4882a593Smuzhiyun its_encode_devid(cmd, desc->its_clear_cmd.dev->device_id);
925*4882a593Smuzhiyun its_encode_event_id(cmd, desc->its_clear_cmd.event_id);
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun its_fixup_cmd(cmd);
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun return valid_vpe(its, map->vpe);
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun
its_build_invdb_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)932*4882a593Smuzhiyun static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
933*4882a593Smuzhiyun struct its_cmd_block *cmd,
934*4882a593Smuzhiyun struct its_cmd_desc *desc)
935*4882a593Smuzhiyun {
936*4882a593Smuzhiyun if (WARN_ON(!is_v4_1(its)))
937*4882a593Smuzhiyun return NULL;
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_INVDB);
940*4882a593Smuzhiyun its_encode_vpeid(cmd, desc->its_invdb_cmd.vpe->vpe_id);
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun its_fixup_cmd(cmd);
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun return valid_vpe(its, desc->its_invdb_cmd.vpe);
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun
its_build_vsgi_cmd(struct its_node * its,struct its_cmd_block * cmd,struct its_cmd_desc * desc)947*4882a593Smuzhiyun static struct its_vpe *its_build_vsgi_cmd(struct its_node *its,
948*4882a593Smuzhiyun struct its_cmd_block *cmd,
949*4882a593Smuzhiyun struct its_cmd_desc *desc)
950*4882a593Smuzhiyun {
951*4882a593Smuzhiyun if (WARN_ON(!is_v4_1(its)))
952*4882a593Smuzhiyun return NULL;
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun its_encode_cmd(cmd, GITS_CMD_VSGI);
955*4882a593Smuzhiyun its_encode_vpeid(cmd, desc->its_vsgi_cmd.vpe->vpe_id);
956*4882a593Smuzhiyun its_encode_sgi_intid(cmd, desc->its_vsgi_cmd.sgi);
957*4882a593Smuzhiyun its_encode_sgi_priority(cmd, desc->its_vsgi_cmd.priority);
958*4882a593Smuzhiyun its_encode_sgi_group(cmd, desc->its_vsgi_cmd.group);
959*4882a593Smuzhiyun its_encode_sgi_clear(cmd, desc->its_vsgi_cmd.clear);
960*4882a593Smuzhiyun its_encode_sgi_enable(cmd, desc->its_vsgi_cmd.enable);
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun its_fixup_cmd(cmd);
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun return valid_vpe(its, desc->its_vsgi_cmd.vpe);
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun
its_cmd_ptr_to_offset(struct its_node * its,struct its_cmd_block * ptr)967*4882a593Smuzhiyun static u64 its_cmd_ptr_to_offset(struct its_node *its,
968*4882a593Smuzhiyun struct its_cmd_block *ptr)
969*4882a593Smuzhiyun {
970*4882a593Smuzhiyun return (ptr - its->cmd_base) * sizeof(*ptr);
971*4882a593Smuzhiyun }
972*4882a593Smuzhiyun
its_queue_full(struct its_node * its)973*4882a593Smuzhiyun static int its_queue_full(struct its_node *its)
974*4882a593Smuzhiyun {
975*4882a593Smuzhiyun int widx;
976*4882a593Smuzhiyun int ridx;
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun widx = its->cmd_write - its->cmd_base;
979*4882a593Smuzhiyun ridx = readl_relaxed(its->base + GITS_CREADR) / sizeof(struct its_cmd_block);
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun /* This is incredibly unlikely to happen, unless the ITS locks up. */
982*4882a593Smuzhiyun if (((widx + 1) % ITS_CMD_QUEUE_NR_ENTRIES) == ridx)
983*4882a593Smuzhiyun return 1;
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun return 0;
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun
its_allocate_entry(struct its_node * its)988*4882a593Smuzhiyun static struct its_cmd_block *its_allocate_entry(struct its_node *its)
989*4882a593Smuzhiyun {
990*4882a593Smuzhiyun struct its_cmd_block *cmd;
991*4882a593Smuzhiyun u32 count = 1000000; /* 1s! */
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun while (its_queue_full(its)) {
994*4882a593Smuzhiyun count--;
995*4882a593Smuzhiyun if (!count) {
996*4882a593Smuzhiyun pr_err_ratelimited("ITS queue not draining\n");
997*4882a593Smuzhiyun return NULL;
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun cpu_relax();
1000*4882a593Smuzhiyun udelay(1);
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun cmd = its->cmd_write++;
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun /* Handle queue wrapping */
1006*4882a593Smuzhiyun if (its->cmd_write == (its->cmd_base + ITS_CMD_QUEUE_NR_ENTRIES))
1007*4882a593Smuzhiyun its->cmd_write = its->cmd_base;
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun /* Clear command */
1010*4882a593Smuzhiyun cmd->raw_cmd[0] = 0;
1011*4882a593Smuzhiyun cmd->raw_cmd[1] = 0;
1012*4882a593Smuzhiyun cmd->raw_cmd[2] = 0;
1013*4882a593Smuzhiyun cmd->raw_cmd[3] = 0;
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun return cmd;
1016*4882a593Smuzhiyun }
1017*4882a593Smuzhiyun
its_post_commands(struct its_node * its)1018*4882a593Smuzhiyun static struct its_cmd_block *its_post_commands(struct its_node *its)
1019*4882a593Smuzhiyun {
1020*4882a593Smuzhiyun u64 wr = its_cmd_ptr_to_offset(its, its->cmd_write);
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun writel_relaxed(wr, its->base + GITS_CWRITER);
1023*4882a593Smuzhiyun
1024*4882a593Smuzhiyun return its->cmd_write;
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun
its_flush_cmd(struct its_node * its,struct its_cmd_block * cmd)1027*4882a593Smuzhiyun static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd)
1028*4882a593Smuzhiyun {
1029*4882a593Smuzhiyun /*
1030*4882a593Smuzhiyun * Make sure the commands written to memory are observable by
1031*4882a593Smuzhiyun * the ITS.
1032*4882a593Smuzhiyun */
1033*4882a593Smuzhiyun if (its->flags & ITS_FLAGS_CMDQ_NEEDS_FLUSHING)
1034*4882a593Smuzhiyun gic_flush_dcache_to_poc(cmd, sizeof(*cmd));
1035*4882a593Smuzhiyun else
1036*4882a593Smuzhiyun dsb(ishst);
1037*4882a593Smuzhiyun }
1038*4882a593Smuzhiyun
its_wait_for_range_completion(struct its_node * its,u64 prev_idx,struct its_cmd_block * to)1039*4882a593Smuzhiyun static int its_wait_for_range_completion(struct its_node *its,
1040*4882a593Smuzhiyun u64 prev_idx,
1041*4882a593Smuzhiyun struct its_cmd_block *to)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun u64 rd_idx, to_idx, linear_idx;
1044*4882a593Smuzhiyun u32 count = 1000000; /* 1s! */
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun /* Linearize to_idx if the command set has wrapped around */
1047*4882a593Smuzhiyun to_idx = its_cmd_ptr_to_offset(its, to);
1048*4882a593Smuzhiyun if (to_idx < prev_idx)
1049*4882a593Smuzhiyun to_idx += ITS_CMD_QUEUE_SZ;
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyun linear_idx = prev_idx;
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun while (1) {
1054*4882a593Smuzhiyun s64 delta;
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun rd_idx = readl_relaxed(its->base + GITS_CREADR);
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun /*
1059*4882a593Smuzhiyun * Compute the read pointer progress, taking the
1060*4882a593Smuzhiyun * potential wrap-around into account.
1061*4882a593Smuzhiyun */
1062*4882a593Smuzhiyun delta = rd_idx - prev_idx;
1063*4882a593Smuzhiyun if (rd_idx < prev_idx)
1064*4882a593Smuzhiyun delta += ITS_CMD_QUEUE_SZ;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun linear_idx += delta;
1067*4882a593Smuzhiyun if (linear_idx >= to_idx)
1068*4882a593Smuzhiyun break;
1069*4882a593Smuzhiyun
1070*4882a593Smuzhiyun count--;
1071*4882a593Smuzhiyun if (!count) {
1072*4882a593Smuzhiyun pr_err_ratelimited("ITS queue timeout (%llu %llu)\n",
1073*4882a593Smuzhiyun to_idx, linear_idx);
1074*4882a593Smuzhiyun return -1;
1075*4882a593Smuzhiyun }
1076*4882a593Smuzhiyun prev_idx = rd_idx;
1077*4882a593Smuzhiyun cpu_relax();
1078*4882a593Smuzhiyun udelay(1);
1079*4882a593Smuzhiyun }
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun return 0;
1082*4882a593Smuzhiyun }
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun /* Warning, macro hell follows */
1085*4882a593Smuzhiyun #define BUILD_SINGLE_CMD_FUNC(name, buildtype, synctype, buildfn) \
1086*4882a593Smuzhiyun void name(struct its_node *its, \
1087*4882a593Smuzhiyun buildtype builder, \
1088*4882a593Smuzhiyun struct its_cmd_desc *desc) \
1089*4882a593Smuzhiyun { \
1090*4882a593Smuzhiyun struct its_cmd_block *cmd, *sync_cmd, *next_cmd; \
1091*4882a593Smuzhiyun synctype *sync_obj; \
1092*4882a593Smuzhiyun unsigned long flags; \
1093*4882a593Smuzhiyun u64 rd_idx; \
1094*4882a593Smuzhiyun \
1095*4882a593Smuzhiyun raw_spin_lock_irqsave(&its->lock, flags); \
1096*4882a593Smuzhiyun \
1097*4882a593Smuzhiyun cmd = its_allocate_entry(its); \
1098*4882a593Smuzhiyun if (!cmd) { /* We're soooooo screewed... */ \
1099*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&its->lock, flags); \
1100*4882a593Smuzhiyun return; \
1101*4882a593Smuzhiyun } \
1102*4882a593Smuzhiyun sync_obj = builder(its, cmd, desc); \
1103*4882a593Smuzhiyun its_flush_cmd(its, cmd); \
1104*4882a593Smuzhiyun \
1105*4882a593Smuzhiyun if (sync_obj) { \
1106*4882a593Smuzhiyun sync_cmd = its_allocate_entry(its); \
1107*4882a593Smuzhiyun if (!sync_cmd) \
1108*4882a593Smuzhiyun goto post; \
1109*4882a593Smuzhiyun \
1110*4882a593Smuzhiyun buildfn(its, sync_cmd, sync_obj); \
1111*4882a593Smuzhiyun its_flush_cmd(its, sync_cmd); \
1112*4882a593Smuzhiyun } \
1113*4882a593Smuzhiyun \
1114*4882a593Smuzhiyun post: \
1115*4882a593Smuzhiyun rd_idx = readl_relaxed(its->base + GITS_CREADR); \
1116*4882a593Smuzhiyun next_cmd = its_post_commands(its); \
1117*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&its->lock, flags); \
1118*4882a593Smuzhiyun \
1119*4882a593Smuzhiyun if (its_wait_for_range_completion(its, rd_idx, next_cmd)) \
1120*4882a593Smuzhiyun pr_err_ratelimited("ITS cmd %ps failed\n", builder); \
1121*4882a593Smuzhiyun }
1122*4882a593Smuzhiyun
its_build_sync_cmd(struct its_node * its,struct its_cmd_block * sync_cmd,struct its_collection * sync_col)1123*4882a593Smuzhiyun static void its_build_sync_cmd(struct its_node *its,
1124*4882a593Smuzhiyun struct its_cmd_block *sync_cmd,
1125*4882a593Smuzhiyun struct its_collection *sync_col)
1126*4882a593Smuzhiyun {
1127*4882a593Smuzhiyun its_encode_cmd(sync_cmd, GITS_CMD_SYNC);
1128*4882a593Smuzhiyun its_encode_target(sync_cmd, sync_col->target_address);
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun its_fixup_cmd(sync_cmd);
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun
BUILD_SINGLE_CMD_FUNC(its_send_single_command,its_cmd_builder_t,struct its_collection,its_build_sync_cmd)1133*4882a593Smuzhiyun static BUILD_SINGLE_CMD_FUNC(its_send_single_command, its_cmd_builder_t,
1134*4882a593Smuzhiyun struct its_collection, its_build_sync_cmd)
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun static void its_build_vsync_cmd(struct its_node *its,
1137*4882a593Smuzhiyun struct its_cmd_block *sync_cmd,
1138*4882a593Smuzhiyun struct its_vpe *sync_vpe)
1139*4882a593Smuzhiyun {
1140*4882a593Smuzhiyun its_encode_cmd(sync_cmd, GITS_CMD_VSYNC);
1141*4882a593Smuzhiyun its_encode_vpeid(sync_cmd, sync_vpe->vpe_id);
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun its_fixup_cmd(sync_cmd);
1144*4882a593Smuzhiyun }
1145*4882a593Smuzhiyun
BUILD_SINGLE_CMD_FUNC(its_send_single_vcommand,its_cmd_vbuilder_t,struct its_vpe,its_build_vsync_cmd)1146*4882a593Smuzhiyun static BUILD_SINGLE_CMD_FUNC(its_send_single_vcommand, its_cmd_vbuilder_t,
1147*4882a593Smuzhiyun struct its_vpe, its_build_vsync_cmd)
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun static void its_send_int(struct its_device *dev, u32 event_id)
1150*4882a593Smuzhiyun {
1151*4882a593Smuzhiyun struct its_cmd_desc desc;
1152*4882a593Smuzhiyun
1153*4882a593Smuzhiyun desc.its_int_cmd.dev = dev;
1154*4882a593Smuzhiyun desc.its_int_cmd.event_id = event_id;
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun its_send_single_command(dev->its, its_build_int_cmd, &desc);
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun
its_send_clear(struct its_device * dev,u32 event_id)1159*4882a593Smuzhiyun static void its_send_clear(struct its_device *dev, u32 event_id)
1160*4882a593Smuzhiyun {
1161*4882a593Smuzhiyun struct its_cmd_desc desc;
1162*4882a593Smuzhiyun
1163*4882a593Smuzhiyun desc.its_clear_cmd.dev = dev;
1164*4882a593Smuzhiyun desc.its_clear_cmd.event_id = event_id;
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun its_send_single_command(dev->its, its_build_clear_cmd, &desc);
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun
its_send_inv(struct its_device * dev,u32 event_id)1169*4882a593Smuzhiyun static void its_send_inv(struct its_device *dev, u32 event_id)
1170*4882a593Smuzhiyun {
1171*4882a593Smuzhiyun struct its_cmd_desc desc;
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun desc.its_inv_cmd.dev = dev;
1174*4882a593Smuzhiyun desc.its_inv_cmd.event_id = event_id;
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun its_send_single_command(dev->its, its_build_inv_cmd, &desc);
1177*4882a593Smuzhiyun }
1178*4882a593Smuzhiyun
its_send_mapd(struct its_device * dev,int valid)1179*4882a593Smuzhiyun static void its_send_mapd(struct its_device *dev, int valid)
1180*4882a593Smuzhiyun {
1181*4882a593Smuzhiyun struct its_cmd_desc desc;
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun desc.its_mapd_cmd.dev = dev;
1184*4882a593Smuzhiyun desc.its_mapd_cmd.valid = !!valid;
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun its_send_single_command(dev->its, its_build_mapd_cmd, &desc);
1187*4882a593Smuzhiyun }
1188*4882a593Smuzhiyun
its_send_mapc(struct its_node * its,struct its_collection * col,int valid)1189*4882a593Smuzhiyun static void its_send_mapc(struct its_node *its, struct its_collection *col,
1190*4882a593Smuzhiyun int valid)
1191*4882a593Smuzhiyun {
1192*4882a593Smuzhiyun struct its_cmd_desc desc;
1193*4882a593Smuzhiyun
1194*4882a593Smuzhiyun desc.its_mapc_cmd.col = col;
1195*4882a593Smuzhiyun desc.its_mapc_cmd.valid = !!valid;
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun its_send_single_command(its, its_build_mapc_cmd, &desc);
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun
its_send_mapti(struct its_device * dev,u32 irq_id,u32 id)1200*4882a593Smuzhiyun static void its_send_mapti(struct its_device *dev, u32 irq_id, u32 id)
1201*4882a593Smuzhiyun {
1202*4882a593Smuzhiyun struct its_cmd_desc desc;
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun desc.its_mapti_cmd.dev = dev;
1205*4882a593Smuzhiyun desc.its_mapti_cmd.phys_id = irq_id;
1206*4882a593Smuzhiyun desc.its_mapti_cmd.event_id = id;
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun its_send_single_command(dev->its, its_build_mapti_cmd, &desc);
1209*4882a593Smuzhiyun }
1210*4882a593Smuzhiyun
its_send_movi(struct its_device * dev,struct its_collection * col,u32 id)1211*4882a593Smuzhiyun static void its_send_movi(struct its_device *dev,
1212*4882a593Smuzhiyun struct its_collection *col, u32 id)
1213*4882a593Smuzhiyun {
1214*4882a593Smuzhiyun struct its_cmd_desc desc;
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun desc.its_movi_cmd.dev = dev;
1217*4882a593Smuzhiyun desc.its_movi_cmd.col = col;
1218*4882a593Smuzhiyun desc.its_movi_cmd.event_id = id;
1219*4882a593Smuzhiyun
1220*4882a593Smuzhiyun its_send_single_command(dev->its, its_build_movi_cmd, &desc);
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun
its_send_discard(struct its_device * dev,u32 id)1223*4882a593Smuzhiyun static void its_send_discard(struct its_device *dev, u32 id)
1224*4882a593Smuzhiyun {
1225*4882a593Smuzhiyun struct its_cmd_desc desc;
1226*4882a593Smuzhiyun
1227*4882a593Smuzhiyun desc.its_discard_cmd.dev = dev;
1228*4882a593Smuzhiyun desc.its_discard_cmd.event_id = id;
1229*4882a593Smuzhiyun
1230*4882a593Smuzhiyun its_send_single_command(dev->its, its_build_discard_cmd, &desc);
1231*4882a593Smuzhiyun }
1232*4882a593Smuzhiyun
its_send_invall(struct its_node * its,struct its_collection * col)1233*4882a593Smuzhiyun static void its_send_invall(struct its_node *its, struct its_collection *col)
1234*4882a593Smuzhiyun {
1235*4882a593Smuzhiyun struct its_cmd_desc desc;
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun desc.its_invall_cmd.col = col;
1238*4882a593Smuzhiyun
1239*4882a593Smuzhiyun its_send_single_command(its, its_build_invall_cmd, &desc);
1240*4882a593Smuzhiyun }
1241*4882a593Smuzhiyun
its_send_vmapti(struct its_device * dev,u32 id)1242*4882a593Smuzhiyun static void its_send_vmapti(struct its_device *dev, u32 id)
1243*4882a593Smuzhiyun {
1244*4882a593Smuzhiyun struct its_vlpi_map *map = dev_event_to_vlpi_map(dev, id);
1245*4882a593Smuzhiyun struct its_cmd_desc desc;
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun desc.its_vmapti_cmd.vpe = map->vpe;
1248*4882a593Smuzhiyun desc.its_vmapti_cmd.dev = dev;
1249*4882a593Smuzhiyun desc.its_vmapti_cmd.virt_id = map->vintid;
1250*4882a593Smuzhiyun desc.its_vmapti_cmd.event_id = id;
1251*4882a593Smuzhiyun desc.its_vmapti_cmd.db_enabled = map->db_enabled;
1252*4882a593Smuzhiyun
1253*4882a593Smuzhiyun its_send_single_vcommand(dev->its, its_build_vmapti_cmd, &desc);
1254*4882a593Smuzhiyun }
1255*4882a593Smuzhiyun
its_send_vmovi(struct its_device * dev,u32 id)1256*4882a593Smuzhiyun static void its_send_vmovi(struct its_device *dev, u32 id)
1257*4882a593Smuzhiyun {
1258*4882a593Smuzhiyun struct its_vlpi_map *map = dev_event_to_vlpi_map(dev, id);
1259*4882a593Smuzhiyun struct its_cmd_desc desc;
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun desc.its_vmovi_cmd.vpe = map->vpe;
1262*4882a593Smuzhiyun desc.its_vmovi_cmd.dev = dev;
1263*4882a593Smuzhiyun desc.its_vmovi_cmd.event_id = id;
1264*4882a593Smuzhiyun desc.its_vmovi_cmd.db_enabled = map->db_enabled;
1265*4882a593Smuzhiyun
1266*4882a593Smuzhiyun its_send_single_vcommand(dev->its, its_build_vmovi_cmd, &desc);
1267*4882a593Smuzhiyun }
1268*4882a593Smuzhiyun
its_send_vmapp(struct its_node * its,struct its_vpe * vpe,bool valid)1269*4882a593Smuzhiyun static void its_send_vmapp(struct its_node *its,
1270*4882a593Smuzhiyun struct its_vpe *vpe, bool valid)
1271*4882a593Smuzhiyun {
1272*4882a593Smuzhiyun struct its_cmd_desc desc;
1273*4882a593Smuzhiyun
1274*4882a593Smuzhiyun desc.its_vmapp_cmd.vpe = vpe;
1275*4882a593Smuzhiyun desc.its_vmapp_cmd.valid = valid;
1276*4882a593Smuzhiyun desc.its_vmapp_cmd.col = &its->collections[vpe->col_idx];
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun its_send_single_vcommand(its, its_build_vmapp_cmd, &desc);
1279*4882a593Smuzhiyun }
1280*4882a593Smuzhiyun
its_send_vmovp(struct its_vpe * vpe)1281*4882a593Smuzhiyun static void its_send_vmovp(struct its_vpe *vpe)
1282*4882a593Smuzhiyun {
1283*4882a593Smuzhiyun struct its_cmd_desc desc = {};
1284*4882a593Smuzhiyun struct its_node *its;
1285*4882a593Smuzhiyun unsigned long flags;
1286*4882a593Smuzhiyun int col_id = vpe->col_idx;
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun desc.its_vmovp_cmd.vpe = vpe;
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun if (!its_list_map) {
1291*4882a593Smuzhiyun its = list_first_entry(&its_nodes, struct its_node, entry);
1292*4882a593Smuzhiyun desc.its_vmovp_cmd.col = &its->collections[col_id];
1293*4882a593Smuzhiyun its_send_single_vcommand(its, its_build_vmovp_cmd, &desc);
1294*4882a593Smuzhiyun return;
1295*4882a593Smuzhiyun }
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun /*
1298*4882a593Smuzhiyun * Yet another marvel of the architecture. If using the
1299*4882a593Smuzhiyun * its_list "feature", we need to make sure that all ITSs
1300*4882a593Smuzhiyun * receive all VMOVP commands in the same order. The only way
1301*4882a593Smuzhiyun * to guarantee this is to make vmovp a serialization point.
1302*4882a593Smuzhiyun *
1303*4882a593Smuzhiyun * Wall <-- Head.
1304*4882a593Smuzhiyun */
1305*4882a593Smuzhiyun raw_spin_lock_irqsave(&vmovp_lock, flags);
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun desc.its_vmovp_cmd.seq_num = vmovp_seq_num++;
1308*4882a593Smuzhiyun desc.its_vmovp_cmd.its_list = get_its_list(vpe->its_vm);
1309*4882a593Smuzhiyun
1310*4882a593Smuzhiyun /* Emit VMOVPs */
1311*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
1312*4882a593Smuzhiyun if (!is_v4(its))
1313*4882a593Smuzhiyun continue;
1314*4882a593Smuzhiyun
1315*4882a593Smuzhiyun if (!require_its_list_vmovp(vpe->its_vm, its))
1316*4882a593Smuzhiyun continue;
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun desc.its_vmovp_cmd.col = &its->collections[col_id];
1319*4882a593Smuzhiyun its_send_single_vcommand(its, its_build_vmovp_cmd, &desc);
1320*4882a593Smuzhiyun }
1321*4882a593Smuzhiyun
1322*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&vmovp_lock, flags);
1323*4882a593Smuzhiyun }
1324*4882a593Smuzhiyun
its_send_vinvall(struct its_node * its,struct its_vpe * vpe)1325*4882a593Smuzhiyun static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
1326*4882a593Smuzhiyun {
1327*4882a593Smuzhiyun struct its_cmd_desc desc;
1328*4882a593Smuzhiyun
1329*4882a593Smuzhiyun desc.its_vinvall_cmd.vpe = vpe;
1330*4882a593Smuzhiyun its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
1331*4882a593Smuzhiyun }
1332*4882a593Smuzhiyun
its_send_vinv(struct its_device * dev,u32 event_id)1333*4882a593Smuzhiyun static void its_send_vinv(struct its_device *dev, u32 event_id)
1334*4882a593Smuzhiyun {
1335*4882a593Smuzhiyun struct its_cmd_desc desc;
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun /*
1338*4882a593Smuzhiyun * There is no real VINV command. This is just a normal INV,
1339*4882a593Smuzhiyun * with a VSYNC instead of a SYNC.
1340*4882a593Smuzhiyun */
1341*4882a593Smuzhiyun desc.its_inv_cmd.dev = dev;
1342*4882a593Smuzhiyun desc.its_inv_cmd.event_id = event_id;
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun its_send_single_vcommand(dev->its, its_build_vinv_cmd, &desc);
1345*4882a593Smuzhiyun }
1346*4882a593Smuzhiyun
its_send_vint(struct its_device * dev,u32 event_id)1347*4882a593Smuzhiyun static void its_send_vint(struct its_device *dev, u32 event_id)
1348*4882a593Smuzhiyun {
1349*4882a593Smuzhiyun struct its_cmd_desc desc;
1350*4882a593Smuzhiyun
1351*4882a593Smuzhiyun /*
1352*4882a593Smuzhiyun * There is no real VINT command. This is just a normal INT,
1353*4882a593Smuzhiyun * with a VSYNC instead of a SYNC.
1354*4882a593Smuzhiyun */
1355*4882a593Smuzhiyun desc.its_int_cmd.dev = dev;
1356*4882a593Smuzhiyun desc.its_int_cmd.event_id = event_id;
1357*4882a593Smuzhiyun
1358*4882a593Smuzhiyun its_send_single_vcommand(dev->its, its_build_vint_cmd, &desc);
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun
its_send_vclear(struct its_device * dev,u32 event_id)1361*4882a593Smuzhiyun static void its_send_vclear(struct its_device *dev, u32 event_id)
1362*4882a593Smuzhiyun {
1363*4882a593Smuzhiyun struct its_cmd_desc desc;
1364*4882a593Smuzhiyun
1365*4882a593Smuzhiyun /*
1366*4882a593Smuzhiyun * There is no real VCLEAR command. This is just a normal CLEAR,
1367*4882a593Smuzhiyun * with a VSYNC instead of a SYNC.
1368*4882a593Smuzhiyun */
1369*4882a593Smuzhiyun desc.its_clear_cmd.dev = dev;
1370*4882a593Smuzhiyun desc.its_clear_cmd.event_id = event_id;
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun its_send_single_vcommand(dev->its, its_build_vclear_cmd, &desc);
1373*4882a593Smuzhiyun }
1374*4882a593Smuzhiyun
its_send_invdb(struct its_node * its,struct its_vpe * vpe)1375*4882a593Smuzhiyun static void its_send_invdb(struct its_node *its, struct its_vpe *vpe)
1376*4882a593Smuzhiyun {
1377*4882a593Smuzhiyun struct its_cmd_desc desc;
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun desc.its_invdb_cmd.vpe = vpe;
1380*4882a593Smuzhiyun its_send_single_vcommand(its, its_build_invdb_cmd, &desc);
1381*4882a593Smuzhiyun }
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun /*
1384*4882a593Smuzhiyun * irqchip functions - assumes MSI, mostly.
1385*4882a593Smuzhiyun */
lpi_write_config(struct irq_data * d,u8 clr,u8 set)1386*4882a593Smuzhiyun static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
1387*4882a593Smuzhiyun {
1388*4882a593Smuzhiyun struct its_vlpi_map *map = get_vlpi_map(d);
1389*4882a593Smuzhiyun irq_hw_number_t hwirq;
1390*4882a593Smuzhiyun void *va;
1391*4882a593Smuzhiyun u8 *cfg;
1392*4882a593Smuzhiyun
1393*4882a593Smuzhiyun if (map) {
1394*4882a593Smuzhiyun va = page_address(map->vm->vprop_page);
1395*4882a593Smuzhiyun hwirq = map->vintid;
1396*4882a593Smuzhiyun
1397*4882a593Smuzhiyun /* Remember the updated property */
1398*4882a593Smuzhiyun map->properties &= ~clr;
1399*4882a593Smuzhiyun map->properties |= set | LPI_PROP_GROUP1;
1400*4882a593Smuzhiyun } else {
1401*4882a593Smuzhiyun va = gic_rdists->prop_table_va;
1402*4882a593Smuzhiyun hwirq = d->hwirq;
1403*4882a593Smuzhiyun }
1404*4882a593Smuzhiyun
1405*4882a593Smuzhiyun cfg = va + hwirq - 8192;
1406*4882a593Smuzhiyun *cfg &= ~clr;
1407*4882a593Smuzhiyun *cfg |= set | LPI_PROP_GROUP1;
1408*4882a593Smuzhiyun
1409*4882a593Smuzhiyun /*
1410*4882a593Smuzhiyun * Make the above write visible to the redistributors.
1411*4882a593Smuzhiyun * And yes, we're flushing exactly: One. Single. Byte.
1412*4882a593Smuzhiyun * Humpf...
1413*4882a593Smuzhiyun */
1414*4882a593Smuzhiyun if (gic_rdists->flags & RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING)
1415*4882a593Smuzhiyun gic_flush_dcache_to_poc(cfg, sizeof(*cfg));
1416*4882a593Smuzhiyun else
1417*4882a593Smuzhiyun dsb(ishst);
1418*4882a593Smuzhiyun }
1419*4882a593Smuzhiyun
wait_for_syncr(void __iomem * rdbase)1420*4882a593Smuzhiyun static void wait_for_syncr(void __iomem *rdbase)
1421*4882a593Smuzhiyun {
1422*4882a593Smuzhiyun while (readl_relaxed(rdbase + GICR_SYNCR) & 1)
1423*4882a593Smuzhiyun cpu_relax();
1424*4882a593Smuzhiyun }
1425*4882a593Smuzhiyun
direct_lpi_inv(struct irq_data * d)1426*4882a593Smuzhiyun static void direct_lpi_inv(struct irq_data *d)
1427*4882a593Smuzhiyun {
1428*4882a593Smuzhiyun struct its_vlpi_map *map = get_vlpi_map(d);
1429*4882a593Smuzhiyun void __iomem *rdbase;
1430*4882a593Smuzhiyun unsigned long flags;
1431*4882a593Smuzhiyun u64 val;
1432*4882a593Smuzhiyun int cpu;
1433*4882a593Smuzhiyun
1434*4882a593Smuzhiyun if (map) {
1435*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun WARN_ON(!is_v4_1(its_dev->its));
1438*4882a593Smuzhiyun
1439*4882a593Smuzhiyun val = GICR_INVLPIR_V;
1440*4882a593Smuzhiyun val |= FIELD_PREP(GICR_INVLPIR_VPEID, map->vpe->vpe_id);
1441*4882a593Smuzhiyun val |= FIELD_PREP(GICR_INVLPIR_INTID, map->vintid);
1442*4882a593Smuzhiyun } else {
1443*4882a593Smuzhiyun val = d->hwirq;
1444*4882a593Smuzhiyun }
1445*4882a593Smuzhiyun
1446*4882a593Smuzhiyun /* Target the redistributor this LPI is currently routed to */
1447*4882a593Smuzhiyun cpu = irq_to_cpuid_lock(d, &flags);
1448*4882a593Smuzhiyun raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
1449*4882a593Smuzhiyun rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
1450*4882a593Smuzhiyun gic_write_lpir(val, rdbase + GICR_INVLPIR);
1451*4882a593Smuzhiyun
1452*4882a593Smuzhiyun wait_for_syncr(rdbase);
1453*4882a593Smuzhiyun raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
1454*4882a593Smuzhiyun irq_to_cpuid_unlock(d, flags);
1455*4882a593Smuzhiyun }
1456*4882a593Smuzhiyun
lpi_update_config(struct irq_data * d,u8 clr,u8 set)1457*4882a593Smuzhiyun static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
1458*4882a593Smuzhiyun {
1459*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1460*4882a593Smuzhiyun
1461*4882a593Smuzhiyun lpi_write_config(d, clr, set);
1462*4882a593Smuzhiyun if (gic_rdists->has_direct_lpi &&
1463*4882a593Smuzhiyun (is_v4_1(its_dev->its) || !irqd_is_forwarded_to_vcpu(d)))
1464*4882a593Smuzhiyun direct_lpi_inv(d);
1465*4882a593Smuzhiyun else if (!irqd_is_forwarded_to_vcpu(d))
1466*4882a593Smuzhiyun its_send_inv(its_dev, its_get_event_id(d));
1467*4882a593Smuzhiyun else
1468*4882a593Smuzhiyun its_send_vinv(its_dev, its_get_event_id(d));
1469*4882a593Smuzhiyun }
1470*4882a593Smuzhiyun
its_vlpi_set_doorbell(struct irq_data * d,bool enable)1471*4882a593Smuzhiyun static void its_vlpi_set_doorbell(struct irq_data *d, bool enable)
1472*4882a593Smuzhiyun {
1473*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1474*4882a593Smuzhiyun u32 event = its_get_event_id(d);
1475*4882a593Smuzhiyun struct its_vlpi_map *map;
1476*4882a593Smuzhiyun
1477*4882a593Smuzhiyun /*
1478*4882a593Smuzhiyun * GICv4.1 does away with the per-LPI nonsense, nothing to do
1479*4882a593Smuzhiyun * here.
1480*4882a593Smuzhiyun */
1481*4882a593Smuzhiyun if (is_v4_1(its_dev->its))
1482*4882a593Smuzhiyun return;
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun map = dev_event_to_vlpi_map(its_dev, event);
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun if (map->db_enabled == enable)
1487*4882a593Smuzhiyun return;
1488*4882a593Smuzhiyun
1489*4882a593Smuzhiyun map->db_enabled = enable;
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun /*
1492*4882a593Smuzhiyun * More fun with the architecture:
1493*4882a593Smuzhiyun *
1494*4882a593Smuzhiyun * Ideally, we'd issue a VMAPTI to set the doorbell to its LPI
1495*4882a593Smuzhiyun * value or to 1023, depending on the enable bit. But that
1496*4882a593Smuzhiyun * would be issueing a mapping for an /existing/ DevID+EventID
1497*4882a593Smuzhiyun * pair, which is UNPREDICTABLE. Instead, let's issue a VMOVI
1498*4882a593Smuzhiyun * to the /same/ vPE, using this opportunity to adjust the
1499*4882a593Smuzhiyun * doorbell. Mouahahahaha. We loves it, Precious.
1500*4882a593Smuzhiyun */
1501*4882a593Smuzhiyun its_send_vmovi(its_dev, event);
1502*4882a593Smuzhiyun }
1503*4882a593Smuzhiyun
its_mask_irq(struct irq_data * d)1504*4882a593Smuzhiyun static void its_mask_irq(struct irq_data *d)
1505*4882a593Smuzhiyun {
1506*4882a593Smuzhiyun if (irqd_is_forwarded_to_vcpu(d))
1507*4882a593Smuzhiyun its_vlpi_set_doorbell(d, false);
1508*4882a593Smuzhiyun
1509*4882a593Smuzhiyun lpi_update_config(d, LPI_PROP_ENABLED, 0);
1510*4882a593Smuzhiyun }
1511*4882a593Smuzhiyun
its_unmask_irq(struct irq_data * d)1512*4882a593Smuzhiyun static void its_unmask_irq(struct irq_data *d)
1513*4882a593Smuzhiyun {
1514*4882a593Smuzhiyun if (irqd_is_forwarded_to_vcpu(d))
1515*4882a593Smuzhiyun its_vlpi_set_doorbell(d, true);
1516*4882a593Smuzhiyun
1517*4882a593Smuzhiyun lpi_update_config(d, 0, LPI_PROP_ENABLED);
1518*4882a593Smuzhiyun }
1519*4882a593Smuzhiyun
its_read_lpi_count(struct irq_data * d,int cpu)1520*4882a593Smuzhiyun static __maybe_unused u32 its_read_lpi_count(struct irq_data *d, int cpu)
1521*4882a593Smuzhiyun {
1522*4882a593Smuzhiyun if (irqd_affinity_is_managed(d))
1523*4882a593Smuzhiyun return atomic_read(&per_cpu_ptr(&cpu_lpi_count, cpu)->managed);
1524*4882a593Smuzhiyun
1525*4882a593Smuzhiyun return atomic_read(&per_cpu_ptr(&cpu_lpi_count, cpu)->unmanaged);
1526*4882a593Smuzhiyun }
1527*4882a593Smuzhiyun
its_inc_lpi_count(struct irq_data * d,int cpu)1528*4882a593Smuzhiyun static void its_inc_lpi_count(struct irq_data *d, int cpu)
1529*4882a593Smuzhiyun {
1530*4882a593Smuzhiyun if (irqd_affinity_is_managed(d))
1531*4882a593Smuzhiyun atomic_inc(&per_cpu_ptr(&cpu_lpi_count, cpu)->managed);
1532*4882a593Smuzhiyun else
1533*4882a593Smuzhiyun atomic_inc(&per_cpu_ptr(&cpu_lpi_count, cpu)->unmanaged);
1534*4882a593Smuzhiyun }
1535*4882a593Smuzhiyun
its_dec_lpi_count(struct irq_data * d,int cpu)1536*4882a593Smuzhiyun static void its_dec_lpi_count(struct irq_data *d, int cpu)
1537*4882a593Smuzhiyun {
1538*4882a593Smuzhiyun if (irqd_affinity_is_managed(d))
1539*4882a593Smuzhiyun atomic_dec(&per_cpu_ptr(&cpu_lpi_count, cpu)->managed);
1540*4882a593Smuzhiyun else
1541*4882a593Smuzhiyun atomic_dec(&per_cpu_ptr(&cpu_lpi_count, cpu)->unmanaged);
1542*4882a593Smuzhiyun }
1543*4882a593Smuzhiyun
cpumask_pick_least_loaded(struct irq_data * d,const struct cpumask * cpu_mask)1544*4882a593Smuzhiyun static unsigned int cpumask_pick_least_loaded(struct irq_data *d,
1545*4882a593Smuzhiyun const struct cpumask *cpu_mask)
1546*4882a593Smuzhiyun {
1547*4882a593Smuzhiyun unsigned int cpu = nr_cpu_ids, tmp;
1548*4882a593Smuzhiyun int count = S32_MAX;
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun for_each_cpu(tmp, cpu_mask) {
1551*4882a593Smuzhiyun int this_count = its_read_lpi_count(d, tmp);
1552*4882a593Smuzhiyun if (this_count < count) {
1553*4882a593Smuzhiyun cpu = tmp;
1554*4882a593Smuzhiyun count = this_count;
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun }
1557*4882a593Smuzhiyun
1558*4882a593Smuzhiyun return cpu;
1559*4882a593Smuzhiyun }
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun /*
1562*4882a593Smuzhiyun * As suggested by Thomas Gleixner in:
1563*4882a593Smuzhiyun * https://lore.kernel.org/r/87h80q2aoc.fsf@nanos.tec.linutronix.de
1564*4882a593Smuzhiyun */
its_select_cpu(struct irq_data * d,const struct cpumask * aff_mask)1565*4882a593Smuzhiyun static int its_select_cpu(struct irq_data *d,
1566*4882a593Smuzhiyun const struct cpumask *aff_mask)
1567*4882a593Smuzhiyun {
1568*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1569*4882a593Smuzhiyun cpumask_var_t tmpmask;
1570*4882a593Smuzhiyun int cpu, node;
1571*4882a593Smuzhiyun
1572*4882a593Smuzhiyun if (!alloc_cpumask_var(&tmpmask, GFP_ATOMIC))
1573*4882a593Smuzhiyun return -ENOMEM;
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun node = its_dev->its->numa_node;
1576*4882a593Smuzhiyun
1577*4882a593Smuzhiyun if (!irqd_affinity_is_managed(d)) {
1578*4882a593Smuzhiyun /* First try the NUMA node */
1579*4882a593Smuzhiyun if (node != NUMA_NO_NODE) {
1580*4882a593Smuzhiyun /*
1581*4882a593Smuzhiyun * Try the intersection of the affinity mask and the
1582*4882a593Smuzhiyun * node mask (and the online mask, just to be safe).
1583*4882a593Smuzhiyun */
1584*4882a593Smuzhiyun cpumask_and(tmpmask, cpumask_of_node(node), aff_mask);
1585*4882a593Smuzhiyun cpumask_and(tmpmask, tmpmask, cpu_online_mask);
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun /*
1588*4882a593Smuzhiyun * Ideally, we would check if the mask is empty, and
1589*4882a593Smuzhiyun * try again on the full node here.
1590*4882a593Smuzhiyun *
1591*4882a593Smuzhiyun * But it turns out that the way ACPI describes the
1592*4882a593Smuzhiyun * affinity for ITSs only deals about memory, and
1593*4882a593Smuzhiyun * not target CPUs, so it cannot describe a single
1594*4882a593Smuzhiyun * ITS placed next to two NUMA nodes.
1595*4882a593Smuzhiyun *
1596*4882a593Smuzhiyun * Instead, just fallback on the online mask. This
1597*4882a593Smuzhiyun * diverges from Thomas' suggestion above.
1598*4882a593Smuzhiyun */
1599*4882a593Smuzhiyun cpu = cpumask_pick_least_loaded(d, tmpmask);
1600*4882a593Smuzhiyun if (cpu < nr_cpu_ids)
1601*4882a593Smuzhiyun goto out;
1602*4882a593Smuzhiyun
1603*4882a593Smuzhiyun /* If we can't cross sockets, give up */
1604*4882a593Smuzhiyun if ((its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144))
1605*4882a593Smuzhiyun goto out;
1606*4882a593Smuzhiyun
1607*4882a593Smuzhiyun /* If the above failed, expand the search */
1608*4882a593Smuzhiyun }
1609*4882a593Smuzhiyun
1610*4882a593Smuzhiyun /* Try the intersection of the affinity and online masks */
1611*4882a593Smuzhiyun cpumask_and(tmpmask, aff_mask, cpu_online_mask);
1612*4882a593Smuzhiyun
1613*4882a593Smuzhiyun /* If that doesn't fly, the online mask is the last resort */
1614*4882a593Smuzhiyun if (cpumask_empty(tmpmask))
1615*4882a593Smuzhiyun cpumask_copy(tmpmask, cpu_online_mask);
1616*4882a593Smuzhiyun
1617*4882a593Smuzhiyun cpu = cpumask_pick_least_loaded(d, tmpmask);
1618*4882a593Smuzhiyun } else {
1619*4882a593Smuzhiyun cpumask_copy(tmpmask, aff_mask);
1620*4882a593Smuzhiyun
1621*4882a593Smuzhiyun /* If we cannot cross sockets, limit the search to that node */
1622*4882a593Smuzhiyun if ((its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) &&
1623*4882a593Smuzhiyun node != NUMA_NO_NODE)
1624*4882a593Smuzhiyun cpumask_and(tmpmask, tmpmask, cpumask_of_node(node));
1625*4882a593Smuzhiyun
1626*4882a593Smuzhiyun cpu = cpumask_pick_least_loaded(d, tmpmask);
1627*4882a593Smuzhiyun }
1628*4882a593Smuzhiyun out:
1629*4882a593Smuzhiyun free_cpumask_var(tmpmask);
1630*4882a593Smuzhiyun
1631*4882a593Smuzhiyun pr_debug("IRQ%d -> %*pbl CPU%d\n", d->irq, cpumask_pr_args(aff_mask), cpu);
1632*4882a593Smuzhiyun return cpu;
1633*4882a593Smuzhiyun }
1634*4882a593Smuzhiyun
its_set_affinity(struct irq_data * d,const struct cpumask * mask_val,bool force)1635*4882a593Smuzhiyun static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
1636*4882a593Smuzhiyun bool force)
1637*4882a593Smuzhiyun {
1638*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1639*4882a593Smuzhiyun struct its_collection *target_col;
1640*4882a593Smuzhiyun u32 id = its_get_event_id(d);
1641*4882a593Smuzhiyun int cpu, prev_cpu;
1642*4882a593Smuzhiyun
1643*4882a593Smuzhiyun /* A forwarded interrupt should use irq_set_vcpu_affinity */
1644*4882a593Smuzhiyun if (irqd_is_forwarded_to_vcpu(d))
1645*4882a593Smuzhiyun return -EINVAL;
1646*4882a593Smuzhiyun
1647*4882a593Smuzhiyun prev_cpu = its_dev->event_map.col_map[id];
1648*4882a593Smuzhiyun its_dec_lpi_count(d, prev_cpu);
1649*4882a593Smuzhiyun
1650*4882a593Smuzhiyun if (!force)
1651*4882a593Smuzhiyun cpu = its_select_cpu(d, mask_val);
1652*4882a593Smuzhiyun else
1653*4882a593Smuzhiyun cpu = cpumask_pick_least_loaded(d, mask_val);
1654*4882a593Smuzhiyun
1655*4882a593Smuzhiyun if (cpu < 0 || cpu >= nr_cpu_ids)
1656*4882a593Smuzhiyun goto err;
1657*4882a593Smuzhiyun
1658*4882a593Smuzhiyun /* don't set the affinity when the target cpu is same as current one */
1659*4882a593Smuzhiyun if (cpu != prev_cpu) {
1660*4882a593Smuzhiyun target_col = &its_dev->its->collections[cpu];
1661*4882a593Smuzhiyun its_send_movi(its_dev, target_col, id);
1662*4882a593Smuzhiyun its_dev->event_map.col_map[id] = cpu;
1663*4882a593Smuzhiyun irq_data_update_effective_affinity(d, cpumask_of(cpu));
1664*4882a593Smuzhiyun }
1665*4882a593Smuzhiyun
1666*4882a593Smuzhiyun its_inc_lpi_count(d, cpu);
1667*4882a593Smuzhiyun
1668*4882a593Smuzhiyun return IRQ_SET_MASK_OK_DONE;
1669*4882a593Smuzhiyun
1670*4882a593Smuzhiyun err:
1671*4882a593Smuzhiyun its_inc_lpi_count(d, prev_cpu);
1672*4882a593Smuzhiyun return -EINVAL;
1673*4882a593Smuzhiyun }
1674*4882a593Smuzhiyun
its_irq_get_msi_base(struct its_device * its_dev)1675*4882a593Smuzhiyun static u64 its_irq_get_msi_base(struct its_device *its_dev)
1676*4882a593Smuzhiyun {
1677*4882a593Smuzhiyun struct its_node *its = its_dev->its;
1678*4882a593Smuzhiyun
1679*4882a593Smuzhiyun return its->phys_base + GITS_TRANSLATER;
1680*4882a593Smuzhiyun }
1681*4882a593Smuzhiyun
its_irq_compose_msi_msg(struct irq_data * d,struct msi_msg * msg)1682*4882a593Smuzhiyun static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
1683*4882a593Smuzhiyun {
1684*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1685*4882a593Smuzhiyun struct its_node *its;
1686*4882a593Smuzhiyun u64 addr;
1687*4882a593Smuzhiyun
1688*4882a593Smuzhiyun its = its_dev->its;
1689*4882a593Smuzhiyun addr = its->get_msi_base(its_dev);
1690*4882a593Smuzhiyun
1691*4882a593Smuzhiyun msg->address_lo = lower_32_bits(addr);
1692*4882a593Smuzhiyun msg->address_hi = upper_32_bits(addr);
1693*4882a593Smuzhiyun msg->data = its_get_event_id(d);
1694*4882a593Smuzhiyun
1695*4882a593Smuzhiyun iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg);
1696*4882a593Smuzhiyun }
1697*4882a593Smuzhiyun
its_irq_set_irqchip_state(struct irq_data * d,enum irqchip_irq_state which,bool state)1698*4882a593Smuzhiyun static int its_irq_set_irqchip_state(struct irq_data *d,
1699*4882a593Smuzhiyun enum irqchip_irq_state which,
1700*4882a593Smuzhiyun bool state)
1701*4882a593Smuzhiyun {
1702*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1703*4882a593Smuzhiyun u32 event = its_get_event_id(d);
1704*4882a593Smuzhiyun
1705*4882a593Smuzhiyun if (which != IRQCHIP_STATE_PENDING)
1706*4882a593Smuzhiyun return -EINVAL;
1707*4882a593Smuzhiyun
1708*4882a593Smuzhiyun if (irqd_is_forwarded_to_vcpu(d)) {
1709*4882a593Smuzhiyun if (state)
1710*4882a593Smuzhiyun its_send_vint(its_dev, event);
1711*4882a593Smuzhiyun else
1712*4882a593Smuzhiyun its_send_vclear(its_dev, event);
1713*4882a593Smuzhiyun } else {
1714*4882a593Smuzhiyun if (state)
1715*4882a593Smuzhiyun its_send_int(its_dev, event);
1716*4882a593Smuzhiyun else
1717*4882a593Smuzhiyun its_send_clear(its_dev, event);
1718*4882a593Smuzhiyun }
1719*4882a593Smuzhiyun
1720*4882a593Smuzhiyun return 0;
1721*4882a593Smuzhiyun }
1722*4882a593Smuzhiyun
its_irq_retrigger(struct irq_data * d)1723*4882a593Smuzhiyun static int its_irq_retrigger(struct irq_data *d)
1724*4882a593Smuzhiyun {
1725*4882a593Smuzhiyun return !its_irq_set_irqchip_state(d, IRQCHIP_STATE_PENDING, true);
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun
1728*4882a593Smuzhiyun /*
1729*4882a593Smuzhiyun * Two favourable cases:
1730*4882a593Smuzhiyun *
1731*4882a593Smuzhiyun * (a) Either we have a GICv4.1, and all vPEs have to be mapped at all times
1732*4882a593Smuzhiyun * for vSGI delivery
1733*4882a593Smuzhiyun *
1734*4882a593Smuzhiyun * (b) Or the ITSs do not use a list map, meaning that VMOVP is cheap enough
1735*4882a593Smuzhiyun * and we're better off mapping all VPEs always
1736*4882a593Smuzhiyun *
1737*4882a593Smuzhiyun * If neither (a) nor (b) is true, then we map vPEs on demand.
1738*4882a593Smuzhiyun *
1739*4882a593Smuzhiyun */
gic_requires_eager_mapping(void)1740*4882a593Smuzhiyun static bool gic_requires_eager_mapping(void)
1741*4882a593Smuzhiyun {
1742*4882a593Smuzhiyun if (!its_list_map || gic_rdists->has_rvpeid)
1743*4882a593Smuzhiyun return true;
1744*4882a593Smuzhiyun
1745*4882a593Smuzhiyun return false;
1746*4882a593Smuzhiyun }
1747*4882a593Smuzhiyun
its_map_vm(struct its_node * its,struct its_vm * vm)1748*4882a593Smuzhiyun static void its_map_vm(struct its_node *its, struct its_vm *vm)
1749*4882a593Smuzhiyun {
1750*4882a593Smuzhiyun unsigned long flags;
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun if (gic_requires_eager_mapping())
1753*4882a593Smuzhiyun return;
1754*4882a593Smuzhiyun
1755*4882a593Smuzhiyun raw_spin_lock_irqsave(&vmovp_lock, flags);
1756*4882a593Smuzhiyun
1757*4882a593Smuzhiyun /*
1758*4882a593Smuzhiyun * If the VM wasn't mapped yet, iterate over the vpes and get
1759*4882a593Smuzhiyun * them mapped now.
1760*4882a593Smuzhiyun */
1761*4882a593Smuzhiyun vm->vlpi_count[its->list_nr]++;
1762*4882a593Smuzhiyun
1763*4882a593Smuzhiyun if (vm->vlpi_count[its->list_nr] == 1) {
1764*4882a593Smuzhiyun int i;
1765*4882a593Smuzhiyun
1766*4882a593Smuzhiyun for (i = 0; i < vm->nr_vpes; i++) {
1767*4882a593Smuzhiyun struct its_vpe *vpe = vm->vpes[i];
1768*4882a593Smuzhiyun struct irq_data *d = irq_get_irq_data(vpe->irq);
1769*4882a593Smuzhiyun
1770*4882a593Smuzhiyun /* Map the VPE to the first possible CPU */
1771*4882a593Smuzhiyun vpe->col_idx = cpumask_first(cpu_online_mask);
1772*4882a593Smuzhiyun its_send_vmapp(its, vpe, true);
1773*4882a593Smuzhiyun its_send_vinvall(its, vpe);
1774*4882a593Smuzhiyun irq_data_update_effective_affinity(d, cpumask_of(vpe->col_idx));
1775*4882a593Smuzhiyun }
1776*4882a593Smuzhiyun }
1777*4882a593Smuzhiyun
1778*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&vmovp_lock, flags);
1779*4882a593Smuzhiyun }
1780*4882a593Smuzhiyun
its_unmap_vm(struct its_node * its,struct its_vm * vm)1781*4882a593Smuzhiyun static void its_unmap_vm(struct its_node *its, struct its_vm *vm)
1782*4882a593Smuzhiyun {
1783*4882a593Smuzhiyun unsigned long flags;
1784*4882a593Smuzhiyun
1785*4882a593Smuzhiyun /* Not using the ITS list? Everything is always mapped. */
1786*4882a593Smuzhiyun if (gic_requires_eager_mapping())
1787*4882a593Smuzhiyun return;
1788*4882a593Smuzhiyun
1789*4882a593Smuzhiyun raw_spin_lock_irqsave(&vmovp_lock, flags);
1790*4882a593Smuzhiyun
1791*4882a593Smuzhiyun if (!--vm->vlpi_count[its->list_nr]) {
1792*4882a593Smuzhiyun int i;
1793*4882a593Smuzhiyun
1794*4882a593Smuzhiyun for (i = 0; i < vm->nr_vpes; i++)
1795*4882a593Smuzhiyun its_send_vmapp(its, vm->vpes[i], false);
1796*4882a593Smuzhiyun }
1797*4882a593Smuzhiyun
1798*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&vmovp_lock, flags);
1799*4882a593Smuzhiyun }
1800*4882a593Smuzhiyun
its_vlpi_map(struct irq_data * d,struct its_cmd_info * info)1801*4882a593Smuzhiyun static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
1802*4882a593Smuzhiyun {
1803*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1804*4882a593Smuzhiyun u32 event = its_get_event_id(d);
1805*4882a593Smuzhiyun int ret = 0;
1806*4882a593Smuzhiyun
1807*4882a593Smuzhiyun if (!info->map)
1808*4882a593Smuzhiyun return -EINVAL;
1809*4882a593Smuzhiyun
1810*4882a593Smuzhiyun raw_spin_lock(&its_dev->event_map.vlpi_lock);
1811*4882a593Smuzhiyun
1812*4882a593Smuzhiyun if (!its_dev->event_map.vm) {
1813*4882a593Smuzhiyun struct its_vlpi_map *maps;
1814*4882a593Smuzhiyun
1815*4882a593Smuzhiyun maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps),
1816*4882a593Smuzhiyun GFP_ATOMIC);
1817*4882a593Smuzhiyun if (!maps) {
1818*4882a593Smuzhiyun ret = -ENOMEM;
1819*4882a593Smuzhiyun goto out;
1820*4882a593Smuzhiyun }
1821*4882a593Smuzhiyun
1822*4882a593Smuzhiyun its_dev->event_map.vm = info->map->vm;
1823*4882a593Smuzhiyun its_dev->event_map.vlpi_maps = maps;
1824*4882a593Smuzhiyun } else if (its_dev->event_map.vm != info->map->vm) {
1825*4882a593Smuzhiyun ret = -EINVAL;
1826*4882a593Smuzhiyun goto out;
1827*4882a593Smuzhiyun }
1828*4882a593Smuzhiyun
1829*4882a593Smuzhiyun /* Get our private copy of the mapping information */
1830*4882a593Smuzhiyun its_dev->event_map.vlpi_maps[event] = *info->map;
1831*4882a593Smuzhiyun
1832*4882a593Smuzhiyun if (irqd_is_forwarded_to_vcpu(d)) {
1833*4882a593Smuzhiyun /* Already mapped, move it around */
1834*4882a593Smuzhiyun its_send_vmovi(its_dev, event);
1835*4882a593Smuzhiyun } else {
1836*4882a593Smuzhiyun /* Ensure all the VPEs are mapped on this ITS */
1837*4882a593Smuzhiyun its_map_vm(its_dev->its, info->map->vm);
1838*4882a593Smuzhiyun
1839*4882a593Smuzhiyun /*
1840*4882a593Smuzhiyun * Flag the interrupt as forwarded so that we can
1841*4882a593Smuzhiyun * start poking the virtual property table.
1842*4882a593Smuzhiyun */
1843*4882a593Smuzhiyun irqd_set_forwarded_to_vcpu(d);
1844*4882a593Smuzhiyun
1845*4882a593Smuzhiyun /* Write out the property to the prop table */
1846*4882a593Smuzhiyun lpi_write_config(d, 0xff, info->map->properties);
1847*4882a593Smuzhiyun
1848*4882a593Smuzhiyun /* Drop the physical mapping */
1849*4882a593Smuzhiyun its_send_discard(its_dev, event);
1850*4882a593Smuzhiyun
1851*4882a593Smuzhiyun /* and install the virtual one */
1852*4882a593Smuzhiyun its_send_vmapti(its_dev, event);
1853*4882a593Smuzhiyun
1854*4882a593Smuzhiyun /* Increment the number of VLPIs */
1855*4882a593Smuzhiyun its_dev->event_map.nr_vlpis++;
1856*4882a593Smuzhiyun }
1857*4882a593Smuzhiyun
1858*4882a593Smuzhiyun out:
1859*4882a593Smuzhiyun raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1860*4882a593Smuzhiyun return ret;
1861*4882a593Smuzhiyun }
1862*4882a593Smuzhiyun
its_vlpi_get(struct irq_data * d,struct its_cmd_info * info)1863*4882a593Smuzhiyun static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
1864*4882a593Smuzhiyun {
1865*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1866*4882a593Smuzhiyun struct its_vlpi_map *map;
1867*4882a593Smuzhiyun int ret = 0;
1868*4882a593Smuzhiyun
1869*4882a593Smuzhiyun raw_spin_lock(&its_dev->event_map.vlpi_lock);
1870*4882a593Smuzhiyun
1871*4882a593Smuzhiyun map = get_vlpi_map(d);
1872*4882a593Smuzhiyun
1873*4882a593Smuzhiyun if (!its_dev->event_map.vm || !map) {
1874*4882a593Smuzhiyun ret = -EINVAL;
1875*4882a593Smuzhiyun goto out;
1876*4882a593Smuzhiyun }
1877*4882a593Smuzhiyun
1878*4882a593Smuzhiyun /* Copy our mapping information to the incoming request */
1879*4882a593Smuzhiyun *info->map = *map;
1880*4882a593Smuzhiyun
1881*4882a593Smuzhiyun out:
1882*4882a593Smuzhiyun raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1883*4882a593Smuzhiyun return ret;
1884*4882a593Smuzhiyun }
1885*4882a593Smuzhiyun
its_vlpi_unmap(struct irq_data * d)1886*4882a593Smuzhiyun static int its_vlpi_unmap(struct irq_data *d)
1887*4882a593Smuzhiyun {
1888*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1889*4882a593Smuzhiyun u32 event = its_get_event_id(d);
1890*4882a593Smuzhiyun int ret = 0;
1891*4882a593Smuzhiyun
1892*4882a593Smuzhiyun raw_spin_lock(&its_dev->event_map.vlpi_lock);
1893*4882a593Smuzhiyun
1894*4882a593Smuzhiyun if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d)) {
1895*4882a593Smuzhiyun ret = -EINVAL;
1896*4882a593Smuzhiyun goto out;
1897*4882a593Smuzhiyun }
1898*4882a593Smuzhiyun
1899*4882a593Smuzhiyun /* Drop the virtual mapping */
1900*4882a593Smuzhiyun its_send_discard(its_dev, event);
1901*4882a593Smuzhiyun
1902*4882a593Smuzhiyun /* and restore the physical one */
1903*4882a593Smuzhiyun irqd_clr_forwarded_to_vcpu(d);
1904*4882a593Smuzhiyun its_send_mapti(its_dev, d->hwirq, event);
1905*4882a593Smuzhiyun lpi_update_config(d, 0xff, (LPI_PROP_DEFAULT_PRIO |
1906*4882a593Smuzhiyun LPI_PROP_ENABLED |
1907*4882a593Smuzhiyun LPI_PROP_GROUP1));
1908*4882a593Smuzhiyun
1909*4882a593Smuzhiyun /* Potentially unmap the VM from this ITS */
1910*4882a593Smuzhiyun its_unmap_vm(its_dev->its, its_dev->event_map.vm);
1911*4882a593Smuzhiyun
1912*4882a593Smuzhiyun /*
1913*4882a593Smuzhiyun * Drop the refcount and make the device available again if
1914*4882a593Smuzhiyun * this was the last VLPI.
1915*4882a593Smuzhiyun */
1916*4882a593Smuzhiyun if (!--its_dev->event_map.nr_vlpis) {
1917*4882a593Smuzhiyun its_dev->event_map.vm = NULL;
1918*4882a593Smuzhiyun kfree(its_dev->event_map.vlpi_maps);
1919*4882a593Smuzhiyun }
1920*4882a593Smuzhiyun
1921*4882a593Smuzhiyun out:
1922*4882a593Smuzhiyun raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1923*4882a593Smuzhiyun return ret;
1924*4882a593Smuzhiyun }
1925*4882a593Smuzhiyun
its_vlpi_prop_update(struct irq_data * d,struct its_cmd_info * info)1926*4882a593Smuzhiyun static int its_vlpi_prop_update(struct irq_data *d, struct its_cmd_info *info)
1927*4882a593Smuzhiyun {
1928*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1929*4882a593Smuzhiyun
1930*4882a593Smuzhiyun if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d))
1931*4882a593Smuzhiyun return -EINVAL;
1932*4882a593Smuzhiyun
1933*4882a593Smuzhiyun if (info->cmd_type == PROP_UPDATE_AND_INV_VLPI)
1934*4882a593Smuzhiyun lpi_update_config(d, 0xff, info->config);
1935*4882a593Smuzhiyun else
1936*4882a593Smuzhiyun lpi_write_config(d, 0xff, info->config);
1937*4882a593Smuzhiyun its_vlpi_set_doorbell(d, !!(info->config & LPI_PROP_ENABLED));
1938*4882a593Smuzhiyun
1939*4882a593Smuzhiyun return 0;
1940*4882a593Smuzhiyun }
1941*4882a593Smuzhiyun
its_irq_set_vcpu_affinity(struct irq_data * d,void * vcpu_info)1942*4882a593Smuzhiyun static int its_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
1943*4882a593Smuzhiyun {
1944*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
1945*4882a593Smuzhiyun struct its_cmd_info *info = vcpu_info;
1946*4882a593Smuzhiyun
1947*4882a593Smuzhiyun /* Need a v4 ITS */
1948*4882a593Smuzhiyun if (!is_v4(its_dev->its))
1949*4882a593Smuzhiyun return -EINVAL;
1950*4882a593Smuzhiyun
1951*4882a593Smuzhiyun /* Unmap request? */
1952*4882a593Smuzhiyun if (!info)
1953*4882a593Smuzhiyun return its_vlpi_unmap(d);
1954*4882a593Smuzhiyun
1955*4882a593Smuzhiyun switch (info->cmd_type) {
1956*4882a593Smuzhiyun case MAP_VLPI:
1957*4882a593Smuzhiyun return its_vlpi_map(d, info);
1958*4882a593Smuzhiyun
1959*4882a593Smuzhiyun case GET_VLPI:
1960*4882a593Smuzhiyun return its_vlpi_get(d, info);
1961*4882a593Smuzhiyun
1962*4882a593Smuzhiyun case PROP_UPDATE_VLPI:
1963*4882a593Smuzhiyun case PROP_UPDATE_AND_INV_VLPI:
1964*4882a593Smuzhiyun return its_vlpi_prop_update(d, info);
1965*4882a593Smuzhiyun
1966*4882a593Smuzhiyun default:
1967*4882a593Smuzhiyun return -EINVAL;
1968*4882a593Smuzhiyun }
1969*4882a593Smuzhiyun }
1970*4882a593Smuzhiyun
1971*4882a593Smuzhiyun static struct irq_chip its_irq_chip = {
1972*4882a593Smuzhiyun .name = "ITS",
1973*4882a593Smuzhiyun .irq_mask = its_mask_irq,
1974*4882a593Smuzhiyun .irq_unmask = its_unmask_irq,
1975*4882a593Smuzhiyun .irq_eoi = irq_chip_eoi_parent,
1976*4882a593Smuzhiyun .irq_set_affinity = its_set_affinity,
1977*4882a593Smuzhiyun .irq_compose_msi_msg = its_irq_compose_msi_msg,
1978*4882a593Smuzhiyun .irq_set_irqchip_state = its_irq_set_irqchip_state,
1979*4882a593Smuzhiyun .irq_retrigger = its_irq_retrigger,
1980*4882a593Smuzhiyun .irq_set_vcpu_affinity = its_irq_set_vcpu_affinity,
1981*4882a593Smuzhiyun };
1982*4882a593Smuzhiyun
1983*4882a593Smuzhiyun
1984*4882a593Smuzhiyun /*
1985*4882a593Smuzhiyun * How we allocate LPIs:
1986*4882a593Smuzhiyun *
1987*4882a593Smuzhiyun * lpi_range_list contains ranges of LPIs that are to available to
1988*4882a593Smuzhiyun * allocate from. To allocate LPIs, just pick the first range that
1989*4882a593Smuzhiyun * fits the required allocation, and reduce it by the required
1990*4882a593Smuzhiyun * amount. Once empty, remove the range from the list.
1991*4882a593Smuzhiyun *
1992*4882a593Smuzhiyun * To free a range of LPIs, add a free range to the list, sort it and
1993*4882a593Smuzhiyun * merge the result if the new range happens to be adjacent to an
1994*4882a593Smuzhiyun * already free block.
1995*4882a593Smuzhiyun *
1996*4882a593Smuzhiyun * The consequence of the above is that allocation is cost is low, but
1997*4882a593Smuzhiyun * freeing is expensive. We assumes that freeing rarely occurs.
1998*4882a593Smuzhiyun */
1999*4882a593Smuzhiyun #define ITS_MAX_LPI_NRBITS 16 /* 64K LPIs */
2000*4882a593Smuzhiyun
2001*4882a593Smuzhiyun static DEFINE_MUTEX(lpi_range_lock);
2002*4882a593Smuzhiyun static LIST_HEAD(lpi_range_list);
2003*4882a593Smuzhiyun
2004*4882a593Smuzhiyun struct lpi_range {
2005*4882a593Smuzhiyun struct list_head entry;
2006*4882a593Smuzhiyun u32 base_id;
2007*4882a593Smuzhiyun u32 span;
2008*4882a593Smuzhiyun };
2009*4882a593Smuzhiyun
mk_lpi_range(u32 base,u32 span)2010*4882a593Smuzhiyun static struct lpi_range *mk_lpi_range(u32 base, u32 span)
2011*4882a593Smuzhiyun {
2012*4882a593Smuzhiyun struct lpi_range *range;
2013*4882a593Smuzhiyun
2014*4882a593Smuzhiyun range = kmalloc(sizeof(*range), GFP_KERNEL);
2015*4882a593Smuzhiyun if (range) {
2016*4882a593Smuzhiyun range->base_id = base;
2017*4882a593Smuzhiyun range->span = span;
2018*4882a593Smuzhiyun }
2019*4882a593Smuzhiyun
2020*4882a593Smuzhiyun return range;
2021*4882a593Smuzhiyun }
2022*4882a593Smuzhiyun
alloc_lpi_range(u32 nr_lpis,u32 * base)2023*4882a593Smuzhiyun static int alloc_lpi_range(u32 nr_lpis, u32 *base)
2024*4882a593Smuzhiyun {
2025*4882a593Smuzhiyun struct lpi_range *range, *tmp;
2026*4882a593Smuzhiyun int err = -ENOSPC;
2027*4882a593Smuzhiyun
2028*4882a593Smuzhiyun mutex_lock(&lpi_range_lock);
2029*4882a593Smuzhiyun
2030*4882a593Smuzhiyun list_for_each_entry_safe(range, tmp, &lpi_range_list, entry) {
2031*4882a593Smuzhiyun if (range->span >= nr_lpis) {
2032*4882a593Smuzhiyun *base = range->base_id;
2033*4882a593Smuzhiyun range->base_id += nr_lpis;
2034*4882a593Smuzhiyun range->span -= nr_lpis;
2035*4882a593Smuzhiyun
2036*4882a593Smuzhiyun if (range->span == 0) {
2037*4882a593Smuzhiyun list_del(&range->entry);
2038*4882a593Smuzhiyun kfree(range);
2039*4882a593Smuzhiyun }
2040*4882a593Smuzhiyun
2041*4882a593Smuzhiyun err = 0;
2042*4882a593Smuzhiyun break;
2043*4882a593Smuzhiyun }
2044*4882a593Smuzhiyun }
2045*4882a593Smuzhiyun
2046*4882a593Smuzhiyun mutex_unlock(&lpi_range_lock);
2047*4882a593Smuzhiyun
2048*4882a593Smuzhiyun pr_debug("ITS: alloc %u:%u\n", *base, nr_lpis);
2049*4882a593Smuzhiyun return err;
2050*4882a593Smuzhiyun }
2051*4882a593Smuzhiyun
merge_lpi_ranges(struct lpi_range * a,struct lpi_range * b)2052*4882a593Smuzhiyun static void merge_lpi_ranges(struct lpi_range *a, struct lpi_range *b)
2053*4882a593Smuzhiyun {
2054*4882a593Smuzhiyun if (&a->entry == &lpi_range_list || &b->entry == &lpi_range_list)
2055*4882a593Smuzhiyun return;
2056*4882a593Smuzhiyun if (a->base_id + a->span != b->base_id)
2057*4882a593Smuzhiyun return;
2058*4882a593Smuzhiyun b->base_id = a->base_id;
2059*4882a593Smuzhiyun b->span += a->span;
2060*4882a593Smuzhiyun list_del(&a->entry);
2061*4882a593Smuzhiyun kfree(a);
2062*4882a593Smuzhiyun }
2063*4882a593Smuzhiyun
free_lpi_range(u32 base,u32 nr_lpis)2064*4882a593Smuzhiyun static int free_lpi_range(u32 base, u32 nr_lpis)
2065*4882a593Smuzhiyun {
2066*4882a593Smuzhiyun struct lpi_range *new, *old;
2067*4882a593Smuzhiyun
2068*4882a593Smuzhiyun new = mk_lpi_range(base, nr_lpis);
2069*4882a593Smuzhiyun if (!new)
2070*4882a593Smuzhiyun return -ENOMEM;
2071*4882a593Smuzhiyun
2072*4882a593Smuzhiyun mutex_lock(&lpi_range_lock);
2073*4882a593Smuzhiyun
2074*4882a593Smuzhiyun list_for_each_entry_reverse(old, &lpi_range_list, entry) {
2075*4882a593Smuzhiyun if (old->base_id < base)
2076*4882a593Smuzhiyun break;
2077*4882a593Smuzhiyun }
2078*4882a593Smuzhiyun /*
2079*4882a593Smuzhiyun * old is the last element with ->base_id smaller than base,
2080*4882a593Smuzhiyun * so new goes right after it. If there are no elements with
2081*4882a593Smuzhiyun * ->base_id smaller than base, &old->entry ends up pointing
2082*4882a593Smuzhiyun * at the head of the list, and inserting new it the start of
2083*4882a593Smuzhiyun * the list is the right thing to do in that case as well.
2084*4882a593Smuzhiyun */
2085*4882a593Smuzhiyun list_add(&new->entry, &old->entry);
2086*4882a593Smuzhiyun /*
2087*4882a593Smuzhiyun * Now check if we can merge with the preceding and/or
2088*4882a593Smuzhiyun * following ranges.
2089*4882a593Smuzhiyun */
2090*4882a593Smuzhiyun merge_lpi_ranges(old, new);
2091*4882a593Smuzhiyun merge_lpi_ranges(new, list_next_entry(new, entry));
2092*4882a593Smuzhiyun
2093*4882a593Smuzhiyun mutex_unlock(&lpi_range_lock);
2094*4882a593Smuzhiyun return 0;
2095*4882a593Smuzhiyun }
2096*4882a593Smuzhiyun
its_lpi_init(u32 id_bits)2097*4882a593Smuzhiyun static int __init its_lpi_init(u32 id_bits)
2098*4882a593Smuzhiyun {
2099*4882a593Smuzhiyun u32 lpis = (1UL << id_bits) - 8192;
2100*4882a593Smuzhiyun u32 numlpis;
2101*4882a593Smuzhiyun int err;
2102*4882a593Smuzhiyun
2103*4882a593Smuzhiyun numlpis = 1UL << GICD_TYPER_NUM_LPIS(gic_rdists->gicd_typer);
2104*4882a593Smuzhiyun
2105*4882a593Smuzhiyun if (numlpis > 2 && !WARN_ON(numlpis > lpis)) {
2106*4882a593Smuzhiyun lpis = numlpis;
2107*4882a593Smuzhiyun pr_info("ITS: Using hypervisor restricted LPI range [%u]\n",
2108*4882a593Smuzhiyun lpis);
2109*4882a593Smuzhiyun }
2110*4882a593Smuzhiyun
2111*4882a593Smuzhiyun /*
2112*4882a593Smuzhiyun * Initializing the allocator is just the same as freeing the
2113*4882a593Smuzhiyun * full range of LPIs.
2114*4882a593Smuzhiyun */
2115*4882a593Smuzhiyun err = free_lpi_range(8192, lpis);
2116*4882a593Smuzhiyun pr_debug("ITS: Allocator initialized for %u LPIs\n", lpis);
2117*4882a593Smuzhiyun return err;
2118*4882a593Smuzhiyun }
2119*4882a593Smuzhiyun
its_lpi_alloc(int nr_irqs,u32 * base,int * nr_ids)2120*4882a593Smuzhiyun static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids)
2121*4882a593Smuzhiyun {
2122*4882a593Smuzhiyun unsigned long *bitmap = NULL;
2123*4882a593Smuzhiyun int err = 0;
2124*4882a593Smuzhiyun
2125*4882a593Smuzhiyun do {
2126*4882a593Smuzhiyun err = alloc_lpi_range(nr_irqs, base);
2127*4882a593Smuzhiyun if (!err)
2128*4882a593Smuzhiyun break;
2129*4882a593Smuzhiyun
2130*4882a593Smuzhiyun nr_irqs /= 2;
2131*4882a593Smuzhiyun } while (nr_irqs > 0);
2132*4882a593Smuzhiyun
2133*4882a593Smuzhiyun if (!nr_irqs)
2134*4882a593Smuzhiyun err = -ENOSPC;
2135*4882a593Smuzhiyun
2136*4882a593Smuzhiyun if (err)
2137*4882a593Smuzhiyun goto out;
2138*4882a593Smuzhiyun
2139*4882a593Smuzhiyun bitmap = kcalloc(BITS_TO_LONGS(nr_irqs), sizeof (long), GFP_ATOMIC);
2140*4882a593Smuzhiyun if (!bitmap)
2141*4882a593Smuzhiyun goto out;
2142*4882a593Smuzhiyun
2143*4882a593Smuzhiyun *nr_ids = nr_irqs;
2144*4882a593Smuzhiyun
2145*4882a593Smuzhiyun out:
2146*4882a593Smuzhiyun if (!bitmap)
2147*4882a593Smuzhiyun *base = *nr_ids = 0;
2148*4882a593Smuzhiyun
2149*4882a593Smuzhiyun return bitmap;
2150*4882a593Smuzhiyun }
2151*4882a593Smuzhiyun
its_lpi_free(unsigned long * bitmap,u32 base,u32 nr_ids)2152*4882a593Smuzhiyun static void its_lpi_free(unsigned long *bitmap, u32 base, u32 nr_ids)
2153*4882a593Smuzhiyun {
2154*4882a593Smuzhiyun WARN_ON(free_lpi_range(base, nr_ids));
2155*4882a593Smuzhiyun kfree(bitmap);
2156*4882a593Smuzhiyun }
2157*4882a593Smuzhiyun
gic_reset_prop_table(void * va)2158*4882a593Smuzhiyun static void gic_reset_prop_table(void *va)
2159*4882a593Smuzhiyun {
2160*4882a593Smuzhiyun /* Priority 0xa0, Group-1, disabled */
2161*4882a593Smuzhiyun memset(va, LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1, LPI_PROPBASE_SZ);
2162*4882a593Smuzhiyun
2163*4882a593Smuzhiyun /* Make sure the GIC will observe the written configuration */
2164*4882a593Smuzhiyun gic_flush_dcache_to_poc(va, LPI_PROPBASE_SZ);
2165*4882a593Smuzhiyun }
2166*4882a593Smuzhiyun
its_allocate_prop_table(gfp_t gfp_flags)2167*4882a593Smuzhiyun static struct page *its_allocate_prop_table(gfp_t gfp_flags)
2168*4882a593Smuzhiyun {
2169*4882a593Smuzhiyun struct page *prop_page;
2170*4882a593Smuzhiyun
2171*4882a593Smuzhiyun if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566"))
2172*4882a593Smuzhiyun gfp_flags |= GFP_DMA32;
2173*4882a593Smuzhiyun prop_page = alloc_pages(gfp_flags, get_order(LPI_PROPBASE_SZ));
2174*4882a593Smuzhiyun if (!prop_page)
2175*4882a593Smuzhiyun return NULL;
2176*4882a593Smuzhiyun
2177*4882a593Smuzhiyun gic_reset_prop_table(page_address(prop_page));
2178*4882a593Smuzhiyun
2179*4882a593Smuzhiyun return prop_page;
2180*4882a593Smuzhiyun }
2181*4882a593Smuzhiyun
its_free_prop_table(struct page * prop_page)2182*4882a593Smuzhiyun static void its_free_prop_table(struct page *prop_page)
2183*4882a593Smuzhiyun {
2184*4882a593Smuzhiyun free_pages((unsigned long)page_address(prop_page),
2185*4882a593Smuzhiyun get_order(LPI_PROPBASE_SZ));
2186*4882a593Smuzhiyun }
2187*4882a593Smuzhiyun
gic_check_reserved_range(phys_addr_t addr,unsigned long size)2188*4882a593Smuzhiyun static bool gic_check_reserved_range(phys_addr_t addr, unsigned long size)
2189*4882a593Smuzhiyun {
2190*4882a593Smuzhiyun phys_addr_t start, end, addr_end;
2191*4882a593Smuzhiyun u64 i;
2192*4882a593Smuzhiyun
2193*4882a593Smuzhiyun /*
2194*4882a593Smuzhiyun * We don't bother checking for a kdump kernel as by
2195*4882a593Smuzhiyun * construction, the LPI tables are out of this kernel's
2196*4882a593Smuzhiyun * memory map.
2197*4882a593Smuzhiyun */
2198*4882a593Smuzhiyun if (is_kdump_kernel())
2199*4882a593Smuzhiyun return true;
2200*4882a593Smuzhiyun
2201*4882a593Smuzhiyun addr_end = addr + size - 1;
2202*4882a593Smuzhiyun
2203*4882a593Smuzhiyun for_each_reserved_mem_range(i, &start, &end) {
2204*4882a593Smuzhiyun if (addr >= start && addr_end <= end)
2205*4882a593Smuzhiyun return true;
2206*4882a593Smuzhiyun }
2207*4882a593Smuzhiyun
2208*4882a593Smuzhiyun /* Not found, not a good sign... */
2209*4882a593Smuzhiyun pr_warn("GICv3: Expected reserved range [%pa:%pa], not found\n",
2210*4882a593Smuzhiyun &addr, &addr_end);
2211*4882a593Smuzhiyun add_taint(TAINT_CRAP, LOCKDEP_STILL_OK);
2212*4882a593Smuzhiyun return false;
2213*4882a593Smuzhiyun }
2214*4882a593Smuzhiyun
gic_reserve_range(phys_addr_t addr,unsigned long size)2215*4882a593Smuzhiyun static int gic_reserve_range(phys_addr_t addr, unsigned long size)
2216*4882a593Smuzhiyun {
2217*4882a593Smuzhiyun if (efi_enabled(EFI_CONFIG_TABLES))
2218*4882a593Smuzhiyun return efi_mem_reserve_persistent(addr, size);
2219*4882a593Smuzhiyun
2220*4882a593Smuzhiyun return 0;
2221*4882a593Smuzhiyun }
2222*4882a593Smuzhiyun
its_setup_lpi_prop_table(void)2223*4882a593Smuzhiyun static int __init its_setup_lpi_prop_table(void)
2224*4882a593Smuzhiyun {
2225*4882a593Smuzhiyun if (gic_rdists->flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED) {
2226*4882a593Smuzhiyun u64 val;
2227*4882a593Smuzhiyun
2228*4882a593Smuzhiyun val = gicr_read_propbaser(gic_data_rdist_rd_base() + GICR_PROPBASER);
2229*4882a593Smuzhiyun lpi_id_bits = (val & GICR_PROPBASER_IDBITS_MASK) + 1;
2230*4882a593Smuzhiyun
2231*4882a593Smuzhiyun gic_rdists->prop_table_pa = val & GENMASK_ULL(51, 12);
2232*4882a593Smuzhiyun gic_rdists->prop_table_va = memremap(gic_rdists->prop_table_pa,
2233*4882a593Smuzhiyun LPI_PROPBASE_SZ,
2234*4882a593Smuzhiyun MEMREMAP_WB);
2235*4882a593Smuzhiyun gic_reset_prop_table(gic_rdists->prop_table_va);
2236*4882a593Smuzhiyun } else {
2237*4882a593Smuzhiyun struct page *page;
2238*4882a593Smuzhiyun
2239*4882a593Smuzhiyun lpi_id_bits = min_t(u32,
2240*4882a593Smuzhiyun GICD_TYPER_ID_BITS(gic_rdists->gicd_typer),
2241*4882a593Smuzhiyun ITS_MAX_LPI_NRBITS);
2242*4882a593Smuzhiyun page = its_allocate_prop_table(GFP_NOWAIT);
2243*4882a593Smuzhiyun if (!page) {
2244*4882a593Smuzhiyun pr_err("Failed to allocate PROPBASE\n");
2245*4882a593Smuzhiyun return -ENOMEM;
2246*4882a593Smuzhiyun }
2247*4882a593Smuzhiyun
2248*4882a593Smuzhiyun gic_rdists->prop_table_pa = page_to_phys(page);
2249*4882a593Smuzhiyun gic_rdists->prop_table_va = page_address(page);
2250*4882a593Smuzhiyun WARN_ON(gic_reserve_range(gic_rdists->prop_table_pa,
2251*4882a593Smuzhiyun LPI_PROPBASE_SZ));
2252*4882a593Smuzhiyun }
2253*4882a593Smuzhiyun
2254*4882a593Smuzhiyun pr_info("GICv3: using LPI property table @%pa\n",
2255*4882a593Smuzhiyun &gic_rdists->prop_table_pa);
2256*4882a593Smuzhiyun
2257*4882a593Smuzhiyun return its_lpi_init(lpi_id_bits);
2258*4882a593Smuzhiyun }
2259*4882a593Smuzhiyun
2260*4882a593Smuzhiyun static const char *its_base_type_string[] = {
2261*4882a593Smuzhiyun [GITS_BASER_TYPE_DEVICE] = "Devices",
2262*4882a593Smuzhiyun [GITS_BASER_TYPE_VCPU] = "Virtual CPUs",
2263*4882a593Smuzhiyun [GITS_BASER_TYPE_RESERVED3] = "Reserved (3)",
2264*4882a593Smuzhiyun [GITS_BASER_TYPE_COLLECTION] = "Interrupt Collections",
2265*4882a593Smuzhiyun [GITS_BASER_TYPE_RESERVED5] = "Reserved (5)",
2266*4882a593Smuzhiyun [GITS_BASER_TYPE_RESERVED6] = "Reserved (6)",
2267*4882a593Smuzhiyun [GITS_BASER_TYPE_RESERVED7] = "Reserved (7)",
2268*4882a593Smuzhiyun };
2269*4882a593Smuzhiyun
its_read_baser(struct its_node * its,struct its_baser * baser)2270*4882a593Smuzhiyun static u64 its_read_baser(struct its_node *its, struct its_baser *baser)
2271*4882a593Smuzhiyun {
2272*4882a593Smuzhiyun u32 idx = baser - its->tables;
2273*4882a593Smuzhiyun
2274*4882a593Smuzhiyun return gits_read_baser(its->base + GITS_BASER + (idx << 3));
2275*4882a593Smuzhiyun }
2276*4882a593Smuzhiyun
its_write_baser(struct its_node * its,struct its_baser * baser,u64 val)2277*4882a593Smuzhiyun static void its_write_baser(struct its_node *its, struct its_baser *baser,
2278*4882a593Smuzhiyun u64 val)
2279*4882a593Smuzhiyun {
2280*4882a593Smuzhiyun u32 idx = baser - its->tables;
2281*4882a593Smuzhiyun
2282*4882a593Smuzhiyun gits_write_baser(val, its->base + GITS_BASER + (idx << 3));
2283*4882a593Smuzhiyun baser->val = its_read_baser(its, baser);
2284*4882a593Smuzhiyun }
2285*4882a593Smuzhiyun
its_setup_baser(struct its_node * its,struct its_baser * baser,u64 cache,u64 shr,u32 order,bool indirect)2286*4882a593Smuzhiyun static int its_setup_baser(struct its_node *its, struct its_baser *baser,
2287*4882a593Smuzhiyun u64 cache, u64 shr, u32 order, bool indirect)
2288*4882a593Smuzhiyun {
2289*4882a593Smuzhiyun u64 val = its_read_baser(its, baser);
2290*4882a593Smuzhiyun u64 esz = GITS_BASER_ENTRY_SIZE(val);
2291*4882a593Smuzhiyun u64 type = GITS_BASER_TYPE(val);
2292*4882a593Smuzhiyun u64 baser_phys, tmp;
2293*4882a593Smuzhiyun u32 alloc_pages, psz;
2294*4882a593Smuzhiyun struct page *page;
2295*4882a593Smuzhiyun void *base;
2296*4882a593Smuzhiyun gfp_t gfp_flags;
2297*4882a593Smuzhiyun
2298*4882a593Smuzhiyun psz = baser->psz;
2299*4882a593Smuzhiyun alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
2300*4882a593Smuzhiyun if (alloc_pages > GITS_BASER_PAGES_MAX) {
2301*4882a593Smuzhiyun pr_warn("ITS@%pa: %s too large, reduce ITS pages %u->%u\n",
2302*4882a593Smuzhiyun &its->phys_base, its_base_type_string[type],
2303*4882a593Smuzhiyun alloc_pages, GITS_BASER_PAGES_MAX);
2304*4882a593Smuzhiyun alloc_pages = GITS_BASER_PAGES_MAX;
2305*4882a593Smuzhiyun order = get_order(GITS_BASER_PAGES_MAX * psz);
2306*4882a593Smuzhiyun }
2307*4882a593Smuzhiyun
2308*4882a593Smuzhiyun gfp_flags = GFP_KERNEL | __GFP_ZERO;
2309*4882a593Smuzhiyun if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566"))
2310*4882a593Smuzhiyun gfp_flags |= GFP_DMA32;
2311*4882a593Smuzhiyun page = alloc_pages_node(its->numa_node, gfp_flags, order);
2312*4882a593Smuzhiyun if (!page)
2313*4882a593Smuzhiyun return -ENOMEM;
2314*4882a593Smuzhiyun
2315*4882a593Smuzhiyun base = (void *)page_address(page);
2316*4882a593Smuzhiyun baser_phys = virt_to_phys(base);
2317*4882a593Smuzhiyun
2318*4882a593Smuzhiyun /* Check if the physical address of the memory is above 48bits */
2319*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_ARM64_64K_PAGES) && (baser_phys >> 48)) {
2320*4882a593Smuzhiyun
2321*4882a593Smuzhiyun /* 52bit PA is supported only when PageSize=64K */
2322*4882a593Smuzhiyun if (psz != SZ_64K) {
2323*4882a593Smuzhiyun pr_err("ITS: no 52bit PA support when psz=%d\n", psz);
2324*4882a593Smuzhiyun free_pages((unsigned long)base, order);
2325*4882a593Smuzhiyun return -ENXIO;
2326*4882a593Smuzhiyun }
2327*4882a593Smuzhiyun
2328*4882a593Smuzhiyun /* Convert 52bit PA to 48bit field */
2329*4882a593Smuzhiyun baser_phys = GITS_BASER_PHYS_52_to_48(baser_phys);
2330*4882a593Smuzhiyun }
2331*4882a593Smuzhiyun
2332*4882a593Smuzhiyun retry_baser:
2333*4882a593Smuzhiyun val = (baser_phys |
2334*4882a593Smuzhiyun (type << GITS_BASER_TYPE_SHIFT) |
2335*4882a593Smuzhiyun ((esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
2336*4882a593Smuzhiyun ((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT) |
2337*4882a593Smuzhiyun cache |
2338*4882a593Smuzhiyun shr |
2339*4882a593Smuzhiyun GITS_BASER_VALID);
2340*4882a593Smuzhiyun
2341*4882a593Smuzhiyun val |= indirect ? GITS_BASER_INDIRECT : 0x0;
2342*4882a593Smuzhiyun
2343*4882a593Smuzhiyun switch (psz) {
2344*4882a593Smuzhiyun case SZ_4K:
2345*4882a593Smuzhiyun val |= GITS_BASER_PAGE_SIZE_4K;
2346*4882a593Smuzhiyun break;
2347*4882a593Smuzhiyun case SZ_16K:
2348*4882a593Smuzhiyun val |= GITS_BASER_PAGE_SIZE_16K;
2349*4882a593Smuzhiyun break;
2350*4882a593Smuzhiyun case SZ_64K:
2351*4882a593Smuzhiyun val |= GITS_BASER_PAGE_SIZE_64K;
2352*4882a593Smuzhiyun break;
2353*4882a593Smuzhiyun }
2354*4882a593Smuzhiyun
2355*4882a593Smuzhiyun its_write_baser(its, baser, val);
2356*4882a593Smuzhiyun tmp = baser->val;
2357*4882a593Smuzhiyun
2358*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_NO_GKI) &&
2359*4882a593Smuzhiyun (of_machine_is_compatible("rockchip,rk3568") ||
2360*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3566") ||
2361*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3588"))) {
2362*4882a593Smuzhiyun if (tmp & GITS_BASER_SHAREABILITY_MASK)
2363*4882a593Smuzhiyun tmp &= ~GITS_BASER_SHAREABILITY_MASK;
2364*4882a593Smuzhiyun else
2365*4882a593Smuzhiyun gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order));
2366*4882a593Smuzhiyun }
2367*4882a593Smuzhiyun
2368*4882a593Smuzhiyun if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
2369*4882a593Smuzhiyun /*
2370*4882a593Smuzhiyun * Shareability didn't stick. Just use
2371*4882a593Smuzhiyun * whatever the read reported, which is likely
2372*4882a593Smuzhiyun * to be the only thing this redistributor
2373*4882a593Smuzhiyun * supports. If that's zero, make it
2374*4882a593Smuzhiyun * non-cacheable as well.
2375*4882a593Smuzhiyun */
2376*4882a593Smuzhiyun shr = tmp & GITS_BASER_SHAREABILITY_MASK;
2377*4882a593Smuzhiyun if (!shr) {
2378*4882a593Smuzhiyun cache = GITS_BASER_nC;
2379*4882a593Smuzhiyun gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order));
2380*4882a593Smuzhiyun }
2381*4882a593Smuzhiyun goto retry_baser;
2382*4882a593Smuzhiyun }
2383*4882a593Smuzhiyun
2384*4882a593Smuzhiyun if (val != tmp) {
2385*4882a593Smuzhiyun pr_err("ITS@%pa: %s doesn't stick: %llx %llx\n",
2386*4882a593Smuzhiyun &its->phys_base, its_base_type_string[type],
2387*4882a593Smuzhiyun val, tmp);
2388*4882a593Smuzhiyun free_pages((unsigned long)base, order);
2389*4882a593Smuzhiyun return -ENXIO;
2390*4882a593Smuzhiyun }
2391*4882a593Smuzhiyun
2392*4882a593Smuzhiyun baser->order = order;
2393*4882a593Smuzhiyun baser->base = base;
2394*4882a593Smuzhiyun baser->psz = psz;
2395*4882a593Smuzhiyun tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;
2396*4882a593Smuzhiyun
2397*4882a593Smuzhiyun pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
2398*4882a593Smuzhiyun &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / (int)tmp),
2399*4882a593Smuzhiyun its_base_type_string[type],
2400*4882a593Smuzhiyun (unsigned long)virt_to_phys(base),
2401*4882a593Smuzhiyun indirect ? "indirect" : "flat", (int)esz,
2402*4882a593Smuzhiyun psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
2403*4882a593Smuzhiyun
2404*4882a593Smuzhiyun return 0;
2405*4882a593Smuzhiyun }
2406*4882a593Smuzhiyun
its_parse_indirect_baser(struct its_node * its,struct its_baser * baser,u32 * order,u32 ids)2407*4882a593Smuzhiyun static bool its_parse_indirect_baser(struct its_node *its,
2408*4882a593Smuzhiyun struct its_baser *baser,
2409*4882a593Smuzhiyun u32 *order, u32 ids)
2410*4882a593Smuzhiyun {
2411*4882a593Smuzhiyun u64 tmp = its_read_baser(its, baser);
2412*4882a593Smuzhiyun u64 type = GITS_BASER_TYPE(tmp);
2413*4882a593Smuzhiyun u64 esz = GITS_BASER_ENTRY_SIZE(tmp);
2414*4882a593Smuzhiyun u64 val = GITS_BASER_InnerShareable | GITS_BASER_RaWaWb;
2415*4882a593Smuzhiyun u32 new_order = *order;
2416*4882a593Smuzhiyun u32 psz = baser->psz;
2417*4882a593Smuzhiyun bool indirect = false;
2418*4882a593Smuzhiyun
2419*4882a593Smuzhiyun /* No need to enable Indirection if memory requirement < (psz*2)bytes */
2420*4882a593Smuzhiyun if ((esz << ids) > (psz * 2)) {
2421*4882a593Smuzhiyun /*
2422*4882a593Smuzhiyun * Find out whether hw supports a single or two-level table by
2423*4882a593Smuzhiyun * table by reading bit at offset '62' after writing '1' to it.
2424*4882a593Smuzhiyun */
2425*4882a593Smuzhiyun its_write_baser(its, baser, val | GITS_BASER_INDIRECT);
2426*4882a593Smuzhiyun indirect = !!(baser->val & GITS_BASER_INDIRECT);
2427*4882a593Smuzhiyun
2428*4882a593Smuzhiyun if (indirect) {
2429*4882a593Smuzhiyun /*
2430*4882a593Smuzhiyun * The size of the lvl2 table is equal to ITS page size
2431*4882a593Smuzhiyun * which is 'psz'. For computing lvl1 table size,
2432*4882a593Smuzhiyun * subtract ID bits that sparse lvl2 table from 'ids'
2433*4882a593Smuzhiyun * which is reported by ITS hardware times lvl1 table
2434*4882a593Smuzhiyun * entry size.
2435*4882a593Smuzhiyun */
2436*4882a593Smuzhiyun ids -= ilog2(psz / (int)esz);
2437*4882a593Smuzhiyun esz = GITS_LVL1_ENTRY_SIZE;
2438*4882a593Smuzhiyun }
2439*4882a593Smuzhiyun }
2440*4882a593Smuzhiyun
2441*4882a593Smuzhiyun /*
2442*4882a593Smuzhiyun * Allocate as many entries as required to fit the
2443*4882a593Smuzhiyun * range of device IDs that the ITS can grok... The ID
2444*4882a593Smuzhiyun * space being incredibly sparse, this results in a
2445*4882a593Smuzhiyun * massive waste of memory if two-level device table
2446*4882a593Smuzhiyun * feature is not supported by hardware.
2447*4882a593Smuzhiyun */
2448*4882a593Smuzhiyun new_order = max_t(u32, get_order(esz << ids), new_order);
2449*4882a593Smuzhiyun if (new_order >= MAX_ORDER) {
2450*4882a593Smuzhiyun new_order = MAX_ORDER - 1;
2451*4882a593Smuzhiyun ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
2452*4882a593Smuzhiyun pr_warn("ITS@%pa: %s Table too large, reduce ids %llu->%u\n",
2453*4882a593Smuzhiyun &its->phys_base, its_base_type_string[type],
2454*4882a593Smuzhiyun device_ids(its), ids);
2455*4882a593Smuzhiyun }
2456*4882a593Smuzhiyun
2457*4882a593Smuzhiyun *order = new_order;
2458*4882a593Smuzhiyun
2459*4882a593Smuzhiyun return indirect;
2460*4882a593Smuzhiyun }
2461*4882a593Smuzhiyun
compute_common_aff(u64 val)2462*4882a593Smuzhiyun static u32 compute_common_aff(u64 val)
2463*4882a593Smuzhiyun {
2464*4882a593Smuzhiyun u32 aff, clpiaff;
2465*4882a593Smuzhiyun
2466*4882a593Smuzhiyun aff = FIELD_GET(GICR_TYPER_AFFINITY, val);
2467*4882a593Smuzhiyun clpiaff = FIELD_GET(GICR_TYPER_COMMON_LPI_AFF, val);
2468*4882a593Smuzhiyun
2469*4882a593Smuzhiyun return aff & ~(GENMASK(31, 0) >> (clpiaff * 8));
2470*4882a593Smuzhiyun }
2471*4882a593Smuzhiyun
compute_its_aff(struct its_node * its)2472*4882a593Smuzhiyun static u32 compute_its_aff(struct its_node *its)
2473*4882a593Smuzhiyun {
2474*4882a593Smuzhiyun u64 val;
2475*4882a593Smuzhiyun u32 svpet;
2476*4882a593Smuzhiyun
2477*4882a593Smuzhiyun /*
2478*4882a593Smuzhiyun * Reencode the ITS SVPET and MPIDR as a GICR_TYPER, and compute
2479*4882a593Smuzhiyun * the resulting affinity. We then use that to see if this match
2480*4882a593Smuzhiyun * our own affinity.
2481*4882a593Smuzhiyun */
2482*4882a593Smuzhiyun svpet = FIELD_GET(GITS_TYPER_SVPET, its->typer);
2483*4882a593Smuzhiyun val = FIELD_PREP(GICR_TYPER_COMMON_LPI_AFF, svpet);
2484*4882a593Smuzhiyun val |= FIELD_PREP(GICR_TYPER_AFFINITY, its->mpidr);
2485*4882a593Smuzhiyun return compute_common_aff(val);
2486*4882a593Smuzhiyun }
2487*4882a593Smuzhiyun
find_sibling_its(struct its_node * cur_its)2488*4882a593Smuzhiyun static struct its_node *find_sibling_its(struct its_node *cur_its)
2489*4882a593Smuzhiyun {
2490*4882a593Smuzhiyun struct its_node *its;
2491*4882a593Smuzhiyun u32 aff;
2492*4882a593Smuzhiyun
2493*4882a593Smuzhiyun if (!FIELD_GET(GITS_TYPER_SVPET, cur_its->typer))
2494*4882a593Smuzhiyun return NULL;
2495*4882a593Smuzhiyun
2496*4882a593Smuzhiyun aff = compute_its_aff(cur_its);
2497*4882a593Smuzhiyun
2498*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
2499*4882a593Smuzhiyun u64 baser;
2500*4882a593Smuzhiyun
2501*4882a593Smuzhiyun if (!is_v4_1(its) || its == cur_its)
2502*4882a593Smuzhiyun continue;
2503*4882a593Smuzhiyun
2504*4882a593Smuzhiyun if (!FIELD_GET(GITS_TYPER_SVPET, its->typer))
2505*4882a593Smuzhiyun continue;
2506*4882a593Smuzhiyun
2507*4882a593Smuzhiyun if (aff != compute_its_aff(its))
2508*4882a593Smuzhiyun continue;
2509*4882a593Smuzhiyun
2510*4882a593Smuzhiyun /* GICv4.1 guarantees that the vPE table is GITS_BASER2 */
2511*4882a593Smuzhiyun baser = its->tables[2].val;
2512*4882a593Smuzhiyun if (!(baser & GITS_BASER_VALID))
2513*4882a593Smuzhiyun continue;
2514*4882a593Smuzhiyun
2515*4882a593Smuzhiyun return its;
2516*4882a593Smuzhiyun }
2517*4882a593Smuzhiyun
2518*4882a593Smuzhiyun return NULL;
2519*4882a593Smuzhiyun }
2520*4882a593Smuzhiyun
its_free_tables(struct its_node * its)2521*4882a593Smuzhiyun static void its_free_tables(struct its_node *its)
2522*4882a593Smuzhiyun {
2523*4882a593Smuzhiyun int i;
2524*4882a593Smuzhiyun
2525*4882a593Smuzhiyun for (i = 0; i < GITS_BASER_NR_REGS; i++) {
2526*4882a593Smuzhiyun if (its->tables[i].base) {
2527*4882a593Smuzhiyun free_pages((unsigned long)its->tables[i].base,
2528*4882a593Smuzhiyun its->tables[i].order);
2529*4882a593Smuzhiyun its->tables[i].base = NULL;
2530*4882a593Smuzhiyun }
2531*4882a593Smuzhiyun }
2532*4882a593Smuzhiyun }
2533*4882a593Smuzhiyun
its_probe_baser_psz(struct its_node * its,struct its_baser * baser)2534*4882a593Smuzhiyun static int its_probe_baser_psz(struct its_node *its, struct its_baser *baser)
2535*4882a593Smuzhiyun {
2536*4882a593Smuzhiyun u64 psz = SZ_64K;
2537*4882a593Smuzhiyun
2538*4882a593Smuzhiyun while (psz) {
2539*4882a593Smuzhiyun u64 val, gpsz;
2540*4882a593Smuzhiyun
2541*4882a593Smuzhiyun val = its_read_baser(its, baser);
2542*4882a593Smuzhiyun val &= ~GITS_BASER_PAGE_SIZE_MASK;
2543*4882a593Smuzhiyun
2544*4882a593Smuzhiyun switch (psz) {
2545*4882a593Smuzhiyun case SZ_64K:
2546*4882a593Smuzhiyun gpsz = GITS_BASER_PAGE_SIZE_64K;
2547*4882a593Smuzhiyun break;
2548*4882a593Smuzhiyun case SZ_16K:
2549*4882a593Smuzhiyun gpsz = GITS_BASER_PAGE_SIZE_16K;
2550*4882a593Smuzhiyun break;
2551*4882a593Smuzhiyun case SZ_4K:
2552*4882a593Smuzhiyun default:
2553*4882a593Smuzhiyun gpsz = GITS_BASER_PAGE_SIZE_4K;
2554*4882a593Smuzhiyun break;
2555*4882a593Smuzhiyun }
2556*4882a593Smuzhiyun
2557*4882a593Smuzhiyun gpsz >>= GITS_BASER_PAGE_SIZE_SHIFT;
2558*4882a593Smuzhiyun
2559*4882a593Smuzhiyun val |= FIELD_PREP(GITS_BASER_PAGE_SIZE_MASK, gpsz);
2560*4882a593Smuzhiyun its_write_baser(its, baser, val);
2561*4882a593Smuzhiyun
2562*4882a593Smuzhiyun if (FIELD_GET(GITS_BASER_PAGE_SIZE_MASK, baser->val) == gpsz)
2563*4882a593Smuzhiyun break;
2564*4882a593Smuzhiyun
2565*4882a593Smuzhiyun switch (psz) {
2566*4882a593Smuzhiyun case SZ_64K:
2567*4882a593Smuzhiyun psz = SZ_16K;
2568*4882a593Smuzhiyun break;
2569*4882a593Smuzhiyun case SZ_16K:
2570*4882a593Smuzhiyun psz = SZ_4K;
2571*4882a593Smuzhiyun break;
2572*4882a593Smuzhiyun case SZ_4K:
2573*4882a593Smuzhiyun default:
2574*4882a593Smuzhiyun return -1;
2575*4882a593Smuzhiyun }
2576*4882a593Smuzhiyun }
2577*4882a593Smuzhiyun
2578*4882a593Smuzhiyun baser->psz = psz;
2579*4882a593Smuzhiyun return 0;
2580*4882a593Smuzhiyun }
2581*4882a593Smuzhiyun
its_alloc_tables(struct its_node * its)2582*4882a593Smuzhiyun static int its_alloc_tables(struct its_node *its)
2583*4882a593Smuzhiyun {
2584*4882a593Smuzhiyun u64 shr = GITS_BASER_InnerShareable;
2585*4882a593Smuzhiyun u64 cache = GITS_BASER_RaWaWb;
2586*4882a593Smuzhiyun int err, i;
2587*4882a593Smuzhiyun
2588*4882a593Smuzhiyun if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375)
2589*4882a593Smuzhiyun /* erratum 24313: ignore memory access type */
2590*4882a593Smuzhiyun cache = GITS_BASER_nCnB;
2591*4882a593Smuzhiyun
2592*4882a593Smuzhiyun for (i = 0; i < GITS_BASER_NR_REGS; i++) {
2593*4882a593Smuzhiyun struct its_baser *baser = its->tables + i;
2594*4882a593Smuzhiyun u64 val = its_read_baser(its, baser);
2595*4882a593Smuzhiyun u64 type = GITS_BASER_TYPE(val);
2596*4882a593Smuzhiyun bool indirect = false;
2597*4882a593Smuzhiyun u32 order;
2598*4882a593Smuzhiyun
2599*4882a593Smuzhiyun if (type == GITS_BASER_TYPE_NONE)
2600*4882a593Smuzhiyun continue;
2601*4882a593Smuzhiyun
2602*4882a593Smuzhiyun if (its_probe_baser_psz(its, baser)) {
2603*4882a593Smuzhiyun its_free_tables(its);
2604*4882a593Smuzhiyun return -ENXIO;
2605*4882a593Smuzhiyun }
2606*4882a593Smuzhiyun
2607*4882a593Smuzhiyun order = get_order(baser->psz);
2608*4882a593Smuzhiyun
2609*4882a593Smuzhiyun switch (type) {
2610*4882a593Smuzhiyun case GITS_BASER_TYPE_DEVICE:
2611*4882a593Smuzhiyun indirect = its_parse_indirect_baser(its, baser, &order,
2612*4882a593Smuzhiyun device_ids(its));
2613*4882a593Smuzhiyun break;
2614*4882a593Smuzhiyun
2615*4882a593Smuzhiyun case GITS_BASER_TYPE_VCPU:
2616*4882a593Smuzhiyun if (is_v4_1(its)) {
2617*4882a593Smuzhiyun struct its_node *sibling;
2618*4882a593Smuzhiyun
2619*4882a593Smuzhiyun WARN_ON(i != 2);
2620*4882a593Smuzhiyun if ((sibling = find_sibling_its(its))) {
2621*4882a593Smuzhiyun *baser = sibling->tables[2];
2622*4882a593Smuzhiyun its_write_baser(its, baser, baser->val);
2623*4882a593Smuzhiyun continue;
2624*4882a593Smuzhiyun }
2625*4882a593Smuzhiyun }
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun indirect = its_parse_indirect_baser(its, baser, &order,
2628*4882a593Smuzhiyun ITS_MAX_VPEID_BITS);
2629*4882a593Smuzhiyun break;
2630*4882a593Smuzhiyun }
2631*4882a593Smuzhiyun
2632*4882a593Smuzhiyun err = its_setup_baser(its, baser, cache, shr, order, indirect);
2633*4882a593Smuzhiyun if (err < 0) {
2634*4882a593Smuzhiyun its_free_tables(its);
2635*4882a593Smuzhiyun return err;
2636*4882a593Smuzhiyun }
2637*4882a593Smuzhiyun
2638*4882a593Smuzhiyun /* Update settings which will be used for next BASERn */
2639*4882a593Smuzhiyun cache = baser->val & GITS_BASER_CACHEABILITY_MASK;
2640*4882a593Smuzhiyun shr = baser->val & GITS_BASER_SHAREABILITY_MASK;
2641*4882a593Smuzhiyun }
2642*4882a593Smuzhiyun
2643*4882a593Smuzhiyun return 0;
2644*4882a593Smuzhiyun }
2645*4882a593Smuzhiyun
inherit_vpe_l1_table_from_its(void)2646*4882a593Smuzhiyun static u64 inherit_vpe_l1_table_from_its(void)
2647*4882a593Smuzhiyun {
2648*4882a593Smuzhiyun struct its_node *its;
2649*4882a593Smuzhiyun u64 val;
2650*4882a593Smuzhiyun u32 aff;
2651*4882a593Smuzhiyun
2652*4882a593Smuzhiyun val = gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER);
2653*4882a593Smuzhiyun aff = compute_common_aff(val);
2654*4882a593Smuzhiyun
2655*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
2656*4882a593Smuzhiyun u64 baser, addr;
2657*4882a593Smuzhiyun
2658*4882a593Smuzhiyun if (!is_v4_1(its))
2659*4882a593Smuzhiyun continue;
2660*4882a593Smuzhiyun
2661*4882a593Smuzhiyun if (!FIELD_GET(GITS_TYPER_SVPET, its->typer))
2662*4882a593Smuzhiyun continue;
2663*4882a593Smuzhiyun
2664*4882a593Smuzhiyun if (aff != compute_its_aff(its))
2665*4882a593Smuzhiyun continue;
2666*4882a593Smuzhiyun
2667*4882a593Smuzhiyun /* GICv4.1 guarantees that the vPE table is GITS_BASER2 */
2668*4882a593Smuzhiyun baser = its->tables[2].val;
2669*4882a593Smuzhiyun if (!(baser & GITS_BASER_VALID))
2670*4882a593Smuzhiyun continue;
2671*4882a593Smuzhiyun
2672*4882a593Smuzhiyun /* We have a winner! */
2673*4882a593Smuzhiyun gic_data_rdist()->vpe_l1_base = its->tables[2].base;
2674*4882a593Smuzhiyun
2675*4882a593Smuzhiyun val = GICR_VPROPBASER_4_1_VALID;
2676*4882a593Smuzhiyun if (baser & GITS_BASER_INDIRECT)
2677*4882a593Smuzhiyun val |= GICR_VPROPBASER_4_1_INDIRECT;
2678*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE,
2679*4882a593Smuzhiyun FIELD_GET(GITS_BASER_PAGE_SIZE_MASK, baser));
2680*4882a593Smuzhiyun switch (FIELD_GET(GITS_BASER_PAGE_SIZE_MASK, baser)) {
2681*4882a593Smuzhiyun case GIC_PAGE_SIZE_64K:
2682*4882a593Smuzhiyun addr = GITS_BASER_ADDR_48_to_52(baser);
2683*4882a593Smuzhiyun break;
2684*4882a593Smuzhiyun default:
2685*4882a593Smuzhiyun addr = baser & GENMASK_ULL(47, 12);
2686*4882a593Smuzhiyun break;
2687*4882a593Smuzhiyun }
2688*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR, addr >> 12);
2689*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_SHAREABILITY_MASK,
2690*4882a593Smuzhiyun FIELD_GET(GITS_BASER_SHAREABILITY_MASK, baser));
2691*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_INNER_CACHEABILITY_MASK,
2692*4882a593Smuzhiyun FIELD_GET(GITS_BASER_INNER_CACHEABILITY_MASK, baser));
2693*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, GITS_BASER_NR_PAGES(baser) - 1);
2694*4882a593Smuzhiyun
2695*4882a593Smuzhiyun return val;
2696*4882a593Smuzhiyun }
2697*4882a593Smuzhiyun
2698*4882a593Smuzhiyun return 0;
2699*4882a593Smuzhiyun }
2700*4882a593Smuzhiyun
inherit_vpe_l1_table_from_rd(cpumask_t ** mask)2701*4882a593Smuzhiyun static u64 inherit_vpe_l1_table_from_rd(cpumask_t **mask)
2702*4882a593Smuzhiyun {
2703*4882a593Smuzhiyun u32 aff;
2704*4882a593Smuzhiyun u64 val;
2705*4882a593Smuzhiyun int cpu;
2706*4882a593Smuzhiyun
2707*4882a593Smuzhiyun val = gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER);
2708*4882a593Smuzhiyun aff = compute_common_aff(val);
2709*4882a593Smuzhiyun
2710*4882a593Smuzhiyun for_each_possible_cpu(cpu) {
2711*4882a593Smuzhiyun void __iomem *base = gic_data_rdist_cpu(cpu)->rd_base;
2712*4882a593Smuzhiyun
2713*4882a593Smuzhiyun if (!base || cpu == smp_processor_id())
2714*4882a593Smuzhiyun continue;
2715*4882a593Smuzhiyun
2716*4882a593Smuzhiyun val = gic_read_typer(base + GICR_TYPER);
2717*4882a593Smuzhiyun if (aff != compute_common_aff(val))
2718*4882a593Smuzhiyun continue;
2719*4882a593Smuzhiyun
2720*4882a593Smuzhiyun /*
2721*4882a593Smuzhiyun * At this point, we have a victim. This particular CPU
2722*4882a593Smuzhiyun * has already booted, and has an affinity that matches
2723*4882a593Smuzhiyun * ours wrt CommonLPIAff. Let's use its own VPROPBASER.
2724*4882a593Smuzhiyun * Make sure we don't write the Z bit in that case.
2725*4882a593Smuzhiyun */
2726*4882a593Smuzhiyun val = gicr_read_vpropbaser(base + SZ_128K + GICR_VPROPBASER);
2727*4882a593Smuzhiyun val &= ~GICR_VPROPBASER_4_1_Z;
2728*4882a593Smuzhiyun
2729*4882a593Smuzhiyun gic_data_rdist()->vpe_l1_base = gic_data_rdist_cpu(cpu)->vpe_l1_base;
2730*4882a593Smuzhiyun *mask = gic_data_rdist_cpu(cpu)->vpe_table_mask;
2731*4882a593Smuzhiyun
2732*4882a593Smuzhiyun return val;
2733*4882a593Smuzhiyun }
2734*4882a593Smuzhiyun
2735*4882a593Smuzhiyun return 0;
2736*4882a593Smuzhiyun }
2737*4882a593Smuzhiyun
allocate_vpe_l2_table(int cpu,u32 id)2738*4882a593Smuzhiyun static bool allocate_vpe_l2_table(int cpu, u32 id)
2739*4882a593Smuzhiyun {
2740*4882a593Smuzhiyun void __iomem *base = gic_data_rdist_cpu(cpu)->rd_base;
2741*4882a593Smuzhiyun unsigned int psz, esz, idx, npg, gpsz;
2742*4882a593Smuzhiyun u64 val;
2743*4882a593Smuzhiyun struct page *page;
2744*4882a593Smuzhiyun __le64 *table;
2745*4882a593Smuzhiyun
2746*4882a593Smuzhiyun if (!gic_rdists->has_rvpeid)
2747*4882a593Smuzhiyun return true;
2748*4882a593Smuzhiyun
2749*4882a593Smuzhiyun /* Skip non-present CPUs */
2750*4882a593Smuzhiyun if (!base)
2751*4882a593Smuzhiyun return true;
2752*4882a593Smuzhiyun
2753*4882a593Smuzhiyun val = gicr_read_vpropbaser(base + SZ_128K + GICR_VPROPBASER);
2754*4882a593Smuzhiyun
2755*4882a593Smuzhiyun esz = FIELD_GET(GICR_VPROPBASER_4_1_ENTRY_SIZE, val) + 1;
2756*4882a593Smuzhiyun gpsz = FIELD_GET(GICR_VPROPBASER_4_1_PAGE_SIZE, val);
2757*4882a593Smuzhiyun npg = FIELD_GET(GICR_VPROPBASER_4_1_SIZE, val) + 1;
2758*4882a593Smuzhiyun
2759*4882a593Smuzhiyun switch (gpsz) {
2760*4882a593Smuzhiyun default:
2761*4882a593Smuzhiyun WARN_ON(1);
2762*4882a593Smuzhiyun fallthrough;
2763*4882a593Smuzhiyun case GIC_PAGE_SIZE_4K:
2764*4882a593Smuzhiyun psz = SZ_4K;
2765*4882a593Smuzhiyun break;
2766*4882a593Smuzhiyun case GIC_PAGE_SIZE_16K:
2767*4882a593Smuzhiyun psz = SZ_16K;
2768*4882a593Smuzhiyun break;
2769*4882a593Smuzhiyun case GIC_PAGE_SIZE_64K:
2770*4882a593Smuzhiyun psz = SZ_64K;
2771*4882a593Smuzhiyun break;
2772*4882a593Smuzhiyun }
2773*4882a593Smuzhiyun
2774*4882a593Smuzhiyun /* Don't allow vpe_id that exceeds single, flat table limit */
2775*4882a593Smuzhiyun if (!(val & GICR_VPROPBASER_4_1_INDIRECT))
2776*4882a593Smuzhiyun return (id < (npg * psz / (esz * SZ_8)));
2777*4882a593Smuzhiyun
2778*4882a593Smuzhiyun /* Compute 1st level table index & check if that exceeds table limit */
2779*4882a593Smuzhiyun idx = id >> ilog2(psz / (esz * SZ_8));
2780*4882a593Smuzhiyun if (idx >= (npg * psz / GITS_LVL1_ENTRY_SIZE))
2781*4882a593Smuzhiyun return false;
2782*4882a593Smuzhiyun
2783*4882a593Smuzhiyun table = gic_data_rdist_cpu(cpu)->vpe_l1_base;
2784*4882a593Smuzhiyun
2785*4882a593Smuzhiyun /* Allocate memory for 2nd level table */
2786*4882a593Smuzhiyun if (!table[idx]) {
2787*4882a593Smuzhiyun page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(psz));
2788*4882a593Smuzhiyun if (!page)
2789*4882a593Smuzhiyun return false;
2790*4882a593Smuzhiyun
2791*4882a593Smuzhiyun /* Flush Lvl2 table to PoC if hw doesn't support coherency */
2792*4882a593Smuzhiyun if (!(val & GICR_VPROPBASER_SHAREABILITY_MASK))
2793*4882a593Smuzhiyun gic_flush_dcache_to_poc(page_address(page), psz);
2794*4882a593Smuzhiyun
2795*4882a593Smuzhiyun table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
2796*4882a593Smuzhiyun
2797*4882a593Smuzhiyun /* Flush Lvl1 entry to PoC if hw doesn't support coherency */
2798*4882a593Smuzhiyun if (!(val & GICR_VPROPBASER_SHAREABILITY_MASK))
2799*4882a593Smuzhiyun gic_flush_dcache_to_poc(table + idx, GITS_LVL1_ENTRY_SIZE);
2800*4882a593Smuzhiyun
2801*4882a593Smuzhiyun /* Ensure updated table contents are visible to RD hardware */
2802*4882a593Smuzhiyun dsb(sy);
2803*4882a593Smuzhiyun }
2804*4882a593Smuzhiyun
2805*4882a593Smuzhiyun return true;
2806*4882a593Smuzhiyun }
2807*4882a593Smuzhiyun
allocate_vpe_l1_table(void)2808*4882a593Smuzhiyun static int allocate_vpe_l1_table(void)
2809*4882a593Smuzhiyun {
2810*4882a593Smuzhiyun void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
2811*4882a593Smuzhiyun u64 val, gpsz, npg, pa;
2812*4882a593Smuzhiyun unsigned int psz = SZ_64K;
2813*4882a593Smuzhiyun unsigned int np, epp, esz;
2814*4882a593Smuzhiyun struct page *page;
2815*4882a593Smuzhiyun
2816*4882a593Smuzhiyun if (!gic_rdists->has_rvpeid)
2817*4882a593Smuzhiyun return 0;
2818*4882a593Smuzhiyun
2819*4882a593Smuzhiyun /*
2820*4882a593Smuzhiyun * if VPENDBASER.Valid is set, disable any previously programmed
2821*4882a593Smuzhiyun * VPE by setting PendingLast while clearing Valid. This has the
2822*4882a593Smuzhiyun * effect of making sure no doorbell will be generated and we can
2823*4882a593Smuzhiyun * then safely clear VPROPBASER.Valid.
2824*4882a593Smuzhiyun */
2825*4882a593Smuzhiyun if (gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER) & GICR_VPENDBASER_Valid)
2826*4882a593Smuzhiyun gicr_write_vpendbaser(GICR_VPENDBASER_PendingLast,
2827*4882a593Smuzhiyun vlpi_base + GICR_VPENDBASER);
2828*4882a593Smuzhiyun
2829*4882a593Smuzhiyun /*
2830*4882a593Smuzhiyun * If we can inherit the configuration from another RD, let's do
2831*4882a593Smuzhiyun * so. Otherwise, we have to go through the allocation process. We
2832*4882a593Smuzhiyun * assume that all RDs have the exact same requirements, as
2833*4882a593Smuzhiyun * nothing will work otherwise.
2834*4882a593Smuzhiyun */
2835*4882a593Smuzhiyun val = inherit_vpe_l1_table_from_rd(&gic_data_rdist()->vpe_table_mask);
2836*4882a593Smuzhiyun if (val & GICR_VPROPBASER_4_1_VALID)
2837*4882a593Smuzhiyun goto out;
2838*4882a593Smuzhiyun
2839*4882a593Smuzhiyun gic_data_rdist()->vpe_table_mask = kzalloc(sizeof(cpumask_t), GFP_ATOMIC);
2840*4882a593Smuzhiyun if (!gic_data_rdist()->vpe_table_mask)
2841*4882a593Smuzhiyun return -ENOMEM;
2842*4882a593Smuzhiyun
2843*4882a593Smuzhiyun val = inherit_vpe_l1_table_from_its();
2844*4882a593Smuzhiyun if (val & GICR_VPROPBASER_4_1_VALID)
2845*4882a593Smuzhiyun goto out;
2846*4882a593Smuzhiyun
2847*4882a593Smuzhiyun /* First probe the page size */
2848*4882a593Smuzhiyun val = FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE, GIC_PAGE_SIZE_64K);
2849*4882a593Smuzhiyun gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
2850*4882a593Smuzhiyun val = gicr_read_vpropbaser(vlpi_base + GICR_VPROPBASER);
2851*4882a593Smuzhiyun gpsz = FIELD_GET(GICR_VPROPBASER_4_1_PAGE_SIZE, val);
2852*4882a593Smuzhiyun esz = FIELD_GET(GICR_VPROPBASER_4_1_ENTRY_SIZE, val);
2853*4882a593Smuzhiyun
2854*4882a593Smuzhiyun switch (gpsz) {
2855*4882a593Smuzhiyun default:
2856*4882a593Smuzhiyun gpsz = GIC_PAGE_SIZE_4K;
2857*4882a593Smuzhiyun fallthrough;
2858*4882a593Smuzhiyun case GIC_PAGE_SIZE_4K:
2859*4882a593Smuzhiyun psz = SZ_4K;
2860*4882a593Smuzhiyun break;
2861*4882a593Smuzhiyun case GIC_PAGE_SIZE_16K:
2862*4882a593Smuzhiyun psz = SZ_16K;
2863*4882a593Smuzhiyun break;
2864*4882a593Smuzhiyun case GIC_PAGE_SIZE_64K:
2865*4882a593Smuzhiyun psz = SZ_64K;
2866*4882a593Smuzhiyun break;
2867*4882a593Smuzhiyun }
2868*4882a593Smuzhiyun
2869*4882a593Smuzhiyun /*
2870*4882a593Smuzhiyun * Start populating the register from scratch, including RO fields
2871*4882a593Smuzhiyun * (which we want to print in debug cases...)
2872*4882a593Smuzhiyun */
2873*4882a593Smuzhiyun val = 0;
2874*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE, gpsz);
2875*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_4_1_ENTRY_SIZE, esz);
2876*4882a593Smuzhiyun
2877*4882a593Smuzhiyun /* How many entries per GIC page? */
2878*4882a593Smuzhiyun esz++;
2879*4882a593Smuzhiyun epp = psz / (esz * SZ_8);
2880*4882a593Smuzhiyun
2881*4882a593Smuzhiyun /*
2882*4882a593Smuzhiyun * If we need more than just a single L1 page, flag the table
2883*4882a593Smuzhiyun * as indirect and compute the number of required L1 pages.
2884*4882a593Smuzhiyun */
2885*4882a593Smuzhiyun if (epp < ITS_MAX_VPEID) {
2886*4882a593Smuzhiyun int nl2;
2887*4882a593Smuzhiyun
2888*4882a593Smuzhiyun val |= GICR_VPROPBASER_4_1_INDIRECT;
2889*4882a593Smuzhiyun
2890*4882a593Smuzhiyun /* Number of L2 pages required to cover the VPEID space */
2891*4882a593Smuzhiyun nl2 = DIV_ROUND_UP(ITS_MAX_VPEID, epp);
2892*4882a593Smuzhiyun
2893*4882a593Smuzhiyun /* Number of L1 pages to point to the L2 pages */
2894*4882a593Smuzhiyun npg = DIV_ROUND_UP(nl2 * SZ_8, psz);
2895*4882a593Smuzhiyun } else {
2896*4882a593Smuzhiyun npg = 1;
2897*4882a593Smuzhiyun }
2898*4882a593Smuzhiyun
2899*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, npg - 1);
2900*4882a593Smuzhiyun
2901*4882a593Smuzhiyun /* Right, that's the number of CPU pages we need for L1 */
2902*4882a593Smuzhiyun np = DIV_ROUND_UP(npg * psz, PAGE_SIZE);
2903*4882a593Smuzhiyun
2904*4882a593Smuzhiyun pr_debug("np = %d, npg = %lld, psz = %d, epp = %d, esz = %d\n",
2905*4882a593Smuzhiyun np, npg, psz, epp, esz);
2906*4882a593Smuzhiyun page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, get_order(np * PAGE_SIZE));
2907*4882a593Smuzhiyun if (!page)
2908*4882a593Smuzhiyun return -ENOMEM;
2909*4882a593Smuzhiyun
2910*4882a593Smuzhiyun gic_data_rdist()->vpe_l1_base = page_address(page);
2911*4882a593Smuzhiyun pa = virt_to_phys(page_address(page));
2912*4882a593Smuzhiyun WARN_ON(!IS_ALIGNED(pa, psz));
2913*4882a593Smuzhiyun
2914*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR, pa >> 12);
2915*4882a593Smuzhiyun val |= GICR_VPROPBASER_RaWb;
2916*4882a593Smuzhiyun val |= GICR_VPROPBASER_InnerShareable;
2917*4882a593Smuzhiyun val |= GICR_VPROPBASER_4_1_Z;
2918*4882a593Smuzhiyun val |= GICR_VPROPBASER_4_1_VALID;
2919*4882a593Smuzhiyun
2920*4882a593Smuzhiyun out:
2921*4882a593Smuzhiyun gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
2922*4882a593Smuzhiyun cpumask_set_cpu(smp_processor_id(), gic_data_rdist()->vpe_table_mask);
2923*4882a593Smuzhiyun
2924*4882a593Smuzhiyun pr_debug("CPU%d: VPROPBASER = %llx %*pbl\n",
2925*4882a593Smuzhiyun smp_processor_id(), val,
2926*4882a593Smuzhiyun cpumask_pr_args(gic_data_rdist()->vpe_table_mask));
2927*4882a593Smuzhiyun
2928*4882a593Smuzhiyun return 0;
2929*4882a593Smuzhiyun }
2930*4882a593Smuzhiyun
its_alloc_collections(struct its_node * its)2931*4882a593Smuzhiyun static int its_alloc_collections(struct its_node *its)
2932*4882a593Smuzhiyun {
2933*4882a593Smuzhiyun int i;
2934*4882a593Smuzhiyun
2935*4882a593Smuzhiyun its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections),
2936*4882a593Smuzhiyun GFP_KERNEL);
2937*4882a593Smuzhiyun if (!its->collections)
2938*4882a593Smuzhiyun return -ENOMEM;
2939*4882a593Smuzhiyun
2940*4882a593Smuzhiyun for (i = 0; i < nr_cpu_ids; i++)
2941*4882a593Smuzhiyun its->collections[i].target_address = ~0ULL;
2942*4882a593Smuzhiyun
2943*4882a593Smuzhiyun return 0;
2944*4882a593Smuzhiyun }
2945*4882a593Smuzhiyun
its_allocate_pending_table(gfp_t gfp_flags)2946*4882a593Smuzhiyun static struct page *its_allocate_pending_table(gfp_t gfp_flags)
2947*4882a593Smuzhiyun {
2948*4882a593Smuzhiyun struct page *pend_page;
2949*4882a593Smuzhiyun
2950*4882a593Smuzhiyun if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566"))
2951*4882a593Smuzhiyun gfp_flags |= GFP_DMA32;
2952*4882a593Smuzhiyun pend_page = alloc_pages(gfp_flags | __GFP_ZERO,
2953*4882a593Smuzhiyun get_order(LPI_PENDBASE_SZ));
2954*4882a593Smuzhiyun if (!pend_page)
2955*4882a593Smuzhiyun return NULL;
2956*4882a593Smuzhiyun
2957*4882a593Smuzhiyun /* Make sure the GIC will observe the zero-ed page */
2958*4882a593Smuzhiyun gic_flush_dcache_to_poc(page_address(pend_page), LPI_PENDBASE_SZ);
2959*4882a593Smuzhiyun
2960*4882a593Smuzhiyun return pend_page;
2961*4882a593Smuzhiyun }
2962*4882a593Smuzhiyun
its_free_pending_table(struct page * pt)2963*4882a593Smuzhiyun static void its_free_pending_table(struct page *pt)
2964*4882a593Smuzhiyun {
2965*4882a593Smuzhiyun free_pages((unsigned long)page_address(pt), get_order(LPI_PENDBASE_SZ));
2966*4882a593Smuzhiyun }
2967*4882a593Smuzhiyun
2968*4882a593Smuzhiyun /*
2969*4882a593Smuzhiyun * Booting with kdump and LPIs enabled is generally fine. Any other
2970*4882a593Smuzhiyun * case is wrong in the absence of firmware/EFI support.
2971*4882a593Smuzhiyun */
enabled_lpis_allowed(void)2972*4882a593Smuzhiyun static bool enabled_lpis_allowed(void)
2973*4882a593Smuzhiyun {
2974*4882a593Smuzhiyun phys_addr_t addr;
2975*4882a593Smuzhiyun u64 val;
2976*4882a593Smuzhiyun
2977*4882a593Smuzhiyun /* Check whether the property table is in a reserved region */
2978*4882a593Smuzhiyun val = gicr_read_propbaser(gic_data_rdist_rd_base() + GICR_PROPBASER);
2979*4882a593Smuzhiyun addr = val & GENMASK_ULL(51, 12);
2980*4882a593Smuzhiyun
2981*4882a593Smuzhiyun return gic_check_reserved_range(addr, LPI_PROPBASE_SZ);
2982*4882a593Smuzhiyun }
2983*4882a593Smuzhiyun
allocate_lpi_tables(void)2984*4882a593Smuzhiyun static int __init allocate_lpi_tables(void)
2985*4882a593Smuzhiyun {
2986*4882a593Smuzhiyun u64 val;
2987*4882a593Smuzhiyun int err, cpu;
2988*4882a593Smuzhiyun
2989*4882a593Smuzhiyun /*
2990*4882a593Smuzhiyun * If LPIs are enabled while we run this from the boot CPU,
2991*4882a593Smuzhiyun * flag the RD tables as pre-allocated if the stars do align.
2992*4882a593Smuzhiyun */
2993*4882a593Smuzhiyun val = readl_relaxed(gic_data_rdist_rd_base() + GICR_CTLR);
2994*4882a593Smuzhiyun if ((val & GICR_CTLR_ENABLE_LPIS) && enabled_lpis_allowed()) {
2995*4882a593Smuzhiyun gic_rdists->flags |= (RDIST_FLAGS_RD_TABLES_PREALLOCATED |
2996*4882a593Smuzhiyun RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING);
2997*4882a593Smuzhiyun pr_info("GICv3: Using preallocated redistributor tables\n");
2998*4882a593Smuzhiyun }
2999*4882a593Smuzhiyun
3000*4882a593Smuzhiyun err = its_setup_lpi_prop_table();
3001*4882a593Smuzhiyun if (err)
3002*4882a593Smuzhiyun return err;
3003*4882a593Smuzhiyun
3004*4882a593Smuzhiyun /*
3005*4882a593Smuzhiyun * We allocate all the pending tables anyway, as we may have a
3006*4882a593Smuzhiyun * mix of RDs that have had LPIs enabled, and some that
3007*4882a593Smuzhiyun * don't. We'll free the unused ones as each CPU comes online.
3008*4882a593Smuzhiyun */
3009*4882a593Smuzhiyun for_each_possible_cpu(cpu) {
3010*4882a593Smuzhiyun struct page *pend_page;
3011*4882a593Smuzhiyun
3012*4882a593Smuzhiyun pend_page = its_allocate_pending_table(GFP_NOWAIT);
3013*4882a593Smuzhiyun if (!pend_page) {
3014*4882a593Smuzhiyun pr_err("Failed to allocate PENDBASE for CPU%d\n", cpu);
3015*4882a593Smuzhiyun return -ENOMEM;
3016*4882a593Smuzhiyun }
3017*4882a593Smuzhiyun
3018*4882a593Smuzhiyun gic_data_rdist_cpu(cpu)->pend_page = pend_page;
3019*4882a593Smuzhiyun }
3020*4882a593Smuzhiyun
3021*4882a593Smuzhiyun return 0;
3022*4882a593Smuzhiyun }
3023*4882a593Smuzhiyun
read_vpend_dirty_clear(void __iomem * vlpi_base)3024*4882a593Smuzhiyun static u64 read_vpend_dirty_clear(void __iomem *vlpi_base)
3025*4882a593Smuzhiyun {
3026*4882a593Smuzhiyun u32 count = 1000000; /* 1s! */
3027*4882a593Smuzhiyun bool clean;
3028*4882a593Smuzhiyun u64 val;
3029*4882a593Smuzhiyun
3030*4882a593Smuzhiyun do {
3031*4882a593Smuzhiyun val = gicr_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
3032*4882a593Smuzhiyun clean = !(val & GICR_VPENDBASER_Dirty);
3033*4882a593Smuzhiyun if (!clean) {
3034*4882a593Smuzhiyun count--;
3035*4882a593Smuzhiyun cpu_relax();
3036*4882a593Smuzhiyun udelay(1);
3037*4882a593Smuzhiyun }
3038*4882a593Smuzhiyun } while (!clean && count);
3039*4882a593Smuzhiyun
3040*4882a593Smuzhiyun if (unlikely(!clean))
3041*4882a593Smuzhiyun pr_err_ratelimited("ITS virtual pending table not cleaning\n");
3042*4882a593Smuzhiyun
3043*4882a593Smuzhiyun return val;
3044*4882a593Smuzhiyun }
3045*4882a593Smuzhiyun
its_clear_vpend_valid(void __iomem * vlpi_base,u64 clr,u64 set)3046*4882a593Smuzhiyun static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
3047*4882a593Smuzhiyun {
3048*4882a593Smuzhiyun u64 val;
3049*4882a593Smuzhiyun
3050*4882a593Smuzhiyun /* Make sure we wait until the RD is done with the initial scan */
3051*4882a593Smuzhiyun val = read_vpend_dirty_clear(vlpi_base);
3052*4882a593Smuzhiyun val &= ~GICR_VPENDBASER_Valid;
3053*4882a593Smuzhiyun val &= ~clr;
3054*4882a593Smuzhiyun val |= set;
3055*4882a593Smuzhiyun gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
3056*4882a593Smuzhiyun
3057*4882a593Smuzhiyun val = read_vpend_dirty_clear(vlpi_base);
3058*4882a593Smuzhiyun if (unlikely(val & GICR_VPENDBASER_Dirty))
3059*4882a593Smuzhiyun val |= GICR_VPENDBASER_PendingLast;
3060*4882a593Smuzhiyun
3061*4882a593Smuzhiyun return val;
3062*4882a593Smuzhiyun }
3063*4882a593Smuzhiyun
its_cpu_init_lpis(void)3064*4882a593Smuzhiyun static void its_cpu_init_lpis(void)
3065*4882a593Smuzhiyun {
3066*4882a593Smuzhiyun void __iomem *rbase = gic_data_rdist_rd_base();
3067*4882a593Smuzhiyun struct page *pend_page;
3068*4882a593Smuzhiyun phys_addr_t paddr;
3069*4882a593Smuzhiyun u64 val, tmp;
3070*4882a593Smuzhiyun
3071*4882a593Smuzhiyun if (gic_data_rdist()->lpi_enabled)
3072*4882a593Smuzhiyun return;
3073*4882a593Smuzhiyun
3074*4882a593Smuzhiyun val = readl_relaxed(rbase + GICR_CTLR);
3075*4882a593Smuzhiyun if ((gic_rdists->flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED) &&
3076*4882a593Smuzhiyun (val & GICR_CTLR_ENABLE_LPIS)) {
3077*4882a593Smuzhiyun /*
3078*4882a593Smuzhiyun * Check that we get the same property table on all
3079*4882a593Smuzhiyun * RDs. If we don't, this is hopeless.
3080*4882a593Smuzhiyun */
3081*4882a593Smuzhiyun paddr = gicr_read_propbaser(rbase + GICR_PROPBASER);
3082*4882a593Smuzhiyun paddr &= GENMASK_ULL(51, 12);
3083*4882a593Smuzhiyun if (WARN_ON(gic_rdists->prop_table_pa != paddr))
3084*4882a593Smuzhiyun add_taint(TAINT_CRAP, LOCKDEP_STILL_OK);
3085*4882a593Smuzhiyun
3086*4882a593Smuzhiyun paddr = gicr_read_pendbaser(rbase + GICR_PENDBASER);
3087*4882a593Smuzhiyun paddr &= GENMASK_ULL(51, 16);
3088*4882a593Smuzhiyun
3089*4882a593Smuzhiyun WARN_ON(!gic_check_reserved_range(paddr, LPI_PENDBASE_SZ));
3090*4882a593Smuzhiyun its_free_pending_table(gic_data_rdist()->pend_page);
3091*4882a593Smuzhiyun gic_data_rdist()->pend_page = NULL;
3092*4882a593Smuzhiyun
3093*4882a593Smuzhiyun goto out;
3094*4882a593Smuzhiyun }
3095*4882a593Smuzhiyun
3096*4882a593Smuzhiyun pend_page = gic_data_rdist()->pend_page;
3097*4882a593Smuzhiyun paddr = page_to_phys(pend_page);
3098*4882a593Smuzhiyun WARN_ON(gic_reserve_range(paddr, LPI_PENDBASE_SZ));
3099*4882a593Smuzhiyun
3100*4882a593Smuzhiyun /* set PROPBASE */
3101*4882a593Smuzhiyun val = (gic_rdists->prop_table_pa |
3102*4882a593Smuzhiyun GICR_PROPBASER_InnerShareable |
3103*4882a593Smuzhiyun GICR_PROPBASER_RaWaWb |
3104*4882a593Smuzhiyun ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
3105*4882a593Smuzhiyun
3106*4882a593Smuzhiyun gicr_write_propbaser(val, rbase + GICR_PROPBASER);
3107*4882a593Smuzhiyun tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);
3108*4882a593Smuzhiyun
3109*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_NO_GKI) &&
3110*4882a593Smuzhiyun (of_machine_is_compatible("rockchip,rk3568") ||
3111*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3566") ||
3112*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3588")))
3113*4882a593Smuzhiyun tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK;
3114*4882a593Smuzhiyun
3115*4882a593Smuzhiyun if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
3116*4882a593Smuzhiyun if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
3117*4882a593Smuzhiyun /*
3118*4882a593Smuzhiyun * The HW reports non-shareable, we must
3119*4882a593Smuzhiyun * remove the cacheability attributes as
3120*4882a593Smuzhiyun * well.
3121*4882a593Smuzhiyun */
3122*4882a593Smuzhiyun val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |
3123*4882a593Smuzhiyun GICR_PROPBASER_CACHEABILITY_MASK);
3124*4882a593Smuzhiyun val |= GICR_PROPBASER_nC;
3125*4882a593Smuzhiyun gicr_write_propbaser(val, rbase + GICR_PROPBASER);
3126*4882a593Smuzhiyun }
3127*4882a593Smuzhiyun pr_info_once("GIC: using cache flushing for LPI property table\n");
3128*4882a593Smuzhiyun gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING;
3129*4882a593Smuzhiyun }
3130*4882a593Smuzhiyun
3131*4882a593Smuzhiyun /* set PENDBASE */
3132*4882a593Smuzhiyun val = (page_to_phys(pend_page) |
3133*4882a593Smuzhiyun GICR_PENDBASER_InnerShareable |
3134*4882a593Smuzhiyun GICR_PENDBASER_RaWaWb);
3135*4882a593Smuzhiyun
3136*4882a593Smuzhiyun gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
3137*4882a593Smuzhiyun tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);
3138*4882a593Smuzhiyun
3139*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_NO_GKI) &&
3140*4882a593Smuzhiyun (of_machine_is_compatible("rockchip,rk3568") ||
3141*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3566") ||
3142*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3588")))
3143*4882a593Smuzhiyun tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK;
3144*4882a593Smuzhiyun
3145*4882a593Smuzhiyun if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
3146*4882a593Smuzhiyun /*
3147*4882a593Smuzhiyun * The HW reports non-shareable, we must remove the
3148*4882a593Smuzhiyun * cacheability attributes as well.
3149*4882a593Smuzhiyun */
3150*4882a593Smuzhiyun val &= ~(GICR_PENDBASER_SHAREABILITY_MASK |
3151*4882a593Smuzhiyun GICR_PENDBASER_CACHEABILITY_MASK);
3152*4882a593Smuzhiyun val |= GICR_PENDBASER_nC;
3153*4882a593Smuzhiyun gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
3154*4882a593Smuzhiyun }
3155*4882a593Smuzhiyun
3156*4882a593Smuzhiyun /* Enable LPIs */
3157*4882a593Smuzhiyun val = readl_relaxed(rbase + GICR_CTLR);
3158*4882a593Smuzhiyun val |= GICR_CTLR_ENABLE_LPIS;
3159*4882a593Smuzhiyun writel_relaxed(val, rbase + GICR_CTLR);
3160*4882a593Smuzhiyun
3161*4882a593Smuzhiyun if (gic_rdists->has_vlpis && !gic_rdists->has_rvpeid) {
3162*4882a593Smuzhiyun void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
3163*4882a593Smuzhiyun
3164*4882a593Smuzhiyun /*
3165*4882a593Smuzhiyun * It's possible for CPU to receive VLPIs before it is
3166*4882a593Smuzhiyun * sheduled as a vPE, especially for the first CPU, and the
3167*4882a593Smuzhiyun * VLPI with INTID larger than 2^(IDbits+1) will be considered
3168*4882a593Smuzhiyun * as out of range and dropped by GIC.
3169*4882a593Smuzhiyun * So we initialize IDbits to known value to avoid VLPI drop.
3170*4882a593Smuzhiyun */
3171*4882a593Smuzhiyun val = (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
3172*4882a593Smuzhiyun pr_debug("GICv4: CPU%d: Init IDbits to 0x%llx for GICR_VPROPBASER\n",
3173*4882a593Smuzhiyun smp_processor_id(), val);
3174*4882a593Smuzhiyun gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
3175*4882a593Smuzhiyun
3176*4882a593Smuzhiyun /*
3177*4882a593Smuzhiyun * Also clear Valid bit of GICR_VPENDBASER, in case some
3178*4882a593Smuzhiyun * ancient programming gets left in and has possibility of
3179*4882a593Smuzhiyun * corrupting memory.
3180*4882a593Smuzhiyun */
3181*4882a593Smuzhiyun val = its_clear_vpend_valid(vlpi_base, 0, 0);
3182*4882a593Smuzhiyun }
3183*4882a593Smuzhiyun
3184*4882a593Smuzhiyun if (allocate_vpe_l1_table()) {
3185*4882a593Smuzhiyun /*
3186*4882a593Smuzhiyun * If the allocation has failed, we're in massive trouble.
3187*4882a593Smuzhiyun * Disable direct injection, and pray that no VM was
3188*4882a593Smuzhiyun * already running...
3189*4882a593Smuzhiyun */
3190*4882a593Smuzhiyun gic_rdists->has_rvpeid = false;
3191*4882a593Smuzhiyun gic_rdists->has_vlpis = false;
3192*4882a593Smuzhiyun }
3193*4882a593Smuzhiyun
3194*4882a593Smuzhiyun /* Make sure the GIC has seen the above */
3195*4882a593Smuzhiyun dsb(sy);
3196*4882a593Smuzhiyun out:
3197*4882a593Smuzhiyun gic_data_rdist()->lpi_enabled = true;
3198*4882a593Smuzhiyun pr_info("GICv3: CPU%d: using %s LPI pending table @%pa\n",
3199*4882a593Smuzhiyun smp_processor_id(),
3200*4882a593Smuzhiyun gic_data_rdist()->pend_page ? "allocated" : "reserved",
3201*4882a593Smuzhiyun &paddr);
3202*4882a593Smuzhiyun }
3203*4882a593Smuzhiyun
its_cpu_init_collection(struct its_node * its)3204*4882a593Smuzhiyun static void its_cpu_init_collection(struct its_node *its)
3205*4882a593Smuzhiyun {
3206*4882a593Smuzhiyun int cpu = smp_processor_id();
3207*4882a593Smuzhiyun u64 target;
3208*4882a593Smuzhiyun
3209*4882a593Smuzhiyun /* avoid cross node collections and its mapping */
3210*4882a593Smuzhiyun if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
3211*4882a593Smuzhiyun struct device_node *cpu_node;
3212*4882a593Smuzhiyun
3213*4882a593Smuzhiyun cpu_node = of_get_cpu_node(cpu, NULL);
3214*4882a593Smuzhiyun if (its->numa_node != NUMA_NO_NODE &&
3215*4882a593Smuzhiyun its->numa_node != of_node_to_nid(cpu_node))
3216*4882a593Smuzhiyun return;
3217*4882a593Smuzhiyun }
3218*4882a593Smuzhiyun
3219*4882a593Smuzhiyun /*
3220*4882a593Smuzhiyun * We now have to bind each collection to its target
3221*4882a593Smuzhiyun * redistributor.
3222*4882a593Smuzhiyun */
3223*4882a593Smuzhiyun if (gic_read_typer(its->base + GITS_TYPER) & GITS_TYPER_PTA) {
3224*4882a593Smuzhiyun /*
3225*4882a593Smuzhiyun * This ITS wants the physical address of the
3226*4882a593Smuzhiyun * redistributor.
3227*4882a593Smuzhiyun */
3228*4882a593Smuzhiyun target = gic_data_rdist()->phys_base;
3229*4882a593Smuzhiyun } else {
3230*4882a593Smuzhiyun /* This ITS wants a linear CPU number. */
3231*4882a593Smuzhiyun target = gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER);
3232*4882a593Smuzhiyun target = GICR_TYPER_CPU_NUMBER(target) << 16;
3233*4882a593Smuzhiyun }
3234*4882a593Smuzhiyun
3235*4882a593Smuzhiyun /* Perform collection mapping */
3236*4882a593Smuzhiyun its->collections[cpu].target_address = target;
3237*4882a593Smuzhiyun its->collections[cpu].col_id = cpu;
3238*4882a593Smuzhiyun
3239*4882a593Smuzhiyun its_send_mapc(its, &its->collections[cpu], 1);
3240*4882a593Smuzhiyun its_send_invall(its, &its->collections[cpu]);
3241*4882a593Smuzhiyun }
3242*4882a593Smuzhiyun
its_cpu_init_collections(void)3243*4882a593Smuzhiyun static void its_cpu_init_collections(void)
3244*4882a593Smuzhiyun {
3245*4882a593Smuzhiyun struct its_node *its;
3246*4882a593Smuzhiyun
3247*4882a593Smuzhiyun raw_spin_lock(&its_lock);
3248*4882a593Smuzhiyun
3249*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry)
3250*4882a593Smuzhiyun its_cpu_init_collection(its);
3251*4882a593Smuzhiyun
3252*4882a593Smuzhiyun raw_spin_unlock(&its_lock);
3253*4882a593Smuzhiyun }
3254*4882a593Smuzhiyun
its_find_device(struct its_node * its,u32 dev_id)3255*4882a593Smuzhiyun static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
3256*4882a593Smuzhiyun {
3257*4882a593Smuzhiyun struct its_device *its_dev = NULL, *tmp;
3258*4882a593Smuzhiyun unsigned long flags;
3259*4882a593Smuzhiyun
3260*4882a593Smuzhiyun raw_spin_lock_irqsave(&its->lock, flags);
3261*4882a593Smuzhiyun
3262*4882a593Smuzhiyun list_for_each_entry(tmp, &its->its_device_list, entry) {
3263*4882a593Smuzhiyun if (tmp->device_id == dev_id) {
3264*4882a593Smuzhiyun its_dev = tmp;
3265*4882a593Smuzhiyun break;
3266*4882a593Smuzhiyun }
3267*4882a593Smuzhiyun }
3268*4882a593Smuzhiyun
3269*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&its->lock, flags);
3270*4882a593Smuzhiyun
3271*4882a593Smuzhiyun return its_dev;
3272*4882a593Smuzhiyun }
3273*4882a593Smuzhiyun
its_get_baser(struct its_node * its,u32 type)3274*4882a593Smuzhiyun static struct its_baser *its_get_baser(struct its_node *its, u32 type)
3275*4882a593Smuzhiyun {
3276*4882a593Smuzhiyun int i;
3277*4882a593Smuzhiyun
3278*4882a593Smuzhiyun for (i = 0; i < GITS_BASER_NR_REGS; i++) {
3279*4882a593Smuzhiyun if (GITS_BASER_TYPE(its->tables[i].val) == type)
3280*4882a593Smuzhiyun return &its->tables[i];
3281*4882a593Smuzhiyun }
3282*4882a593Smuzhiyun
3283*4882a593Smuzhiyun return NULL;
3284*4882a593Smuzhiyun }
3285*4882a593Smuzhiyun
its_alloc_table_entry(struct its_node * its,struct its_baser * baser,u32 id)3286*4882a593Smuzhiyun static bool its_alloc_table_entry(struct its_node *its,
3287*4882a593Smuzhiyun struct its_baser *baser, u32 id)
3288*4882a593Smuzhiyun {
3289*4882a593Smuzhiyun struct page *page;
3290*4882a593Smuzhiyun u32 esz, idx;
3291*4882a593Smuzhiyun __le64 *table;
3292*4882a593Smuzhiyun
3293*4882a593Smuzhiyun /* Don't allow device id that exceeds single, flat table limit */
3294*4882a593Smuzhiyun esz = GITS_BASER_ENTRY_SIZE(baser->val);
3295*4882a593Smuzhiyun if (!(baser->val & GITS_BASER_INDIRECT))
3296*4882a593Smuzhiyun return (id < (PAGE_ORDER_TO_SIZE(baser->order) / esz));
3297*4882a593Smuzhiyun
3298*4882a593Smuzhiyun /* Compute 1st level table index & check if that exceeds table limit */
3299*4882a593Smuzhiyun idx = id >> ilog2(baser->psz / esz);
3300*4882a593Smuzhiyun if (idx >= (PAGE_ORDER_TO_SIZE(baser->order) / GITS_LVL1_ENTRY_SIZE))
3301*4882a593Smuzhiyun return false;
3302*4882a593Smuzhiyun
3303*4882a593Smuzhiyun table = baser->base;
3304*4882a593Smuzhiyun
3305*4882a593Smuzhiyun /* Allocate memory for 2nd level table */
3306*4882a593Smuzhiyun if (!table[idx]) {
3307*4882a593Smuzhiyun gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
3308*4882a593Smuzhiyun
3309*4882a593Smuzhiyun if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566"))
3310*4882a593Smuzhiyun gfp_flags |= GFP_DMA32;
3311*4882a593Smuzhiyun page = alloc_pages_node(its->numa_node, gfp_flags,
3312*4882a593Smuzhiyun get_order(baser->psz));
3313*4882a593Smuzhiyun if (!page)
3314*4882a593Smuzhiyun return false;
3315*4882a593Smuzhiyun
3316*4882a593Smuzhiyun /* Flush Lvl2 table to PoC if hw doesn't support coherency */
3317*4882a593Smuzhiyun if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
3318*4882a593Smuzhiyun gic_flush_dcache_to_poc(page_address(page), baser->psz);
3319*4882a593Smuzhiyun
3320*4882a593Smuzhiyun table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
3321*4882a593Smuzhiyun
3322*4882a593Smuzhiyun /* Flush Lvl1 entry to PoC if hw doesn't support coherency */
3323*4882a593Smuzhiyun if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
3324*4882a593Smuzhiyun gic_flush_dcache_to_poc(table + idx, GITS_LVL1_ENTRY_SIZE);
3325*4882a593Smuzhiyun
3326*4882a593Smuzhiyun /* Ensure updated table contents are visible to ITS hardware */
3327*4882a593Smuzhiyun dsb(sy);
3328*4882a593Smuzhiyun }
3329*4882a593Smuzhiyun
3330*4882a593Smuzhiyun return true;
3331*4882a593Smuzhiyun }
3332*4882a593Smuzhiyun
its_alloc_device_table(struct its_node * its,u32 dev_id)3333*4882a593Smuzhiyun static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
3334*4882a593Smuzhiyun {
3335*4882a593Smuzhiyun struct its_baser *baser;
3336*4882a593Smuzhiyun
3337*4882a593Smuzhiyun baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
3338*4882a593Smuzhiyun
3339*4882a593Smuzhiyun /* Don't allow device id that exceeds ITS hardware limit */
3340*4882a593Smuzhiyun if (!baser)
3341*4882a593Smuzhiyun return (ilog2(dev_id) < device_ids(its));
3342*4882a593Smuzhiyun
3343*4882a593Smuzhiyun return its_alloc_table_entry(its, baser, dev_id);
3344*4882a593Smuzhiyun }
3345*4882a593Smuzhiyun
its_alloc_vpe_table(u32 vpe_id)3346*4882a593Smuzhiyun static bool its_alloc_vpe_table(u32 vpe_id)
3347*4882a593Smuzhiyun {
3348*4882a593Smuzhiyun struct its_node *its;
3349*4882a593Smuzhiyun int cpu;
3350*4882a593Smuzhiyun
3351*4882a593Smuzhiyun /*
3352*4882a593Smuzhiyun * Make sure the L2 tables are allocated on *all* v4 ITSs. We
3353*4882a593Smuzhiyun * could try and only do it on ITSs corresponding to devices
3354*4882a593Smuzhiyun * that have interrupts targeted at this VPE, but the
3355*4882a593Smuzhiyun * complexity becomes crazy (and you have tons of memory
3356*4882a593Smuzhiyun * anyway, right?).
3357*4882a593Smuzhiyun */
3358*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
3359*4882a593Smuzhiyun struct its_baser *baser;
3360*4882a593Smuzhiyun
3361*4882a593Smuzhiyun if (!is_v4(its))
3362*4882a593Smuzhiyun continue;
3363*4882a593Smuzhiyun
3364*4882a593Smuzhiyun baser = its_get_baser(its, GITS_BASER_TYPE_VCPU);
3365*4882a593Smuzhiyun if (!baser)
3366*4882a593Smuzhiyun return false;
3367*4882a593Smuzhiyun
3368*4882a593Smuzhiyun if (!its_alloc_table_entry(its, baser, vpe_id))
3369*4882a593Smuzhiyun return false;
3370*4882a593Smuzhiyun }
3371*4882a593Smuzhiyun
3372*4882a593Smuzhiyun /* Non v4.1? No need to iterate RDs and go back early. */
3373*4882a593Smuzhiyun if (!gic_rdists->has_rvpeid)
3374*4882a593Smuzhiyun return true;
3375*4882a593Smuzhiyun
3376*4882a593Smuzhiyun /*
3377*4882a593Smuzhiyun * Make sure the L2 tables are allocated for all copies of
3378*4882a593Smuzhiyun * the L1 table on *all* v4.1 RDs.
3379*4882a593Smuzhiyun */
3380*4882a593Smuzhiyun for_each_possible_cpu(cpu) {
3381*4882a593Smuzhiyun if (!allocate_vpe_l2_table(cpu, vpe_id))
3382*4882a593Smuzhiyun return false;
3383*4882a593Smuzhiyun }
3384*4882a593Smuzhiyun
3385*4882a593Smuzhiyun return true;
3386*4882a593Smuzhiyun }
3387*4882a593Smuzhiyun
its_create_device(struct its_node * its,u32 dev_id,int nvecs,bool alloc_lpis)3388*4882a593Smuzhiyun static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
3389*4882a593Smuzhiyun int nvecs, bool alloc_lpis)
3390*4882a593Smuzhiyun {
3391*4882a593Smuzhiyun struct its_device *dev;
3392*4882a593Smuzhiyun unsigned long *lpi_map = NULL;
3393*4882a593Smuzhiyun unsigned long flags;
3394*4882a593Smuzhiyun u16 *col_map = NULL;
3395*4882a593Smuzhiyun void *itt;
3396*4882a593Smuzhiyun int lpi_base;
3397*4882a593Smuzhiyun int nr_lpis;
3398*4882a593Smuzhiyun int nr_ites;
3399*4882a593Smuzhiyun int sz;
3400*4882a593Smuzhiyun gfp_t gfp_flags;
3401*4882a593Smuzhiyun
3402*4882a593Smuzhiyun if (!its_alloc_device_table(its, dev_id))
3403*4882a593Smuzhiyun return NULL;
3404*4882a593Smuzhiyun
3405*4882a593Smuzhiyun if (WARN_ON(!is_power_of_2(nvecs)))
3406*4882a593Smuzhiyun nvecs = roundup_pow_of_two(nvecs);
3407*4882a593Smuzhiyun
3408*4882a593Smuzhiyun dev = kzalloc(sizeof(*dev), GFP_KERNEL);
3409*4882a593Smuzhiyun /*
3410*4882a593Smuzhiyun * Even if the device wants a single LPI, the ITT must be
3411*4882a593Smuzhiyun * sized as a power of two (and you need at least one bit...).
3412*4882a593Smuzhiyun */
3413*4882a593Smuzhiyun nr_ites = max(2, nvecs);
3414*4882a593Smuzhiyun sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
3415*4882a593Smuzhiyun sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
3416*4882a593Smuzhiyun gfp_flags = GFP_KERNEL;
3417*4882a593Smuzhiyun if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566")) {
3418*4882a593Smuzhiyun gfp_flags |= GFP_DMA32;
3419*4882a593Smuzhiyun itt = (void *)__get_free_pages(gfp_flags, get_order(sz));
3420*4882a593Smuzhiyun } else {
3421*4882a593Smuzhiyun itt = kzalloc_node(sz, gfp_flags, its->numa_node);
3422*4882a593Smuzhiyun }
3423*4882a593Smuzhiyun
3424*4882a593Smuzhiyun if (alloc_lpis) {
3425*4882a593Smuzhiyun lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);
3426*4882a593Smuzhiyun if (lpi_map)
3427*4882a593Smuzhiyun col_map = kcalloc(nr_lpis, sizeof(*col_map),
3428*4882a593Smuzhiyun GFP_KERNEL);
3429*4882a593Smuzhiyun } else {
3430*4882a593Smuzhiyun col_map = kcalloc(nr_ites, sizeof(*col_map), GFP_KERNEL);
3431*4882a593Smuzhiyun nr_lpis = 0;
3432*4882a593Smuzhiyun lpi_base = 0;
3433*4882a593Smuzhiyun }
3434*4882a593Smuzhiyun
3435*4882a593Smuzhiyun if (!dev || !itt || !col_map || (!lpi_map && alloc_lpis)) {
3436*4882a593Smuzhiyun kfree(dev);
3437*4882a593Smuzhiyun
3438*4882a593Smuzhiyun if (of_machine_is_compatible("rockchip,rk3568") ||
3439*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3566"))
3440*4882a593Smuzhiyun free_pages((unsigned long)itt, get_order(sz));
3441*4882a593Smuzhiyun else
3442*4882a593Smuzhiyun kfree(itt);
3443*4882a593Smuzhiyun
3444*4882a593Smuzhiyun kfree(lpi_map);
3445*4882a593Smuzhiyun kfree(col_map);
3446*4882a593Smuzhiyun return NULL;
3447*4882a593Smuzhiyun }
3448*4882a593Smuzhiyun
3449*4882a593Smuzhiyun gic_flush_dcache_to_poc(itt, sz);
3450*4882a593Smuzhiyun
3451*4882a593Smuzhiyun dev->its = its;
3452*4882a593Smuzhiyun dev->itt = itt;
3453*4882a593Smuzhiyun dev->itt_sz = sz;
3454*4882a593Smuzhiyun dev->nr_ites = nr_ites;
3455*4882a593Smuzhiyun dev->event_map.lpi_map = lpi_map;
3456*4882a593Smuzhiyun dev->event_map.col_map = col_map;
3457*4882a593Smuzhiyun dev->event_map.lpi_base = lpi_base;
3458*4882a593Smuzhiyun dev->event_map.nr_lpis = nr_lpis;
3459*4882a593Smuzhiyun raw_spin_lock_init(&dev->event_map.vlpi_lock);
3460*4882a593Smuzhiyun dev->device_id = dev_id;
3461*4882a593Smuzhiyun INIT_LIST_HEAD(&dev->entry);
3462*4882a593Smuzhiyun
3463*4882a593Smuzhiyun raw_spin_lock_irqsave(&its->lock, flags);
3464*4882a593Smuzhiyun list_add(&dev->entry, &its->its_device_list);
3465*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&its->lock, flags);
3466*4882a593Smuzhiyun
3467*4882a593Smuzhiyun /* Map device to its ITT */
3468*4882a593Smuzhiyun its_send_mapd(dev, 1);
3469*4882a593Smuzhiyun
3470*4882a593Smuzhiyun return dev;
3471*4882a593Smuzhiyun }
3472*4882a593Smuzhiyun
its_free_device(struct its_device * its_dev)3473*4882a593Smuzhiyun static void its_free_device(struct its_device *its_dev)
3474*4882a593Smuzhiyun {
3475*4882a593Smuzhiyun unsigned long flags;
3476*4882a593Smuzhiyun
3477*4882a593Smuzhiyun raw_spin_lock_irqsave(&its_dev->its->lock, flags);
3478*4882a593Smuzhiyun list_del(&its_dev->entry);
3479*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&its_dev->its->lock, flags);
3480*4882a593Smuzhiyun kfree(its_dev->event_map.col_map);
3481*4882a593Smuzhiyun
3482*4882a593Smuzhiyun if (of_machine_is_compatible("rockchip,rk3568") ||
3483*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3566"))
3484*4882a593Smuzhiyun free_pages((unsigned long)its_dev->itt, get_order(its_dev->itt_sz));
3485*4882a593Smuzhiyun else
3486*4882a593Smuzhiyun kfree(its_dev->itt);
3487*4882a593Smuzhiyun
3488*4882a593Smuzhiyun kfree(its_dev);
3489*4882a593Smuzhiyun }
3490*4882a593Smuzhiyun
its_alloc_device_irq(struct its_device * dev,int nvecs,irq_hw_number_t * hwirq)3491*4882a593Smuzhiyun static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number_t *hwirq)
3492*4882a593Smuzhiyun {
3493*4882a593Smuzhiyun int idx;
3494*4882a593Smuzhiyun
3495*4882a593Smuzhiyun /* Find a free LPI region in lpi_map and allocate them. */
3496*4882a593Smuzhiyun idx = bitmap_find_free_region(dev->event_map.lpi_map,
3497*4882a593Smuzhiyun dev->event_map.nr_lpis,
3498*4882a593Smuzhiyun get_count_order(nvecs));
3499*4882a593Smuzhiyun if (idx < 0)
3500*4882a593Smuzhiyun return -ENOSPC;
3501*4882a593Smuzhiyun
3502*4882a593Smuzhiyun *hwirq = dev->event_map.lpi_base + idx;
3503*4882a593Smuzhiyun
3504*4882a593Smuzhiyun return 0;
3505*4882a593Smuzhiyun }
3506*4882a593Smuzhiyun
its_msi_prepare(struct irq_domain * domain,struct device * dev,int nvec,msi_alloc_info_t * info)3507*4882a593Smuzhiyun static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
3508*4882a593Smuzhiyun int nvec, msi_alloc_info_t *info)
3509*4882a593Smuzhiyun {
3510*4882a593Smuzhiyun struct its_node *its;
3511*4882a593Smuzhiyun struct its_device *its_dev;
3512*4882a593Smuzhiyun struct msi_domain_info *msi_info;
3513*4882a593Smuzhiyun u32 dev_id;
3514*4882a593Smuzhiyun int err = 0;
3515*4882a593Smuzhiyun
3516*4882a593Smuzhiyun /*
3517*4882a593Smuzhiyun * We ignore "dev" entirely, and rely on the dev_id that has
3518*4882a593Smuzhiyun * been passed via the scratchpad. This limits this domain's
3519*4882a593Smuzhiyun * usefulness to upper layers that definitely know that they
3520*4882a593Smuzhiyun * are built on top of the ITS.
3521*4882a593Smuzhiyun */
3522*4882a593Smuzhiyun dev_id = info->scratchpad[0].ul;
3523*4882a593Smuzhiyun
3524*4882a593Smuzhiyun msi_info = msi_get_domain_info(domain);
3525*4882a593Smuzhiyun its = msi_info->data;
3526*4882a593Smuzhiyun
3527*4882a593Smuzhiyun if (!gic_rdists->has_direct_lpi &&
3528*4882a593Smuzhiyun vpe_proxy.dev &&
3529*4882a593Smuzhiyun vpe_proxy.dev->its == its &&
3530*4882a593Smuzhiyun dev_id == vpe_proxy.dev->device_id) {
3531*4882a593Smuzhiyun /* Bad luck. Get yourself a better implementation */
3532*4882a593Smuzhiyun WARN_ONCE(1, "DevId %x clashes with GICv4 VPE proxy device\n",
3533*4882a593Smuzhiyun dev_id);
3534*4882a593Smuzhiyun return -EINVAL;
3535*4882a593Smuzhiyun }
3536*4882a593Smuzhiyun
3537*4882a593Smuzhiyun mutex_lock(&its->dev_alloc_lock);
3538*4882a593Smuzhiyun its_dev = its_find_device(its, dev_id);
3539*4882a593Smuzhiyun if (its_dev) {
3540*4882a593Smuzhiyun /*
3541*4882a593Smuzhiyun * We already have seen this ID, probably through
3542*4882a593Smuzhiyun * another alias (PCI bridge of some sort). No need to
3543*4882a593Smuzhiyun * create the device.
3544*4882a593Smuzhiyun */
3545*4882a593Smuzhiyun its_dev->shared = true;
3546*4882a593Smuzhiyun pr_debug("Reusing ITT for devID %x\n", dev_id);
3547*4882a593Smuzhiyun goto out;
3548*4882a593Smuzhiyun }
3549*4882a593Smuzhiyun
3550*4882a593Smuzhiyun its_dev = its_create_device(its, dev_id, nvec, true);
3551*4882a593Smuzhiyun if (!its_dev) {
3552*4882a593Smuzhiyun err = -ENOMEM;
3553*4882a593Smuzhiyun goto out;
3554*4882a593Smuzhiyun }
3555*4882a593Smuzhiyun
3556*4882a593Smuzhiyun pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
3557*4882a593Smuzhiyun out:
3558*4882a593Smuzhiyun mutex_unlock(&its->dev_alloc_lock);
3559*4882a593Smuzhiyun info->scratchpad[0].ptr = its_dev;
3560*4882a593Smuzhiyun return err;
3561*4882a593Smuzhiyun }
3562*4882a593Smuzhiyun
3563*4882a593Smuzhiyun static struct msi_domain_ops its_msi_domain_ops = {
3564*4882a593Smuzhiyun .msi_prepare = its_msi_prepare,
3565*4882a593Smuzhiyun };
3566*4882a593Smuzhiyun
its_irq_gic_domain_alloc(struct irq_domain * domain,unsigned int virq,irq_hw_number_t hwirq)3567*4882a593Smuzhiyun static int its_irq_gic_domain_alloc(struct irq_domain *domain,
3568*4882a593Smuzhiyun unsigned int virq,
3569*4882a593Smuzhiyun irq_hw_number_t hwirq)
3570*4882a593Smuzhiyun {
3571*4882a593Smuzhiyun struct irq_fwspec fwspec;
3572*4882a593Smuzhiyun
3573*4882a593Smuzhiyun if (irq_domain_get_of_node(domain->parent)) {
3574*4882a593Smuzhiyun fwspec.fwnode = domain->parent->fwnode;
3575*4882a593Smuzhiyun fwspec.param_count = 3;
3576*4882a593Smuzhiyun fwspec.param[0] = GIC_IRQ_TYPE_LPI;
3577*4882a593Smuzhiyun fwspec.param[1] = hwirq;
3578*4882a593Smuzhiyun fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
3579*4882a593Smuzhiyun } else if (is_fwnode_irqchip(domain->parent->fwnode)) {
3580*4882a593Smuzhiyun fwspec.fwnode = domain->parent->fwnode;
3581*4882a593Smuzhiyun fwspec.param_count = 2;
3582*4882a593Smuzhiyun fwspec.param[0] = hwirq;
3583*4882a593Smuzhiyun fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
3584*4882a593Smuzhiyun } else {
3585*4882a593Smuzhiyun return -EINVAL;
3586*4882a593Smuzhiyun }
3587*4882a593Smuzhiyun
3588*4882a593Smuzhiyun return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
3589*4882a593Smuzhiyun }
3590*4882a593Smuzhiyun
its_irq_domain_alloc(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs,void * args)3591*4882a593Smuzhiyun static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
3592*4882a593Smuzhiyun unsigned int nr_irqs, void *args)
3593*4882a593Smuzhiyun {
3594*4882a593Smuzhiyun msi_alloc_info_t *info = args;
3595*4882a593Smuzhiyun struct its_device *its_dev = info->scratchpad[0].ptr;
3596*4882a593Smuzhiyun struct its_node *its = its_dev->its;
3597*4882a593Smuzhiyun struct irq_data *irqd;
3598*4882a593Smuzhiyun irq_hw_number_t hwirq;
3599*4882a593Smuzhiyun int err;
3600*4882a593Smuzhiyun int i;
3601*4882a593Smuzhiyun
3602*4882a593Smuzhiyun err = its_alloc_device_irq(its_dev, nr_irqs, &hwirq);
3603*4882a593Smuzhiyun if (err)
3604*4882a593Smuzhiyun return err;
3605*4882a593Smuzhiyun
3606*4882a593Smuzhiyun err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev));
3607*4882a593Smuzhiyun if (err)
3608*4882a593Smuzhiyun return err;
3609*4882a593Smuzhiyun
3610*4882a593Smuzhiyun for (i = 0; i < nr_irqs; i++) {
3611*4882a593Smuzhiyun err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
3612*4882a593Smuzhiyun if (err)
3613*4882a593Smuzhiyun return err;
3614*4882a593Smuzhiyun
3615*4882a593Smuzhiyun irq_domain_set_hwirq_and_chip(domain, virq + i,
3616*4882a593Smuzhiyun hwirq + i, &its_irq_chip, its_dev);
3617*4882a593Smuzhiyun irqd = irq_get_irq_data(virq + i);
3618*4882a593Smuzhiyun irqd_set_single_target(irqd);
3619*4882a593Smuzhiyun irqd_set_affinity_on_activate(irqd);
3620*4882a593Smuzhiyun pr_debug("ID:%d pID:%d vID:%d\n",
3621*4882a593Smuzhiyun (int)(hwirq + i - its_dev->event_map.lpi_base),
3622*4882a593Smuzhiyun (int)(hwirq + i), virq + i);
3623*4882a593Smuzhiyun }
3624*4882a593Smuzhiyun
3625*4882a593Smuzhiyun return 0;
3626*4882a593Smuzhiyun }
3627*4882a593Smuzhiyun
its_irq_domain_activate(struct irq_domain * domain,struct irq_data * d,bool reserve)3628*4882a593Smuzhiyun static int its_irq_domain_activate(struct irq_domain *domain,
3629*4882a593Smuzhiyun struct irq_data *d, bool reserve)
3630*4882a593Smuzhiyun {
3631*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
3632*4882a593Smuzhiyun u32 event = its_get_event_id(d);
3633*4882a593Smuzhiyun int cpu;
3634*4882a593Smuzhiyun
3635*4882a593Smuzhiyun cpu = its_select_cpu(d, cpu_online_mask);
3636*4882a593Smuzhiyun if (cpu < 0 || cpu >= nr_cpu_ids)
3637*4882a593Smuzhiyun return -EINVAL;
3638*4882a593Smuzhiyun
3639*4882a593Smuzhiyun its_inc_lpi_count(d, cpu);
3640*4882a593Smuzhiyun its_dev->event_map.col_map[event] = cpu;
3641*4882a593Smuzhiyun irq_data_update_effective_affinity(d, cpumask_of(cpu));
3642*4882a593Smuzhiyun
3643*4882a593Smuzhiyun /* Map the GIC IRQ and event to the device */
3644*4882a593Smuzhiyun its_send_mapti(its_dev, d->hwirq, event);
3645*4882a593Smuzhiyun return 0;
3646*4882a593Smuzhiyun }
3647*4882a593Smuzhiyun
its_irq_domain_deactivate(struct irq_domain * domain,struct irq_data * d)3648*4882a593Smuzhiyun static void its_irq_domain_deactivate(struct irq_domain *domain,
3649*4882a593Smuzhiyun struct irq_data *d)
3650*4882a593Smuzhiyun {
3651*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
3652*4882a593Smuzhiyun u32 event = its_get_event_id(d);
3653*4882a593Smuzhiyun
3654*4882a593Smuzhiyun its_dec_lpi_count(d, its_dev->event_map.col_map[event]);
3655*4882a593Smuzhiyun /* Stop the delivery of interrupts */
3656*4882a593Smuzhiyun its_send_discard(its_dev, event);
3657*4882a593Smuzhiyun }
3658*4882a593Smuzhiyun
its_irq_domain_free(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs)3659*4882a593Smuzhiyun static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
3660*4882a593Smuzhiyun unsigned int nr_irqs)
3661*4882a593Smuzhiyun {
3662*4882a593Smuzhiyun struct irq_data *d = irq_domain_get_irq_data(domain, virq);
3663*4882a593Smuzhiyun struct its_device *its_dev = irq_data_get_irq_chip_data(d);
3664*4882a593Smuzhiyun struct its_node *its = its_dev->its;
3665*4882a593Smuzhiyun int i;
3666*4882a593Smuzhiyun
3667*4882a593Smuzhiyun bitmap_release_region(its_dev->event_map.lpi_map,
3668*4882a593Smuzhiyun its_get_event_id(irq_domain_get_irq_data(domain, virq)),
3669*4882a593Smuzhiyun get_count_order(nr_irqs));
3670*4882a593Smuzhiyun
3671*4882a593Smuzhiyun for (i = 0; i < nr_irqs; i++) {
3672*4882a593Smuzhiyun struct irq_data *data = irq_domain_get_irq_data(domain,
3673*4882a593Smuzhiyun virq + i);
3674*4882a593Smuzhiyun /* Nuke the entry in the domain */
3675*4882a593Smuzhiyun irq_domain_reset_irq_data(data);
3676*4882a593Smuzhiyun }
3677*4882a593Smuzhiyun
3678*4882a593Smuzhiyun mutex_lock(&its->dev_alloc_lock);
3679*4882a593Smuzhiyun
3680*4882a593Smuzhiyun /*
3681*4882a593Smuzhiyun * If all interrupts have been freed, start mopping the
3682*4882a593Smuzhiyun * floor. This is conditionned on the device not being shared.
3683*4882a593Smuzhiyun */
3684*4882a593Smuzhiyun if (!its_dev->shared &&
3685*4882a593Smuzhiyun bitmap_empty(its_dev->event_map.lpi_map,
3686*4882a593Smuzhiyun its_dev->event_map.nr_lpis)) {
3687*4882a593Smuzhiyun its_lpi_free(its_dev->event_map.lpi_map,
3688*4882a593Smuzhiyun its_dev->event_map.lpi_base,
3689*4882a593Smuzhiyun its_dev->event_map.nr_lpis);
3690*4882a593Smuzhiyun
3691*4882a593Smuzhiyun /* Unmap device/itt */
3692*4882a593Smuzhiyun its_send_mapd(its_dev, 0);
3693*4882a593Smuzhiyun its_free_device(its_dev);
3694*4882a593Smuzhiyun }
3695*4882a593Smuzhiyun
3696*4882a593Smuzhiyun mutex_unlock(&its->dev_alloc_lock);
3697*4882a593Smuzhiyun
3698*4882a593Smuzhiyun irq_domain_free_irqs_parent(domain, virq, nr_irqs);
3699*4882a593Smuzhiyun }
3700*4882a593Smuzhiyun
3701*4882a593Smuzhiyun static const struct irq_domain_ops its_domain_ops = {
3702*4882a593Smuzhiyun .alloc = its_irq_domain_alloc,
3703*4882a593Smuzhiyun .free = its_irq_domain_free,
3704*4882a593Smuzhiyun .activate = its_irq_domain_activate,
3705*4882a593Smuzhiyun .deactivate = its_irq_domain_deactivate,
3706*4882a593Smuzhiyun };
3707*4882a593Smuzhiyun
3708*4882a593Smuzhiyun /*
3709*4882a593Smuzhiyun * This is insane.
3710*4882a593Smuzhiyun *
3711*4882a593Smuzhiyun * If a GICv4.0 doesn't implement Direct LPIs (which is extremely
3712*4882a593Smuzhiyun * likely), the only way to perform an invalidate is to use a fake
3713*4882a593Smuzhiyun * device to issue an INV command, implying that the LPI has first
3714*4882a593Smuzhiyun * been mapped to some event on that device. Since this is not exactly
3715*4882a593Smuzhiyun * cheap, we try to keep that mapping around as long as possible, and
3716*4882a593Smuzhiyun * only issue an UNMAP if we're short on available slots.
3717*4882a593Smuzhiyun *
3718*4882a593Smuzhiyun * Broken by design(tm).
3719*4882a593Smuzhiyun *
3720*4882a593Smuzhiyun * GICv4.1, on the other hand, mandates that we're able to invalidate
3721*4882a593Smuzhiyun * by writing to a MMIO register. It doesn't implement the whole of
3722*4882a593Smuzhiyun * DirectLPI, but that's good enough. And most of the time, we don't
3723*4882a593Smuzhiyun * even have to invalidate anything, as the redistributor can be told
3724*4882a593Smuzhiyun * whether to generate a doorbell or not (we thus leave it enabled,
3725*4882a593Smuzhiyun * always).
3726*4882a593Smuzhiyun */
its_vpe_db_proxy_unmap_locked(struct its_vpe * vpe)3727*4882a593Smuzhiyun static void its_vpe_db_proxy_unmap_locked(struct its_vpe *vpe)
3728*4882a593Smuzhiyun {
3729*4882a593Smuzhiyun /* GICv4.1 doesn't use a proxy, so nothing to do here */
3730*4882a593Smuzhiyun if (gic_rdists->has_rvpeid)
3731*4882a593Smuzhiyun return;
3732*4882a593Smuzhiyun
3733*4882a593Smuzhiyun /* Already unmapped? */
3734*4882a593Smuzhiyun if (vpe->vpe_proxy_event == -1)
3735*4882a593Smuzhiyun return;
3736*4882a593Smuzhiyun
3737*4882a593Smuzhiyun its_send_discard(vpe_proxy.dev, vpe->vpe_proxy_event);
3738*4882a593Smuzhiyun vpe_proxy.vpes[vpe->vpe_proxy_event] = NULL;
3739*4882a593Smuzhiyun
3740*4882a593Smuzhiyun /*
3741*4882a593Smuzhiyun * We don't track empty slots at all, so let's move the
3742*4882a593Smuzhiyun * next_victim pointer if we can quickly reuse that slot
3743*4882a593Smuzhiyun * instead of nuking an existing entry. Not clear that this is
3744*4882a593Smuzhiyun * always a win though, and this might just generate a ripple
3745*4882a593Smuzhiyun * effect... Let's just hope VPEs don't migrate too often.
3746*4882a593Smuzhiyun */
3747*4882a593Smuzhiyun if (vpe_proxy.vpes[vpe_proxy.next_victim])
3748*4882a593Smuzhiyun vpe_proxy.next_victim = vpe->vpe_proxy_event;
3749*4882a593Smuzhiyun
3750*4882a593Smuzhiyun vpe->vpe_proxy_event = -1;
3751*4882a593Smuzhiyun }
3752*4882a593Smuzhiyun
its_vpe_db_proxy_unmap(struct its_vpe * vpe)3753*4882a593Smuzhiyun static void its_vpe_db_proxy_unmap(struct its_vpe *vpe)
3754*4882a593Smuzhiyun {
3755*4882a593Smuzhiyun /* GICv4.1 doesn't use a proxy, so nothing to do here */
3756*4882a593Smuzhiyun if (gic_rdists->has_rvpeid)
3757*4882a593Smuzhiyun return;
3758*4882a593Smuzhiyun
3759*4882a593Smuzhiyun if (!gic_rdists->has_direct_lpi) {
3760*4882a593Smuzhiyun unsigned long flags;
3761*4882a593Smuzhiyun
3762*4882a593Smuzhiyun raw_spin_lock_irqsave(&vpe_proxy.lock, flags);
3763*4882a593Smuzhiyun its_vpe_db_proxy_unmap_locked(vpe);
3764*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&vpe_proxy.lock, flags);
3765*4882a593Smuzhiyun }
3766*4882a593Smuzhiyun }
3767*4882a593Smuzhiyun
its_vpe_db_proxy_map_locked(struct its_vpe * vpe)3768*4882a593Smuzhiyun static void its_vpe_db_proxy_map_locked(struct its_vpe *vpe)
3769*4882a593Smuzhiyun {
3770*4882a593Smuzhiyun /* GICv4.1 doesn't use a proxy, so nothing to do here */
3771*4882a593Smuzhiyun if (gic_rdists->has_rvpeid)
3772*4882a593Smuzhiyun return;
3773*4882a593Smuzhiyun
3774*4882a593Smuzhiyun /* Already mapped? */
3775*4882a593Smuzhiyun if (vpe->vpe_proxy_event != -1)
3776*4882a593Smuzhiyun return;
3777*4882a593Smuzhiyun
3778*4882a593Smuzhiyun /* This slot was already allocated. Kick the other VPE out. */
3779*4882a593Smuzhiyun if (vpe_proxy.vpes[vpe_proxy.next_victim])
3780*4882a593Smuzhiyun its_vpe_db_proxy_unmap_locked(vpe_proxy.vpes[vpe_proxy.next_victim]);
3781*4882a593Smuzhiyun
3782*4882a593Smuzhiyun /* Map the new VPE instead */
3783*4882a593Smuzhiyun vpe_proxy.vpes[vpe_proxy.next_victim] = vpe;
3784*4882a593Smuzhiyun vpe->vpe_proxy_event = vpe_proxy.next_victim;
3785*4882a593Smuzhiyun vpe_proxy.next_victim = (vpe_proxy.next_victim + 1) % vpe_proxy.dev->nr_ites;
3786*4882a593Smuzhiyun
3787*4882a593Smuzhiyun vpe_proxy.dev->event_map.col_map[vpe->vpe_proxy_event] = vpe->col_idx;
3788*4882a593Smuzhiyun its_send_mapti(vpe_proxy.dev, vpe->vpe_db_lpi, vpe->vpe_proxy_event);
3789*4882a593Smuzhiyun }
3790*4882a593Smuzhiyun
its_vpe_db_proxy_move(struct its_vpe * vpe,int from,int to)3791*4882a593Smuzhiyun static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to)
3792*4882a593Smuzhiyun {
3793*4882a593Smuzhiyun unsigned long flags;
3794*4882a593Smuzhiyun struct its_collection *target_col;
3795*4882a593Smuzhiyun
3796*4882a593Smuzhiyun /* GICv4.1 doesn't use a proxy, so nothing to do here */
3797*4882a593Smuzhiyun if (gic_rdists->has_rvpeid)
3798*4882a593Smuzhiyun return;
3799*4882a593Smuzhiyun
3800*4882a593Smuzhiyun if (gic_rdists->has_direct_lpi) {
3801*4882a593Smuzhiyun void __iomem *rdbase;
3802*4882a593Smuzhiyun
3803*4882a593Smuzhiyun rdbase = per_cpu_ptr(gic_rdists->rdist, from)->rd_base;
3804*4882a593Smuzhiyun gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_CLRLPIR);
3805*4882a593Smuzhiyun wait_for_syncr(rdbase);
3806*4882a593Smuzhiyun
3807*4882a593Smuzhiyun return;
3808*4882a593Smuzhiyun }
3809*4882a593Smuzhiyun
3810*4882a593Smuzhiyun raw_spin_lock_irqsave(&vpe_proxy.lock, flags);
3811*4882a593Smuzhiyun
3812*4882a593Smuzhiyun its_vpe_db_proxy_map_locked(vpe);
3813*4882a593Smuzhiyun
3814*4882a593Smuzhiyun target_col = &vpe_proxy.dev->its->collections[to];
3815*4882a593Smuzhiyun its_send_movi(vpe_proxy.dev, target_col, vpe->vpe_proxy_event);
3816*4882a593Smuzhiyun vpe_proxy.dev->event_map.col_map[vpe->vpe_proxy_event] = to;
3817*4882a593Smuzhiyun
3818*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&vpe_proxy.lock, flags);
3819*4882a593Smuzhiyun }
3820*4882a593Smuzhiyun
its_vpe_set_affinity(struct irq_data * d,const struct cpumask * mask_val,bool force)3821*4882a593Smuzhiyun static int its_vpe_set_affinity(struct irq_data *d,
3822*4882a593Smuzhiyun const struct cpumask *mask_val,
3823*4882a593Smuzhiyun bool force)
3824*4882a593Smuzhiyun {
3825*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
3826*4882a593Smuzhiyun int from, cpu = cpumask_first(mask_val);
3827*4882a593Smuzhiyun unsigned long flags;
3828*4882a593Smuzhiyun
3829*4882a593Smuzhiyun /*
3830*4882a593Smuzhiyun * Changing affinity is mega expensive, so let's be as lazy as
3831*4882a593Smuzhiyun * we can and only do it if we really have to. Also, if mapped
3832*4882a593Smuzhiyun * into the proxy device, we need to move the doorbell
3833*4882a593Smuzhiyun * interrupt to its new location.
3834*4882a593Smuzhiyun *
3835*4882a593Smuzhiyun * Another thing is that changing the affinity of a vPE affects
3836*4882a593Smuzhiyun * *other interrupts* such as all the vLPIs that are routed to
3837*4882a593Smuzhiyun * this vPE. This means that the irq_desc lock is not enough to
3838*4882a593Smuzhiyun * protect us, and that we must ensure nobody samples vpe->col_idx
3839*4882a593Smuzhiyun * during the update, hence the lock below which must also be
3840*4882a593Smuzhiyun * taken on any vLPI handling path that evaluates vpe->col_idx.
3841*4882a593Smuzhiyun */
3842*4882a593Smuzhiyun from = vpe_to_cpuid_lock(vpe, &flags);
3843*4882a593Smuzhiyun if (from == cpu)
3844*4882a593Smuzhiyun goto out;
3845*4882a593Smuzhiyun
3846*4882a593Smuzhiyun vpe->col_idx = cpu;
3847*4882a593Smuzhiyun
3848*4882a593Smuzhiyun /*
3849*4882a593Smuzhiyun * GICv4.1 allows us to skip VMOVP if moving to a cpu whose RD
3850*4882a593Smuzhiyun * is sharing its VPE table with the current one.
3851*4882a593Smuzhiyun */
3852*4882a593Smuzhiyun if (gic_data_rdist_cpu(cpu)->vpe_table_mask &&
3853*4882a593Smuzhiyun cpumask_test_cpu(from, gic_data_rdist_cpu(cpu)->vpe_table_mask))
3854*4882a593Smuzhiyun goto out;
3855*4882a593Smuzhiyun
3856*4882a593Smuzhiyun its_send_vmovp(vpe);
3857*4882a593Smuzhiyun its_vpe_db_proxy_move(vpe, from, cpu);
3858*4882a593Smuzhiyun
3859*4882a593Smuzhiyun out:
3860*4882a593Smuzhiyun irq_data_update_effective_affinity(d, cpumask_of(cpu));
3861*4882a593Smuzhiyun vpe_to_cpuid_unlock(vpe, flags);
3862*4882a593Smuzhiyun
3863*4882a593Smuzhiyun return IRQ_SET_MASK_OK_DONE;
3864*4882a593Smuzhiyun }
3865*4882a593Smuzhiyun
its_wait_vpt_parse_complete(void)3866*4882a593Smuzhiyun static void its_wait_vpt_parse_complete(void)
3867*4882a593Smuzhiyun {
3868*4882a593Smuzhiyun void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
3869*4882a593Smuzhiyun u64 val;
3870*4882a593Smuzhiyun
3871*4882a593Smuzhiyun if (!gic_rdists->has_vpend_valid_dirty)
3872*4882a593Smuzhiyun return;
3873*4882a593Smuzhiyun
3874*4882a593Smuzhiyun WARN_ON_ONCE(readq_relaxed_poll_timeout_atomic(vlpi_base + GICR_VPENDBASER,
3875*4882a593Smuzhiyun val,
3876*4882a593Smuzhiyun !(val & GICR_VPENDBASER_Dirty),
3877*4882a593Smuzhiyun 10, 500));
3878*4882a593Smuzhiyun }
3879*4882a593Smuzhiyun
its_vpe_schedule(struct its_vpe * vpe)3880*4882a593Smuzhiyun static void its_vpe_schedule(struct its_vpe *vpe)
3881*4882a593Smuzhiyun {
3882*4882a593Smuzhiyun void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
3883*4882a593Smuzhiyun u64 val;
3884*4882a593Smuzhiyun
3885*4882a593Smuzhiyun /* Schedule the VPE */
3886*4882a593Smuzhiyun val = virt_to_phys(page_address(vpe->its_vm->vprop_page)) &
3887*4882a593Smuzhiyun GENMASK_ULL(51, 12);
3888*4882a593Smuzhiyun val |= (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
3889*4882a593Smuzhiyun val |= GICR_VPROPBASER_RaWb;
3890*4882a593Smuzhiyun val |= GICR_VPROPBASER_InnerShareable;
3891*4882a593Smuzhiyun gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
3892*4882a593Smuzhiyun
3893*4882a593Smuzhiyun val = virt_to_phys(page_address(vpe->vpt_page)) &
3894*4882a593Smuzhiyun GENMASK_ULL(51, 16);
3895*4882a593Smuzhiyun val |= GICR_VPENDBASER_RaWaWb;
3896*4882a593Smuzhiyun val |= GICR_VPENDBASER_InnerShareable;
3897*4882a593Smuzhiyun /*
3898*4882a593Smuzhiyun * There is no good way of finding out if the pending table is
3899*4882a593Smuzhiyun * empty as we can race against the doorbell interrupt very
3900*4882a593Smuzhiyun * easily. So in the end, vpe->pending_last is only an
3901*4882a593Smuzhiyun * indication that the vcpu has something pending, not one
3902*4882a593Smuzhiyun * that the pending table is empty. A good implementation
3903*4882a593Smuzhiyun * would be able to read its coarse map pretty quickly anyway,
3904*4882a593Smuzhiyun * making this a tolerable issue.
3905*4882a593Smuzhiyun */
3906*4882a593Smuzhiyun val |= GICR_VPENDBASER_PendingLast;
3907*4882a593Smuzhiyun val |= vpe->idai ? GICR_VPENDBASER_IDAI : 0;
3908*4882a593Smuzhiyun val |= GICR_VPENDBASER_Valid;
3909*4882a593Smuzhiyun gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
3910*4882a593Smuzhiyun }
3911*4882a593Smuzhiyun
its_vpe_deschedule(struct its_vpe * vpe)3912*4882a593Smuzhiyun static void its_vpe_deschedule(struct its_vpe *vpe)
3913*4882a593Smuzhiyun {
3914*4882a593Smuzhiyun void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
3915*4882a593Smuzhiyun u64 val;
3916*4882a593Smuzhiyun
3917*4882a593Smuzhiyun val = its_clear_vpend_valid(vlpi_base, 0, 0);
3918*4882a593Smuzhiyun
3919*4882a593Smuzhiyun vpe->idai = !!(val & GICR_VPENDBASER_IDAI);
3920*4882a593Smuzhiyun vpe->pending_last = !!(val & GICR_VPENDBASER_PendingLast);
3921*4882a593Smuzhiyun }
3922*4882a593Smuzhiyun
its_vpe_invall(struct its_vpe * vpe)3923*4882a593Smuzhiyun static void its_vpe_invall(struct its_vpe *vpe)
3924*4882a593Smuzhiyun {
3925*4882a593Smuzhiyun struct its_node *its;
3926*4882a593Smuzhiyun
3927*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
3928*4882a593Smuzhiyun if (!is_v4(its))
3929*4882a593Smuzhiyun continue;
3930*4882a593Smuzhiyun
3931*4882a593Smuzhiyun if (its_list_map && !vpe->its_vm->vlpi_count[its->list_nr])
3932*4882a593Smuzhiyun continue;
3933*4882a593Smuzhiyun
3934*4882a593Smuzhiyun /*
3935*4882a593Smuzhiyun * Sending a VINVALL to a single ITS is enough, as all
3936*4882a593Smuzhiyun * we need is to reach the redistributors.
3937*4882a593Smuzhiyun */
3938*4882a593Smuzhiyun its_send_vinvall(its, vpe);
3939*4882a593Smuzhiyun return;
3940*4882a593Smuzhiyun }
3941*4882a593Smuzhiyun }
3942*4882a593Smuzhiyun
its_vpe_set_vcpu_affinity(struct irq_data * d,void * vcpu_info)3943*4882a593Smuzhiyun static int its_vpe_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
3944*4882a593Smuzhiyun {
3945*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
3946*4882a593Smuzhiyun struct its_cmd_info *info = vcpu_info;
3947*4882a593Smuzhiyun
3948*4882a593Smuzhiyun switch (info->cmd_type) {
3949*4882a593Smuzhiyun case SCHEDULE_VPE:
3950*4882a593Smuzhiyun its_vpe_schedule(vpe);
3951*4882a593Smuzhiyun return 0;
3952*4882a593Smuzhiyun
3953*4882a593Smuzhiyun case DESCHEDULE_VPE:
3954*4882a593Smuzhiyun its_vpe_deschedule(vpe);
3955*4882a593Smuzhiyun return 0;
3956*4882a593Smuzhiyun
3957*4882a593Smuzhiyun case COMMIT_VPE:
3958*4882a593Smuzhiyun its_wait_vpt_parse_complete();
3959*4882a593Smuzhiyun return 0;
3960*4882a593Smuzhiyun
3961*4882a593Smuzhiyun case INVALL_VPE:
3962*4882a593Smuzhiyun its_vpe_invall(vpe);
3963*4882a593Smuzhiyun return 0;
3964*4882a593Smuzhiyun
3965*4882a593Smuzhiyun default:
3966*4882a593Smuzhiyun return -EINVAL;
3967*4882a593Smuzhiyun }
3968*4882a593Smuzhiyun }
3969*4882a593Smuzhiyun
its_vpe_send_cmd(struct its_vpe * vpe,void (* cmd)(struct its_device *,u32))3970*4882a593Smuzhiyun static void its_vpe_send_cmd(struct its_vpe *vpe,
3971*4882a593Smuzhiyun void (*cmd)(struct its_device *, u32))
3972*4882a593Smuzhiyun {
3973*4882a593Smuzhiyun unsigned long flags;
3974*4882a593Smuzhiyun
3975*4882a593Smuzhiyun raw_spin_lock_irqsave(&vpe_proxy.lock, flags);
3976*4882a593Smuzhiyun
3977*4882a593Smuzhiyun its_vpe_db_proxy_map_locked(vpe);
3978*4882a593Smuzhiyun cmd(vpe_proxy.dev, vpe->vpe_proxy_event);
3979*4882a593Smuzhiyun
3980*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&vpe_proxy.lock, flags);
3981*4882a593Smuzhiyun }
3982*4882a593Smuzhiyun
its_vpe_send_inv(struct irq_data * d)3983*4882a593Smuzhiyun static void its_vpe_send_inv(struct irq_data *d)
3984*4882a593Smuzhiyun {
3985*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
3986*4882a593Smuzhiyun
3987*4882a593Smuzhiyun if (gic_rdists->has_direct_lpi) {
3988*4882a593Smuzhiyun void __iomem *rdbase;
3989*4882a593Smuzhiyun
3990*4882a593Smuzhiyun /* Target the redistributor this VPE is currently known on */
3991*4882a593Smuzhiyun raw_spin_lock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
3992*4882a593Smuzhiyun rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
3993*4882a593Smuzhiyun gic_write_lpir(d->parent_data->hwirq, rdbase + GICR_INVLPIR);
3994*4882a593Smuzhiyun wait_for_syncr(rdbase);
3995*4882a593Smuzhiyun raw_spin_unlock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
3996*4882a593Smuzhiyun } else {
3997*4882a593Smuzhiyun its_vpe_send_cmd(vpe, its_send_inv);
3998*4882a593Smuzhiyun }
3999*4882a593Smuzhiyun }
4000*4882a593Smuzhiyun
its_vpe_mask_irq(struct irq_data * d)4001*4882a593Smuzhiyun static void its_vpe_mask_irq(struct irq_data *d)
4002*4882a593Smuzhiyun {
4003*4882a593Smuzhiyun /*
4004*4882a593Smuzhiyun * We need to unmask the LPI, which is described by the parent
4005*4882a593Smuzhiyun * irq_data. Instead of calling into the parent (which won't
4006*4882a593Smuzhiyun * exactly do the right thing, let's simply use the
4007*4882a593Smuzhiyun * parent_data pointer. Yes, I'm naughty.
4008*4882a593Smuzhiyun */
4009*4882a593Smuzhiyun lpi_write_config(d->parent_data, LPI_PROP_ENABLED, 0);
4010*4882a593Smuzhiyun its_vpe_send_inv(d);
4011*4882a593Smuzhiyun }
4012*4882a593Smuzhiyun
its_vpe_unmask_irq(struct irq_data * d)4013*4882a593Smuzhiyun static void its_vpe_unmask_irq(struct irq_data *d)
4014*4882a593Smuzhiyun {
4015*4882a593Smuzhiyun /* Same hack as above... */
4016*4882a593Smuzhiyun lpi_write_config(d->parent_data, 0, LPI_PROP_ENABLED);
4017*4882a593Smuzhiyun its_vpe_send_inv(d);
4018*4882a593Smuzhiyun }
4019*4882a593Smuzhiyun
its_vpe_set_irqchip_state(struct irq_data * d,enum irqchip_irq_state which,bool state)4020*4882a593Smuzhiyun static int its_vpe_set_irqchip_state(struct irq_data *d,
4021*4882a593Smuzhiyun enum irqchip_irq_state which,
4022*4882a593Smuzhiyun bool state)
4023*4882a593Smuzhiyun {
4024*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4025*4882a593Smuzhiyun
4026*4882a593Smuzhiyun if (which != IRQCHIP_STATE_PENDING)
4027*4882a593Smuzhiyun return -EINVAL;
4028*4882a593Smuzhiyun
4029*4882a593Smuzhiyun if (gic_rdists->has_direct_lpi) {
4030*4882a593Smuzhiyun void __iomem *rdbase;
4031*4882a593Smuzhiyun
4032*4882a593Smuzhiyun rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
4033*4882a593Smuzhiyun if (state) {
4034*4882a593Smuzhiyun gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_SETLPIR);
4035*4882a593Smuzhiyun } else {
4036*4882a593Smuzhiyun gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_CLRLPIR);
4037*4882a593Smuzhiyun wait_for_syncr(rdbase);
4038*4882a593Smuzhiyun }
4039*4882a593Smuzhiyun } else {
4040*4882a593Smuzhiyun if (state)
4041*4882a593Smuzhiyun its_vpe_send_cmd(vpe, its_send_int);
4042*4882a593Smuzhiyun else
4043*4882a593Smuzhiyun its_vpe_send_cmd(vpe, its_send_clear);
4044*4882a593Smuzhiyun }
4045*4882a593Smuzhiyun
4046*4882a593Smuzhiyun return 0;
4047*4882a593Smuzhiyun }
4048*4882a593Smuzhiyun
its_vpe_retrigger(struct irq_data * d)4049*4882a593Smuzhiyun static int its_vpe_retrigger(struct irq_data *d)
4050*4882a593Smuzhiyun {
4051*4882a593Smuzhiyun return !its_vpe_set_irqchip_state(d, IRQCHIP_STATE_PENDING, true);
4052*4882a593Smuzhiyun }
4053*4882a593Smuzhiyun
4054*4882a593Smuzhiyun static struct irq_chip its_vpe_irq_chip = {
4055*4882a593Smuzhiyun .name = "GICv4-vpe",
4056*4882a593Smuzhiyun .irq_mask = its_vpe_mask_irq,
4057*4882a593Smuzhiyun .irq_unmask = its_vpe_unmask_irq,
4058*4882a593Smuzhiyun .irq_eoi = irq_chip_eoi_parent,
4059*4882a593Smuzhiyun .irq_set_affinity = its_vpe_set_affinity,
4060*4882a593Smuzhiyun .irq_retrigger = its_vpe_retrigger,
4061*4882a593Smuzhiyun .irq_set_irqchip_state = its_vpe_set_irqchip_state,
4062*4882a593Smuzhiyun .irq_set_vcpu_affinity = its_vpe_set_vcpu_affinity,
4063*4882a593Smuzhiyun };
4064*4882a593Smuzhiyun
find_4_1_its(void)4065*4882a593Smuzhiyun static struct its_node *find_4_1_its(void)
4066*4882a593Smuzhiyun {
4067*4882a593Smuzhiyun static struct its_node *its = NULL;
4068*4882a593Smuzhiyun
4069*4882a593Smuzhiyun if (!its) {
4070*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
4071*4882a593Smuzhiyun if (is_v4_1(its))
4072*4882a593Smuzhiyun return its;
4073*4882a593Smuzhiyun }
4074*4882a593Smuzhiyun
4075*4882a593Smuzhiyun /* Oops? */
4076*4882a593Smuzhiyun its = NULL;
4077*4882a593Smuzhiyun }
4078*4882a593Smuzhiyun
4079*4882a593Smuzhiyun return its;
4080*4882a593Smuzhiyun }
4081*4882a593Smuzhiyun
its_vpe_4_1_send_inv(struct irq_data * d)4082*4882a593Smuzhiyun static void its_vpe_4_1_send_inv(struct irq_data *d)
4083*4882a593Smuzhiyun {
4084*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4085*4882a593Smuzhiyun struct its_node *its;
4086*4882a593Smuzhiyun
4087*4882a593Smuzhiyun /*
4088*4882a593Smuzhiyun * GICv4.1 wants doorbells to be invalidated using the
4089*4882a593Smuzhiyun * INVDB command in order to be broadcast to all RDs. Send
4090*4882a593Smuzhiyun * it to the first valid ITS, and let the HW do its magic.
4091*4882a593Smuzhiyun */
4092*4882a593Smuzhiyun its = find_4_1_its();
4093*4882a593Smuzhiyun if (its)
4094*4882a593Smuzhiyun its_send_invdb(its, vpe);
4095*4882a593Smuzhiyun }
4096*4882a593Smuzhiyun
its_vpe_4_1_mask_irq(struct irq_data * d)4097*4882a593Smuzhiyun static void its_vpe_4_1_mask_irq(struct irq_data *d)
4098*4882a593Smuzhiyun {
4099*4882a593Smuzhiyun lpi_write_config(d->parent_data, LPI_PROP_ENABLED, 0);
4100*4882a593Smuzhiyun its_vpe_4_1_send_inv(d);
4101*4882a593Smuzhiyun }
4102*4882a593Smuzhiyun
its_vpe_4_1_unmask_irq(struct irq_data * d)4103*4882a593Smuzhiyun static void its_vpe_4_1_unmask_irq(struct irq_data *d)
4104*4882a593Smuzhiyun {
4105*4882a593Smuzhiyun lpi_write_config(d->parent_data, 0, LPI_PROP_ENABLED);
4106*4882a593Smuzhiyun its_vpe_4_1_send_inv(d);
4107*4882a593Smuzhiyun }
4108*4882a593Smuzhiyun
its_vpe_4_1_schedule(struct its_vpe * vpe,struct its_cmd_info * info)4109*4882a593Smuzhiyun static void its_vpe_4_1_schedule(struct its_vpe *vpe,
4110*4882a593Smuzhiyun struct its_cmd_info *info)
4111*4882a593Smuzhiyun {
4112*4882a593Smuzhiyun void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
4113*4882a593Smuzhiyun u64 val = 0;
4114*4882a593Smuzhiyun
4115*4882a593Smuzhiyun /* Schedule the VPE */
4116*4882a593Smuzhiyun val |= GICR_VPENDBASER_Valid;
4117*4882a593Smuzhiyun val |= info->g0en ? GICR_VPENDBASER_4_1_VGRP0EN : 0;
4118*4882a593Smuzhiyun val |= info->g1en ? GICR_VPENDBASER_4_1_VGRP1EN : 0;
4119*4882a593Smuzhiyun val |= FIELD_PREP(GICR_VPENDBASER_4_1_VPEID, vpe->vpe_id);
4120*4882a593Smuzhiyun
4121*4882a593Smuzhiyun gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
4122*4882a593Smuzhiyun }
4123*4882a593Smuzhiyun
its_vpe_4_1_deschedule(struct its_vpe * vpe,struct its_cmd_info * info)4124*4882a593Smuzhiyun static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
4125*4882a593Smuzhiyun struct its_cmd_info *info)
4126*4882a593Smuzhiyun {
4127*4882a593Smuzhiyun void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
4128*4882a593Smuzhiyun u64 val;
4129*4882a593Smuzhiyun
4130*4882a593Smuzhiyun if (info->req_db) {
4131*4882a593Smuzhiyun unsigned long flags;
4132*4882a593Smuzhiyun
4133*4882a593Smuzhiyun /*
4134*4882a593Smuzhiyun * vPE is going to block: make the vPE non-resident with
4135*4882a593Smuzhiyun * PendingLast clear and DB set. The GIC guarantees that if
4136*4882a593Smuzhiyun * we read-back PendingLast clear, then a doorbell will be
4137*4882a593Smuzhiyun * delivered when an interrupt comes.
4138*4882a593Smuzhiyun *
4139*4882a593Smuzhiyun * Note the locking to deal with the concurrent update of
4140*4882a593Smuzhiyun * pending_last from the doorbell interrupt handler that can
4141*4882a593Smuzhiyun * run concurrently.
4142*4882a593Smuzhiyun */
4143*4882a593Smuzhiyun raw_spin_lock_irqsave(&vpe->vpe_lock, flags);
4144*4882a593Smuzhiyun val = its_clear_vpend_valid(vlpi_base,
4145*4882a593Smuzhiyun GICR_VPENDBASER_PendingLast,
4146*4882a593Smuzhiyun GICR_VPENDBASER_4_1_DB);
4147*4882a593Smuzhiyun vpe->pending_last = !!(val & GICR_VPENDBASER_PendingLast);
4148*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&vpe->vpe_lock, flags);
4149*4882a593Smuzhiyun } else {
4150*4882a593Smuzhiyun /*
4151*4882a593Smuzhiyun * We're not blocking, so just make the vPE non-resident
4152*4882a593Smuzhiyun * with PendingLast set, indicating that we'll be back.
4153*4882a593Smuzhiyun */
4154*4882a593Smuzhiyun val = its_clear_vpend_valid(vlpi_base,
4155*4882a593Smuzhiyun 0,
4156*4882a593Smuzhiyun GICR_VPENDBASER_PendingLast);
4157*4882a593Smuzhiyun vpe->pending_last = true;
4158*4882a593Smuzhiyun }
4159*4882a593Smuzhiyun }
4160*4882a593Smuzhiyun
its_vpe_4_1_invall(struct its_vpe * vpe)4161*4882a593Smuzhiyun static void its_vpe_4_1_invall(struct its_vpe *vpe)
4162*4882a593Smuzhiyun {
4163*4882a593Smuzhiyun void __iomem *rdbase;
4164*4882a593Smuzhiyun unsigned long flags;
4165*4882a593Smuzhiyun u64 val;
4166*4882a593Smuzhiyun int cpu;
4167*4882a593Smuzhiyun
4168*4882a593Smuzhiyun val = GICR_INVALLR_V;
4169*4882a593Smuzhiyun val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);
4170*4882a593Smuzhiyun
4171*4882a593Smuzhiyun /* Target the redistributor this vPE is currently known on */
4172*4882a593Smuzhiyun cpu = vpe_to_cpuid_lock(vpe, &flags);
4173*4882a593Smuzhiyun raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
4174*4882a593Smuzhiyun rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
4175*4882a593Smuzhiyun gic_write_lpir(val, rdbase + GICR_INVALLR);
4176*4882a593Smuzhiyun
4177*4882a593Smuzhiyun wait_for_syncr(rdbase);
4178*4882a593Smuzhiyun raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
4179*4882a593Smuzhiyun vpe_to_cpuid_unlock(vpe, flags);
4180*4882a593Smuzhiyun }
4181*4882a593Smuzhiyun
its_vpe_4_1_set_vcpu_affinity(struct irq_data * d,void * vcpu_info)4182*4882a593Smuzhiyun static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
4183*4882a593Smuzhiyun {
4184*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4185*4882a593Smuzhiyun struct its_cmd_info *info = vcpu_info;
4186*4882a593Smuzhiyun
4187*4882a593Smuzhiyun switch (info->cmd_type) {
4188*4882a593Smuzhiyun case SCHEDULE_VPE:
4189*4882a593Smuzhiyun its_vpe_4_1_schedule(vpe, info);
4190*4882a593Smuzhiyun return 0;
4191*4882a593Smuzhiyun
4192*4882a593Smuzhiyun case DESCHEDULE_VPE:
4193*4882a593Smuzhiyun its_vpe_4_1_deschedule(vpe, info);
4194*4882a593Smuzhiyun return 0;
4195*4882a593Smuzhiyun
4196*4882a593Smuzhiyun case COMMIT_VPE:
4197*4882a593Smuzhiyun its_wait_vpt_parse_complete();
4198*4882a593Smuzhiyun return 0;
4199*4882a593Smuzhiyun
4200*4882a593Smuzhiyun case INVALL_VPE:
4201*4882a593Smuzhiyun its_vpe_4_1_invall(vpe);
4202*4882a593Smuzhiyun return 0;
4203*4882a593Smuzhiyun
4204*4882a593Smuzhiyun default:
4205*4882a593Smuzhiyun return -EINVAL;
4206*4882a593Smuzhiyun }
4207*4882a593Smuzhiyun }
4208*4882a593Smuzhiyun
4209*4882a593Smuzhiyun static struct irq_chip its_vpe_4_1_irq_chip = {
4210*4882a593Smuzhiyun .name = "GICv4.1-vpe",
4211*4882a593Smuzhiyun .irq_mask = its_vpe_4_1_mask_irq,
4212*4882a593Smuzhiyun .irq_unmask = its_vpe_4_1_unmask_irq,
4213*4882a593Smuzhiyun .irq_eoi = irq_chip_eoi_parent,
4214*4882a593Smuzhiyun .irq_set_affinity = its_vpe_set_affinity,
4215*4882a593Smuzhiyun .irq_set_vcpu_affinity = its_vpe_4_1_set_vcpu_affinity,
4216*4882a593Smuzhiyun };
4217*4882a593Smuzhiyun
its_configure_sgi(struct irq_data * d,bool clear)4218*4882a593Smuzhiyun static void its_configure_sgi(struct irq_data *d, bool clear)
4219*4882a593Smuzhiyun {
4220*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4221*4882a593Smuzhiyun struct its_cmd_desc desc;
4222*4882a593Smuzhiyun
4223*4882a593Smuzhiyun desc.its_vsgi_cmd.vpe = vpe;
4224*4882a593Smuzhiyun desc.its_vsgi_cmd.sgi = d->hwirq;
4225*4882a593Smuzhiyun desc.its_vsgi_cmd.priority = vpe->sgi_config[d->hwirq].priority;
4226*4882a593Smuzhiyun desc.its_vsgi_cmd.enable = vpe->sgi_config[d->hwirq].enabled;
4227*4882a593Smuzhiyun desc.its_vsgi_cmd.group = vpe->sgi_config[d->hwirq].group;
4228*4882a593Smuzhiyun desc.its_vsgi_cmd.clear = clear;
4229*4882a593Smuzhiyun
4230*4882a593Smuzhiyun /*
4231*4882a593Smuzhiyun * GICv4.1 allows us to send VSGI commands to any ITS as long as the
4232*4882a593Smuzhiyun * destination VPE is mapped there. Since we map them eagerly at
4233*4882a593Smuzhiyun * activation time, we're pretty sure the first GICv4.1 ITS will do.
4234*4882a593Smuzhiyun */
4235*4882a593Smuzhiyun its_send_single_vcommand(find_4_1_its(), its_build_vsgi_cmd, &desc);
4236*4882a593Smuzhiyun }
4237*4882a593Smuzhiyun
its_sgi_mask_irq(struct irq_data * d)4238*4882a593Smuzhiyun static void its_sgi_mask_irq(struct irq_data *d)
4239*4882a593Smuzhiyun {
4240*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4241*4882a593Smuzhiyun
4242*4882a593Smuzhiyun vpe->sgi_config[d->hwirq].enabled = false;
4243*4882a593Smuzhiyun its_configure_sgi(d, false);
4244*4882a593Smuzhiyun }
4245*4882a593Smuzhiyun
its_sgi_unmask_irq(struct irq_data * d)4246*4882a593Smuzhiyun static void its_sgi_unmask_irq(struct irq_data *d)
4247*4882a593Smuzhiyun {
4248*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4249*4882a593Smuzhiyun
4250*4882a593Smuzhiyun vpe->sgi_config[d->hwirq].enabled = true;
4251*4882a593Smuzhiyun its_configure_sgi(d, false);
4252*4882a593Smuzhiyun }
4253*4882a593Smuzhiyun
its_sgi_set_affinity(struct irq_data * d,const struct cpumask * mask_val,bool force)4254*4882a593Smuzhiyun static int its_sgi_set_affinity(struct irq_data *d,
4255*4882a593Smuzhiyun const struct cpumask *mask_val,
4256*4882a593Smuzhiyun bool force)
4257*4882a593Smuzhiyun {
4258*4882a593Smuzhiyun /*
4259*4882a593Smuzhiyun * There is no notion of affinity for virtual SGIs, at least
4260*4882a593Smuzhiyun * not on the host (since they can only be targetting a vPE).
4261*4882a593Smuzhiyun * Tell the kernel we've done whatever it asked for.
4262*4882a593Smuzhiyun */
4263*4882a593Smuzhiyun irq_data_update_effective_affinity(d, mask_val);
4264*4882a593Smuzhiyun return IRQ_SET_MASK_OK;
4265*4882a593Smuzhiyun }
4266*4882a593Smuzhiyun
its_sgi_set_irqchip_state(struct irq_data * d,enum irqchip_irq_state which,bool state)4267*4882a593Smuzhiyun static int its_sgi_set_irqchip_state(struct irq_data *d,
4268*4882a593Smuzhiyun enum irqchip_irq_state which,
4269*4882a593Smuzhiyun bool state)
4270*4882a593Smuzhiyun {
4271*4882a593Smuzhiyun if (which != IRQCHIP_STATE_PENDING)
4272*4882a593Smuzhiyun return -EINVAL;
4273*4882a593Smuzhiyun
4274*4882a593Smuzhiyun if (state) {
4275*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4276*4882a593Smuzhiyun struct its_node *its = find_4_1_its();
4277*4882a593Smuzhiyun u64 val;
4278*4882a593Smuzhiyun
4279*4882a593Smuzhiyun val = FIELD_PREP(GITS_SGIR_VPEID, vpe->vpe_id);
4280*4882a593Smuzhiyun val |= FIELD_PREP(GITS_SGIR_VINTID, d->hwirq);
4281*4882a593Smuzhiyun writeq_relaxed(val, its->sgir_base + GITS_SGIR - SZ_128K);
4282*4882a593Smuzhiyun } else {
4283*4882a593Smuzhiyun its_configure_sgi(d, true);
4284*4882a593Smuzhiyun }
4285*4882a593Smuzhiyun
4286*4882a593Smuzhiyun return 0;
4287*4882a593Smuzhiyun }
4288*4882a593Smuzhiyun
its_sgi_get_irqchip_state(struct irq_data * d,enum irqchip_irq_state which,bool * val)4289*4882a593Smuzhiyun static int its_sgi_get_irqchip_state(struct irq_data *d,
4290*4882a593Smuzhiyun enum irqchip_irq_state which, bool *val)
4291*4882a593Smuzhiyun {
4292*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4293*4882a593Smuzhiyun void __iomem *base;
4294*4882a593Smuzhiyun unsigned long flags;
4295*4882a593Smuzhiyun u32 count = 1000000; /* 1s! */
4296*4882a593Smuzhiyun u32 status;
4297*4882a593Smuzhiyun int cpu;
4298*4882a593Smuzhiyun
4299*4882a593Smuzhiyun if (which != IRQCHIP_STATE_PENDING)
4300*4882a593Smuzhiyun return -EINVAL;
4301*4882a593Smuzhiyun
4302*4882a593Smuzhiyun /*
4303*4882a593Smuzhiyun * Locking galore! We can race against two different events:
4304*4882a593Smuzhiyun *
4305*4882a593Smuzhiyun * - Concurent vPE affinity change: we must make sure it cannot
4306*4882a593Smuzhiyun * happen, or we'll talk to the wrong redistributor. This is
4307*4882a593Smuzhiyun * identical to what happens with vLPIs.
4308*4882a593Smuzhiyun *
4309*4882a593Smuzhiyun * - Concurrent VSGIPENDR access: As it involves accessing two
4310*4882a593Smuzhiyun * MMIO registers, this must be made atomic one way or another.
4311*4882a593Smuzhiyun */
4312*4882a593Smuzhiyun cpu = vpe_to_cpuid_lock(vpe, &flags);
4313*4882a593Smuzhiyun raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
4314*4882a593Smuzhiyun base = gic_data_rdist_cpu(cpu)->rd_base + SZ_128K;
4315*4882a593Smuzhiyun writel_relaxed(vpe->vpe_id, base + GICR_VSGIR);
4316*4882a593Smuzhiyun do {
4317*4882a593Smuzhiyun status = readl_relaxed(base + GICR_VSGIPENDR);
4318*4882a593Smuzhiyun if (!(status & GICR_VSGIPENDR_BUSY))
4319*4882a593Smuzhiyun goto out;
4320*4882a593Smuzhiyun
4321*4882a593Smuzhiyun count--;
4322*4882a593Smuzhiyun if (!count) {
4323*4882a593Smuzhiyun pr_err_ratelimited("Unable to get SGI status\n");
4324*4882a593Smuzhiyun goto out;
4325*4882a593Smuzhiyun }
4326*4882a593Smuzhiyun cpu_relax();
4327*4882a593Smuzhiyun udelay(1);
4328*4882a593Smuzhiyun } while (count);
4329*4882a593Smuzhiyun
4330*4882a593Smuzhiyun out:
4331*4882a593Smuzhiyun raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
4332*4882a593Smuzhiyun vpe_to_cpuid_unlock(vpe, flags);
4333*4882a593Smuzhiyun
4334*4882a593Smuzhiyun if (!count)
4335*4882a593Smuzhiyun return -ENXIO;
4336*4882a593Smuzhiyun
4337*4882a593Smuzhiyun *val = !!(status & (1 << d->hwirq));
4338*4882a593Smuzhiyun
4339*4882a593Smuzhiyun return 0;
4340*4882a593Smuzhiyun }
4341*4882a593Smuzhiyun
its_sgi_set_vcpu_affinity(struct irq_data * d,void * vcpu_info)4342*4882a593Smuzhiyun static int its_sgi_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
4343*4882a593Smuzhiyun {
4344*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4345*4882a593Smuzhiyun struct its_cmd_info *info = vcpu_info;
4346*4882a593Smuzhiyun
4347*4882a593Smuzhiyun switch (info->cmd_type) {
4348*4882a593Smuzhiyun case PROP_UPDATE_VSGI:
4349*4882a593Smuzhiyun vpe->sgi_config[d->hwirq].priority = info->priority;
4350*4882a593Smuzhiyun vpe->sgi_config[d->hwirq].group = info->group;
4351*4882a593Smuzhiyun its_configure_sgi(d, false);
4352*4882a593Smuzhiyun return 0;
4353*4882a593Smuzhiyun
4354*4882a593Smuzhiyun default:
4355*4882a593Smuzhiyun return -EINVAL;
4356*4882a593Smuzhiyun }
4357*4882a593Smuzhiyun }
4358*4882a593Smuzhiyun
4359*4882a593Smuzhiyun static struct irq_chip its_sgi_irq_chip = {
4360*4882a593Smuzhiyun .name = "GICv4.1-sgi",
4361*4882a593Smuzhiyun .irq_mask = its_sgi_mask_irq,
4362*4882a593Smuzhiyun .irq_unmask = its_sgi_unmask_irq,
4363*4882a593Smuzhiyun .irq_set_affinity = its_sgi_set_affinity,
4364*4882a593Smuzhiyun .irq_set_irqchip_state = its_sgi_set_irqchip_state,
4365*4882a593Smuzhiyun .irq_get_irqchip_state = its_sgi_get_irqchip_state,
4366*4882a593Smuzhiyun .irq_set_vcpu_affinity = its_sgi_set_vcpu_affinity,
4367*4882a593Smuzhiyun };
4368*4882a593Smuzhiyun
its_sgi_irq_domain_alloc(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs,void * args)4369*4882a593Smuzhiyun static int its_sgi_irq_domain_alloc(struct irq_domain *domain,
4370*4882a593Smuzhiyun unsigned int virq, unsigned int nr_irqs,
4371*4882a593Smuzhiyun void *args)
4372*4882a593Smuzhiyun {
4373*4882a593Smuzhiyun struct its_vpe *vpe = args;
4374*4882a593Smuzhiyun int i;
4375*4882a593Smuzhiyun
4376*4882a593Smuzhiyun /* Yes, we do want 16 SGIs */
4377*4882a593Smuzhiyun WARN_ON(nr_irqs != 16);
4378*4882a593Smuzhiyun
4379*4882a593Smuzhiyun for (i = 0; i < 16; i++) {
4380*4882a593Smuzhiyun vpe->sgi_config[i].priority = 0;
4381*4882a593Smuzhiyun vpe->sgi_config[i].enabled = false;
4382*4882a593Smuzhiyun vpe->sgi_config[i].group = false;
4383*4882a593Smuzhiyun
4384*4882a593Smuzhiyun irq_domain_set_hwirq_and_chip(domain, virq + i, i,
4385*4882a593Smuzhiyun &its_sgi_irq_chip, vpe);
4386*4882a593Smuzhiyun irq_set_status_flags(virq + i, IRQ_DISABLE_UNLAZY);
4387*4882a593Smuzhiyun }
4388*4882a593Smuzhiyun
4389*4882a593Smuzhiyun return 0;
4390*4882a593Smuzhiyun }
4391*4882a593Smuzhiyun
its_sgi_irq_domain_free(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs)4392*4882a593Smuzhiyun static void its_sgi_irq_domain_free(struct irq_domain *domain,
4393*4882a593Smuzhiyun unsigned int virq,
4394*4882a593Smuzhiyun unsigned int nr_irqs)
4395*4882a593Smuzhiyun {
4396*4882a593Smuzhiyun /* Nothing to do */
4397*4882a593Smuzhiyun }
4398*4882a593Smuzhiyun
its_sgi_irq_domain_activate(struct irq_domain * domain,struct irq_data * d,bool reserve)4399*4882a593Smuzhiyun static int its_sgi_irq_domain_activate(struct irq_domain *domain,
4400*4882a593Smuzhiyun struct irq_data *d, bool reserve)
4401*4882a593Smuzhiyun {
4402*4882a593Smuzhiyun /* Write out the initial SGI configuration */
4403*4882a593Smuzhiyun its_configure_sgi(d, false);
4404*4882a593Smuzhiyun return 0;
4405*4882a593Smuzhiyun }
4406*4882a593Smuzhiyun
its_sgi_irq_domain_deactivate(struct irq_domain * domain,struct irq_data * d)4407*4882a593Smuzhiyun static void its_sgi_irq_domain_deactivate(struct irq_domain *domain,
4408*4882a593Smuzhiyun struct irq_data *d)
4409*4882a593Smuzhiyun {
4410*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4411*4882a593Smuzhiyun
4412*4882a593Smuzhiyun /*
4413*4882a593Smuzhiyun * The VSGI command is awkward:
4414*4882a593Smuzhiyun *
4415*4882a593Smuzhiyun * - To change the configuration, CLEAR must be set to false,
4416*4882a593Smuzhiyun * leaving the pending bit unchanged.
4417*4882a593Smuzhiyun * - To clear the pending bit, CLEAR must be set to true, leaving
4418*4882a593Smuzhiyun * the configuration unchanged.
4419*4882a593Smuzhiyun *
4420*4882a593Smuzhiyun * You just can't do both at once, hence the two commands below.
4421*4882a593Smuzhiyun */
4422*4882a593Smuzhiyun vpe->sgi_config[d->hwirq].enabled = false;
4423*4882a593Smuzhiyun its_configure_sgi(d, false);
4424*4882a593Smuzhiyun its_configure_sgi(d, true);
4425*4882a593Smuzhiyun }
4426*4882a593Smuzhiyun
4427*4882a593Smuzhiyun static const struct irq_domain_ops its_sgi_domain_ops = {
4428*4882a593Smuzhiyun .alloc = its_sgi_irq_domain_alloc,
4429*4882a593Smuzhiyun .free = its_sgi_irq_domain_free,
4430*4882a593Smuzhiyun .activate = its_sgi_irq_domain_activate,
4431*4882a593Smuzhiyun .deactivate = its_sgi_irq_domain_deactivate,
4432*4882a593Smuzhiyun };
4433*4882a593Smuzhiyun
its_vpe_id_alloc(void)4434*4882a593Smuzhiyun static int its_vpe_id_alloc(void)
4435*4882a593Smuzhiyun {
4436*4882a593Smuzhiyun return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL);
4437*4882a593Smuzhiyun }
4438*4882a593Smuzhiyun
its_vpe_id_free(u16 id)4439*4882a593Smuzhiyun static void its_vpe_id_free(u16 id)
4440*4882a593Smuzhiyun {
4441*4882a593Smuzhiyun ida_simple_remove(&its_vpeid_ida, id);
4442*4882a593Smuzhiyun }
4443*4882a593Smuzhiyun
its_vpe_init(struct its_vpe * vpe)4444*4882a593Smuzhiyun static int its_vpe_init(struct its_vpe *vpe)
4445*4882a593Smuzhiyun {
4446*4882a593Smuzhiyun struct page *vpt_page;
4447*4882a593Smuzhiyun int vpe_id;
4448*4882a593Smuzhiyun
4449*4882a593Smuzhiyun /* Allocate vpe_id */
4450*4882a593Smuzhiyun vpe_id = its_vpe_id_alloc();
4451*4882a593Smuzhiyun if (vpe_id < 0)
4452*4882a593Smuzhiyun return vpe_id;
4453*4882a593Smuzhiyun
4454*4882a593Smuzhiyun /* Allocate VPT */
4455*4882a593Smuzhiyun vpt_page = its_allocate_pending_table(GFP_KERNEL);
4456*4882a593Smuzhiyun if (!vpt_page) {
4457*4882a593Smuzhiyun its_vpe_id_free(vpe_id);
4458*4882a593Smuzhiyun return -ENOMEM;
4459*4882a593Smuzhiyun }
4460*4882a593Smuzhiyun
4461*4882a593Smuzhiyun if (!its_alloc_vpe_table(vpe_id)) {
4462*4882a593Smuzhiyun its_vpe_id_free(vpe_id);
4463*4882a593Smuzhiyun its_free_pending_table(vpt_page);
4464*4882a593Smuzhiyun return -ENOMEM;
4465*4882a593Smuzhiyun }
4466*4882a593Smuzhiyun
4467*4882a593Smuzhiyun raw_spin_lock_init(&vpe->vpe_lock);
4468*4882a593Smuzhiyun vpe->vpe_id = vpe_id;
4469*4882a593Smuzhiyun vpe->vpt_page = vpt_page;
4470*4882a593Smuzhiyun if (gic_rdists->has_rvpeid)
4471*4882a593Smuzhiyun atomic_set(&vpe->vmapp_count, 0);
4472*4882a593Smuzhiyun else
4473*4882a593Smuzhiyun vpe->vpe_proxy_event = -1;
4474*4882a593Smuzhiyun
4475*4882a593Smuzhiyun return 0;
4476*4882a593Smuzhiyun }
4477*4882a593Smuzhiyun
its_vpe_teardown(struct its_vpe * vpe)4478*4882a593Smuzhiyun static void its_vpe_teardown(struct its_vpe *vpe)
4479*4882a593Smuzhiyun {
4480*4882a593Smuzhiyun its_vpe_db_proxy_unmap(vpe);
4481*4882a593Smuzhiyun its_vpe_id_free(vpe->vpe_id);
4482*4882a593Smuzhiyun its_free_pending_table(vpe->vpt_page);
4483*4882a593Smuzhiyun }
4484*4882a593Smuzhiyun
its_vpe_irq_domain_free(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs)4485*4882a593Smuzhiyun static void its_vpe_irq_domain_free(struct irq_domain *domain,
4486*4882a593Smuzhiyun unsigned int virq,
4487*4882a593Smuzhiyun unsigned int nr_irqs)
4488*4882a593Smuzhiyun {
4489*4882a593Smuzhiyun struct its_vm *vm = domain->host_data;
4490*4882a593Smuzhiyun int i;
4491*4882a593Smuzhiyun
4492*4882a593Smuzhiyun irq_domain_free_irqs_parent(domain, virq, nr_irqs);
4493*4882a593Smuzhiyun
4494*4882a593Smuzhiyun for (i = 0; i < nr_irqs; i++) {
4495*4882a593Smuzhiyun struct irq_data *data = irq_domain_get_irq_data(domain,
4496*4882a593Smuzhiyun virq + i);
4497*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(data);
4498*4882a593Smuzhiyun
4499*4882a593Smuzhiyun BUG_ON(vm != vpe->its_vm);
4500*4882a593Smuzhiyun
4501*4882a593Smuzhiyun clear_bit(data->hwirq, vm->db_bitmap);
4502*4882a593Smuzhiyun its_vpe_teardown(vpe);
4503*4882a593Smuzhiyun irq_domain_reset_irq_data(data);
4504*4882a593Smuzhiyun }
4505*4882a593Smuzhiyun
4506*4882a593Smuzhiyun if (bitmap_empty(vm->db_bitmap, vm->nr_db_lpis)) {
4507*4882a593Smuzhiyun its_lpi_free(vm->db_bitmap, vm->db_lpi_base, vm->nr_db_lpis);
4508*4882a593Smuzhiyun its_free_prop_table(vm->vprop_page);
4509*4882a593Smuzhiyun }
4510*4882a593Smuzhiyun }
4511*4882a593Smuzhiyun
its_vpe_irq_domain_alloc(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs,void * args)4512*4882a593Smuzhiyun static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
4513*4882a593Smuzhiyun unsigned int nr_irqs, void *args)
4514*4882a593Smuzhiyun {
4515*4882a593Smuzhiyun struct irq_chip *irqchip = &its_vpe_irq_chip;
4516*4882a593Smuzhiyun struct its_vm *vm = args;
4517*4882a593Smuzhiyun unsigned long *bitmap;
4518*4882a593Smuzhiyun struct page *vprop_page;
4519*4882a593Smuzhiyun int base, nr_ids, i, err = 0;
4520*4882a593Smuzhiyun
4521*4882a593Smuzhiyun BUG_ON(!vm);
4522*4882a593Smuzhiyun
4523*4882a593Smuzhiyun bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids);
4524*4882a593Smuzhiyun if (!bitmap)
4525*4882a593Smuzhiyun return -ENOMEM;
4526*4882a593Smuzhiyun
4527*4882a593Smuzhiyun if (nr_ids < nr_irqs) {
4528*4882a593Smuzhiyun its_lpi_free(bitmap, base, nr_ids);
4529*4882a593Smuzhiyun return -ENOMEM;
4530*4882a593Smuzhiyun }
4531*4882a593Smuzhiyun
4532*4882a593Smuzhiyun vprop_page = its_allocate_prop_table(GFP_KERNEL);
4533*4882a593Smuzhiyun if (!vprop_page) {
4534*4882a593Smuzhiyun its_lpi_free(bitmap, base, nr_ids);
4535*4882a593Smuzhiyun return -ENOMEM;
4536*4882a593Smuzhiyun }
4537*4882a593Smuzhiyun
4538*4882a593Smuzhiyun vm->db_bitmap = bitmap;
4539*4882a593Smuzhiyun vm->db_lpi_base = base;
4540*4882a593Smuzhiyun vm->nr_db_lpis = nr_ids;
4541*4882a593Smuzhiyun vm->vprop_page = vprop_page;
4542*4882a593Smuzhiyun
4543*4882a593Smuzhiyun if (gic_rdists->has_rvpeid)
4544*4882a593Smuzhiyun irqchip = &its_vpe_4_1_irq_chip;
4545*4882a593Smuzhiyun
4546*4882a593Smuzhiyun for (i = 0; i < nr_irqs; i++) {
4547*4882a593Smuzhiyun vm->vpes[i]->vpe_db_lpi = base + i;
4548*4882a593Smuzhiyun err = its_vpe_init(vm->vpes[i]);
4549*4882a593Smuzhiyun if (err)
4550*4882a593Smuzhiyun break;
4551*4882a593Smuzhiyun err = its_irq_gic_domain_alloc(domain, virq + i,
4552*4882a593Smuzhiyun vm->vpes[i]->vpe_db_lpi);
4553*4882a593Smuzhiyun if (err)
4554*4882a593Smuzhiyun break;
4555*4882a593Smuzhiyun irq_domain_set_hwirq_and_chip(domain, virq + i, i,
4556*4882a593Smuzhiyun irqchip, vm->vpes[i]);
4557*4882a593Smuzhiyun set_bit(i, bitmap);
4558*4882a593Smuzhiyun }
4559*4882a593Smuzhiyun
4560*4882a593Smuzhiyun if (err) {
4561*4882a593Smuzhiyun if (i > 0)
4562*4882a593Smuzhiyun its_vpe_irq_domain_free(domain, virq, i);
4563*4882a593Smuzhiyun
4564*4882a593Smuzhiyun its_lpi_free(bitmap, base, nr_ids);
4565*4882a593Smuzhiyun its_free_prop_table(vprop_page);
4566*4882a593Smuzhiyun }
4567*4882a593Smuzhiyun
4568*4882a593Smuzhiyun return err;
4569*4882a593Smuzhiyun }
4570*4882a593Smuzhiyun
its_vpe_irq_domain_activate(struct irq_domain * domain,struct irq_data * d,bool reserve)4571*4882a593Smuzhiyun static int its_vpe_irq_domain_activate(struct irq_domain *domain,
4572*4882a593Smuzhiyun struct irq_data *d, bool reserve)
4573*4882a593Smuzhiyun {
4574*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4575*4882a593Smuzhiyun struct its_node *its;
4576*4882a593Smuzhiyun
4577*4882a593Smuzhiyun /*
4578*4882a593Smuzhiyun * If we use the list map, we issue VMAPP on demand... Unless
4579*4882a593Smuzhiyun * we're on a GICv4.1 and we eagerly map the VPE on all ITSs
4580*4882a593Smuzhiyun * so that VSGIs can work.
4581*4882a593Smuzhiyun */
4582*4882a593Smuzhiyun if (!gic_requires_eager_mapping())
4583*4882a593Smuzhiyun return 0;
4584*4882a593Smuzhiyun
4585*4882a593Smuzhiyun /* Map the VPE to the first possible CPU */
4586*4882a593Smuzhiyun vpe->col_idx = cpumask_first(cpu_online_mask);
4587*4882a593Smuzhiyun
4588*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
4589*4882a593Smuzhiyun if (!is_v4(its))
4590*4882a593Smuzhiyun continue;
4591*4882a593Smuzhiyun
4592*4882a593Smuzhiyun its_send_vmapp(its, vpe, true);
4593*4882a593Smuzhiyun its_send_vinvall(its, vpe);
4594*4882a593Smuzhiyun }
4595*4882a593Smuzhiyun
4596*4882a593Smuzhiyun irq_data_update_effective_affinity(d, cpumask_of(vpe->col_idx));
4597*4882a593Smuzhiyun
4598*4882a593Smuzhiyun return 0;
4599*4882a593Smuzhiyun }
4600*4882a593Smuzhiyun
its_vpe_irq_domain_deactivate(struct irq_domain * domain,struct irq_data * d)4601*4882a593Smuzhiyun static void its_vpe_irq_domain_deactivate(struct irq_domain *domain,
4602*4882a593Smuzhiyun struct irq_data *d)
4603*4882a593Smuzhiyun {
4604*4882a593Smuzhiyun struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
4605*4882a593Smuzhiyun struct its_node *its;
4606*4882a593Smuzhiyun
4607*4882a593Smuzhiyun /*
4608*4882a593Smuzhiyun * If we use the list map on GICv4.0, we unmap the VPE once no
4609*4882a593Smuzhiyun * VLPIs are associated with the VM.
4610*4882a593Smuzhiyun */
4611*4882a593Smuzhiyun if (!gic_requires_eager_mapping())
4612*4882a593Smuzhiyun return;
4613*4882a593Smuzhiyun
4614*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
4615*4882a593Smuzhiyun if (!is_v4(its))
4616*4882a593Smuzhiyun continue;
4617*4882a593Smuzhiyun
4618*4882a593Smuzhiyun its_send_vmapp(its, vpe, false);
4619*4882a593Smuzhiyun }
4620*4882a593Smuzhiyun }
4621*4882a593Smuzhiyun
4622*4882a593Smuzhiyun static const struct irq_domain_ops its_vpe_domain_ops = {
4623*4882a593Smuzhiyun .alloc = its_vpe_irq_domain_alloc,
4624*4882a593Smuzhiyun .free = its_vpe_irq_domain_free,
4625*4882a593Smuzhiyun .activate = its_vpe_irq_domain_activate,
4626*4882a593Smuzhiyun .deactivate = its_vpe_irq_domain_deactivate,
4627*4882a593Smuzhiyun };
4628*4882a593Smuzhiyun
its_force_quiescent(void __iomem * base)4629*4882a593Smuzhiyun static int its_force_quiescent(void __iomem *base)
4630*4882a593Smuzhiyun {
4631*4882a593Smuzhiyun u32 count = 1000000; /* 1s */
4632*4882a593Smuzhiyun u32 val;
4633*4882a593Smuzhiyun
4634*4882a593Smuzhiyun val = readl_relaxed(base + GITS_CTLR);
4635*4882a593Smuzhiyun /*
4636*4882a593Smuzhiyun * GIC architecture specification requires the ITS to be both
4637*4882a593Smuzhiyun * disabled and quiescent for writes to GITS_BASER<n> or
4638*4882a593Smuzhiyun * GITS_CBASER to not have UNPREDICTABLE results.
4639*4882a593Smuzhiyun */
4640*4882a593Smuzhiyun if ((val & GITS_CTLR_QUIESCENT) && !(val & GITS_CTLR_ENABLE))
4641*4882a593Smuzhiyun return 0;
4642*4882a593Smuzhiyun
4643*4882a593Smuzhiyun /* Disable the generation of all interrupts to this ITS */
4644*4882a593Smuzhiyun val &= ~(GITS_CTLR_ENABLE | GITS_CTLR_ImDe);
4645*4882a593Smuzhiyun writel_relaxed(val, base + GITS_CTLR);
4646*4882a593Smuzhiyun
4647*4882a593Smuzhiyun /* Poll GITS_CTLR and wait until ITS becomes quiescent */
4648*4882a593Smuzhiyun while (1) {
4649*4882a593Smuzhiyun val = readl_relaxed(base + GITS_CTLR);
4650*4882a593Smuzhiyun if (val & GITS_CTLR_QUIESCENT)
4651*4882a593Smuzhiyun return 0;
4652*4882a593Smuzhiyun
4653*4882a593Smuzhiyun count--;
4654*4882a593Smuzhiyun if (!count)
4655*4882a593Smuzhiyun return -EBUSY;
4656*4882a593Smuzhiyun
4657*4882a593Smuzhiyun cpu_relax();
4658*4882a593Smuzhiyun udelay(1);
4659*4882a593Smuzhiyun }
4660*4882a593Smuzhiyun }
4661*4882a593Smuzhiyun
its_enable_quirk_cavium_22375(void * data)4662*4882a593Smuzhiyun static bool __maybe_unused its_enable_quirk_cavium_22375(void *data)
4663*4882a593Smuzhiyun {
4664*4882a593Smuzhiyun struct its_node *its = data;
4665*4882a593Smuzhiyun
4666*4882a593Smuzhiyun /* erratum 22375: only alloc 8MB table size (20 bits) */
4667*4882a593Smuzhiyun its->typer &= ~GITS_TYPER_DEVBITS;
4668*4882a593Smuzhiyun its->typer |= FIELD_PREP(GITS_TYPER_DEVBITS, 20 - 1);
4669*4882a593Smuzhiyun its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375;
4670*4882a593Smuzhiyun
4671*4882a593Smuzhiyun return true;
4672*4882a593Smuzhiyun }
4673*4882a593Smuzhiyun
its_enable_quirk_cavium_23144(void * data)4674*4882a593Smuzhiyun static bool __maybe_unused its_enable_quirk_cavium_23144(void *data)
4675*4882a593Smuzhiyun {
4676*4882a593Smuzhiyun struct its_node *its = data;
4677*4882a593Smuzhiyun
4678*4882a593Smuzhiyun its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_23144;
4679*4882a593Smuzhiyun
4680*4882a593Smuzhiyun return true;
4681*4882a593Smuzhiyun }
4682*4882a593Smuzhiyun
its_enable_quirk_qdf2400_e0065(void * data)4683*4882a593Smuzhiyun static bool __maybe_unused its_enable_quirk_qdf2400_e0065(void *data)
4684*4882a593Smuzhiyun {
4685*4882a593Smuzhiyun struct its_node *its = data;
4686*4882a593Smuzhiyun
4687*4882a593Smuzhiyun /* On QDF2400, the size of the ITE is 16Bytes */
4688*4882a593Smuzhiyun its->typer &= ~GITS_TYPER_ITT_ENTRY_SIZE;
4689*4882a593Smuzhiyun its->typer |= FIELD_PREP(GITS_TYPER_ITT_ENTRY_SIZE, 16 - 1);
4690*4882a593Smuzhiyun
4691*4882a593Smuzhiyun return true;
4692*4882a593Smuzhiyun }
4693*4882a593Smuzhiyun
its_irq_get_msi_base_pre_its(struct its_device * its_dev)4694*4882a593Smuzhiyun static u64 its_irq_get_msi_base_pre_its(struct its_device *its_dev)
4695*4882a593Smuzhiyun {
4696*4882a593Smuzhiyun struct its_node *its = its_dev->its;
4697*4882a593Smuzhiyun
4698*4882a593Smuzhiyun /*
4699*4882a593Smuzhiyun * The Socionext Synquacer SoC has a so-called 'pre-ITS',
4700*4882a593Smuzhiyun * which maps 32-bit writes targeted at a separate window of
4701*4882a593Smuzhiyun * size '4 << device_id_bits' onto writes to GITS_TRANSLATER
4702*4882a593Smuzhiyun * with device ID taken from bits [device_id_bits + 1:2] of
4703*4882a593Smuzhiyun * the window offset.
4704*4882a593Smuzhiyun */
4705*4882a593Smuzhiyun return its->pre_its_base + (its_dev->device_id << 2);
4706*4882a593Smuzhiyun }
4707*4882a593Smuzhiyun
its_enable_quirk_socionext_synquacer(void * data)4708*4882a593Smuzhiyun static bool __maybe_unused its_enable_quirk_socionext_synquacer(void *data)
4709*4882a593Smuzhiyun {
4710*4882a593Smuzhiyun struct its_node *its = data;
4711*4882a593Smuzhiyun u32 pre_its_window[2];
4712*4882a593Smuzhiyun u32 ids;
4713*4882a593Smuzhiyun
4714*4882a593Smuzhiyun if (!fwnode_property_read_u32_array(its->fwnode_handle,
4715*4882a593Smuzhiyun "socionext,synquacer-pre-its",
4716*4882a593Smuzhiyun pre_its_window,
4717*4882a593Smuzhiyun ARRAY_SIZE(pre_its_window))) {
4718*4882a593Smuzhiyun
4719*4882a593Smuzhiyun its->pre_its_base = pre_its_window[0];
4720*4882a593Smuzhiyun its->get_msi_base = its_irq_get_msi_base_pre_its;
4721*4882a593Smuzhiyun
4722*4882a593Smuzhiyun ids = ilog2(pre_its_window[1]) - 2;
4723*4882a593Smuzhiyun if (device_ids(its) > ids) {
4724*4882a593Smuzhiyun its->typer &= ~GITS_TYPER_DEVBITS;
4725*4882a593Smuzhiyun its->typer |= FIELD_PREP(GITS_TYPER_DEVBITS, ids - 1);
4726*4882a593Smuzhiyun }
4727*4882a593Smuzhiyun
4728*4882a593Smuzhiyun /* the pre-ITS breaks isolation, so disable MSI remapping */
4729*4882a593Smuzhiyun its->msi_domain_flags &= ~IRQ_DOMAIN_FLAG_MSI_REMAP;
4730*4882a593Smuzhiyun return true;
4731*4882a593Smuzhiyun }
4732*4882a593Smuzhiyun return false;
4733*4882a593Smuzhiyun }
4734*4882a593Smuzhiyun
its_enable_quirk_hip07_161600802(void * data)4735*4882a593Smuzhiyun static bool __maybe_unused its_enable_quirk_hip07_161600802(void *data)
4736*4882a593Smuzhiyun {
4737*4882a593Smuzhiyun struct its_node *its = data;
4738*4882a593Smuzhiyun
4739*4882a593Smuzhiyun /*
4740*4882a593Smuzhiyun * Hip07 insists on using the wrong address for the VLPI
4741*4882a593Smuzhiyun * page. Trick it into doing the right thing...
4742*4882a593Smuzhiyun */
4743*4882a593Smuzhiyun its->vlpi_redist_offset = SZ_128K;
4744*4882a593Smuzhiyun return true;
4745*4882a593Smuzhiyun }
4746*4882a593Smuzhiyun
4747*4882a593Smuzhiyun static const struct gic_quirk its_quirks[] = {
4748*4882a593Smuzhiyun #ifdef CONFIG_CAVIUM_ERRATUM_22375
4749*4882a593Smuzhiyun {
4750*4882a593Smuzhiyun .desc = "ITS: Cavium errata 22375, 24313",
4751*4882a593Smuzhiyun .iidr = 0xa100034c, /* ThunderX pass 1.x */
4752*4882a593Smuzhiyun .mask = 0xffff0fff,
4753*4882a593Smuzhiyun .init = its_enable_quirk_cavium_22375,
4754*4882a593Smuzhiyun },
4755*4882a593Smuzhiyun #endif
4756*4882a593Smuzhiyun #ifdef CONFIG_CAVIUM_ERRATUM_23144
4757*4882a593Smuzhiyun {
4758*4882a593Smuzhiyun .desc = "ITS: Cavium erratum 23144",
4759*4882a593Smuzhiyun .iidr = 0xa100034c, /* ThunderX pass 1.x */
4760*4882a593Smuzhiyun .mask = 0xffff0fff,
4761*4882a593Smuzhiyun .init = its_enable_quirk_cavium_23144,
4762*4882a593Smuzhiyun },
4763*4882a593Smuzhiyun #endif
4764*4882a593Smuzhiyun #ifdef CONFIG_QCOM_QDF2400_ERRATUM_0065
4765*4882a593Smuzhiyun {
4766*4882a593Smuzhiyun .desc = "ITS: QDF2400 erratum 0065",
4767*4882a593Smuzhiyun .iidr = 0x00001070, /* QDF2400 ITS rev 1.x */
4768*4882a593Smuzhiyun .mask = 0xffffffff,
4769*4882a593Smuzhiyun .init = its_enable_quirk_qdf2400_e0065,
4770*4882a593Smuzhiyun },
4771*4882a593Smuzhiyun #endif
4772*4882a593Smuzhiyun #ifdef CONFIG_SOCIONEXT_SYNQUACER_PREITS
4773*4882a593Smuzhiyun {
4774*4882a593Smuzhiyun /*
4775*4882a593Smuzhiyun * The Socionext Synquacer SoC incorporates ARM's own GIC-500
4776*4882a593Smuzhiyun * implementation, but with a 'pre-ITS' added that requires
4777*4882a593Smuzhiyun * special handling in software.
4778*4882a593Smuzhiyun */
4779*4882a593Smuzhiyun .desc = "ITS: Socionext Synquacer pre-ITS",
4780*4882a593Smuzhiyun .iidr = 0x0001143b,
4781*4882a593Smuzhiyun .mask = 0xffffffff,
4782*4882a593Smuzhiyun .init = its_enable_quirk_socionext_synquacer,
4783*4882a593Smuzhiyun },
4784*4882a593Smuzhiyun #endif
4785*4882a593Smuzhiyun #ifdef CONFIG_HISILICON_ERRATUM_161600802
4786*4882a593Smuzhiyun {
4787*4882a593Smuzhiyun .desc = "ITS: Hip07 erratum 161600802",
4788*4882a593Smuzhiyun .iidr = 0x00000004,
4789*4882a593Smuzhiyun .mask = 0xffffffff,
4790*4882a593Smuzhiyun .init = its_enable_quirk_hip07_161600802,
4791*4882a593Smuzhiyun },
4792*4882a593Smuzhiyun #endif
4793*4882a593Smuzhiyun {
4794*4882a593Smuzhiyun }
4795*4882a593Smuzhiyun };
4796*4882a593Smuzhiyun
its_enable_quirks(struct its_node * its)4797*4882a593Smuzhiyun static void its_enable_quirks(struct its_node *its)
4798*4882a593Smuzhiyun {
4799*4882a593Smuzhiyun u32 iidr = readl_relaxed(its->base + GITS_IIDR);
4800*4882a593Smuzhiyun
4801*4882a593Smuzhiyun gic_enable_quirks(iidr, its_quirks, its);
4802*4882a593Smuzhiyun }
4803*4882a593Smuzhiyun
its_save_disable(void)4804*4882a593Smuzhiyun static int its_save_disable(void)
4805*4882a593Smuzhiyun {
4806*4882a593Smuzhiyun struct its_node *its;
4807*4882a593Smuzhiyun int err = 0;
4808*4882a593Smuzhiyun
4809*4882a593Smuzhiyun raw_spin_lock(&its_lock);
4810*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
4811*4882a593Smuzhiyun void __iomem *base;
4812*4882a593Smuzhiyun
4813*4882a593Smuzhiyun base = its->base;
4814*4882a593Smuzhiyun its->ctlr_save = readl_relaxed(base + GITS_CTLR);
4815*4882a593Smuzhiyun err = its_force_quiescent(base);
4816*4882a593Smuzhiyun if (err) {
4817*4882a593Smuzhiyun pr_err("ITS@%pa: failed to quiesce: %d\n",
4818*4882a593Smuzhiyun &its->phys_base, err);
4819*4882a593Smuzhiyun writel_relaxed(its->ctlr_save, base + GITS_CTLR);
4820*4882a593Smuzhiyun goto err;
4821*4882a593Smuzhiyun }
4822*4882a593Smuzhiyun
4823*4882a593Smuzhiyun its->cbaser_save = gits_read_cbaser(base + GITS_CBASER);
4824*4882a593Smuzhiyun }
4825*4882a593Smuzhiyun
4826*4882a593Smuzhiyun err:
4827*4882a593Smuzhiyun if (err) {
4828*4882a593Smuzhiyun list_for_each_entry_continue_reverse(its, &its_nodes, entry) {
4829*4882a593Smuzhiyun void __iomem *base;
4830*4882a593Smuzhiyun
4831*4882a593Smuzhiyun base = its->base;
4832*4882a593Smuzhiyun writel_relaxed(its->ctlr_save, base + GITS_CTLR);
4833*4882a593Smuzhiyun }
4834*4882a593Smuzhiyun }
4835*4882a593Smuzhiyun raw_spin_unlock(&its_lock);
4836*4882a593Smuzhiyun
4837*4882a593Smuzhiyun return err;
4838*4882a593Smuzhiyun }
4839*4882a593Smuzhiyun
its_restore_enable(void)4840*4882a593Smuzhiyun static void its_restore_enable(void)
4841*4882a593Smuzhiyun {
4842*4882a593Smuzhiyun struct its_node *its;
4843*4882a593Smuzhiyun int ret;
4844*4882a593Smuzhiyun
4845*4882a593Smuzhiyun raw_spin_lock(&its_lock);
4846*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
4847*4882a593Smuzhiyun void __iomem *base;
4848*4882a593Smuzhiyun int i;
4849*4882a593Smuzhiyun
4850*4882a593Smuzhiyun base = its->base;
4851*4882a593Smuzhiyun
4852*4882a593Smuzhiyun /*
4853*4882a593Smuzhiyun * Make sure that the ITS is disabled. If it fails to quiesce,
4854*4882a593Smuzhiyun * don't restore it since writing to CBASER or BASER<n>
4855*4882a593Smuzhiyun * registers is undefined according to the GIC v3 ITS
4856*4882a593Smuzhiyun * Specification.
4857*4882a593Smuzhiyun *
4858*4882a593Smuzhiyun * Firmware resuming with the ITS enabled is terminally broken.
4859*4882a593Smuzhiyun */
4860*4882a593Smuzhiyun WARN_ON(readl_relaxed(base + GITS_CTLR) & GITS_CTLR_ENABLE);
4861*4882a593Smuzhiyun ret = its_force_quiescent(base);
4862*4882a593Smuzhiyun if (ret) {
4863*4882a593Smuzhiyun pr_err("ITS@%pa: failed to quiesce on resume: %d\n",
4864*4882a593Smuzhiyun &its->phys_base, ret);
4865*4882a593Smuzhiyun continue;
4866*4882a593Smuzhiyun }
4867*4882a593Smuzhiyun
4868*4882a593Smuzhiyun gits_write_cbaser(its->cbaser_save, base + GITS_CBASER);
4869*4882a593Smuzhiyun
4870*4882a593Smuzhiyun /*
4871*4882a593Smuzhiyun * Writing CBASER resets CREADR to 0, so make CWRITER and
4872*4882a593Smuzhiyun * cmd_write line up with it.
4873*4882a593Smuzhiyun */
4874*4882a593Smuzhiyun its->cmd_write = its->cmd_base;
4875*4882a593Smuzhiyun gits_write_cwriter(0, base + GITS_CWRITER);
4876*4882a593Smuzhiyun
4877*4882a593Smuzhiyun /* Restore GITS_BASER from the value cache. */
4878*4882a593Smuzhiyun for (i = 0; i < GITS_BASER_NR_REGS; i++) {
4879*4882a593Smuzhiyun struct its_baser *baser = &its->tables[i];
4880*4882a593Smuzhiyun
4881*4882a593Smuzhiyun if (!(baser->val & GITS_BASER_VALID))
4882*4882a593Smuzhiyun continue;
4883*4882a593Smuzhiyun
4884*4882a593Smuzhiyun its_write_baser(its, baser, baser->val);
4885*4882a593Smuzhiyun }
4886*4882a593Smuzhiyun writel_relaxed(its->ctlr_save, base + GITS_CTLR);
4887*4882a593Smuzhiyun
4888*4882a593Smuzhiyun /*
4889*4882a593Smuzhiyun * Reinit the collection if it's stored in the ITS. This is
4890*4882a593Smuzhiyun * indicated by the col_id being less than the HCC field.
4891*4882a593Smuzhiyun * CID < HCC as specified in the GIC v3 Documentation.
4892*4882a593Smuzhiyun */
4893*4882a593Smuzhiyun if (its->collections[smp_processor_id()].col_id <
4894*4882a593Smuzhiyun GITS_TYPER_HCC(gic_read_typer(base + GITS_TYPER)))
4895*4882a593Smuzhiyun its_cpu_init_collection(its);
4896*4882a593Smuzhiyun }
4897*4882a593Smuzhiyun raw_spin_unlock(&its_lock);
4898*4882a593Smuzhiyun }
4899*4882a593Smuzhiyun
4900*4882a593Smuzhiyun static struct syscore_ops its_syscore_ops = {
4901*4882a593Smuzhiyun .suspend = its_save_disable,
4902*4882a593Smuzhiyun .resume = its_restore_enable,
4903*4882a593Smuzhiyun };
4904*4882a593Smuzhiyun
its_init_domain(struct fwnode_handle * handle,struct its_node * its)4905*4882a593Smuzhiyun static int its_init_domain(struct fwnode_handle *handle, struct its_node *its)
4906*4882a593Smuzhiyun {
4907*4882a593Smuzhiyun struct irq_domain *inner_domain;
4908*4882a593Smuzhiyun struct msi_domain_info *info;
4909*4882a593Smuzhiyun
4910*4882a593Smuzhiyun info = kzalloc(sizeof(*info), GFP_KERNEL);
4911*4882a593Smuzhiyun if (!info)
4912*4882a593Smuzhiyun return -ENOMEM;
4913*4882a593Smuzhiyun
4914*4882a593Smuzhiyun inner_domain = irq_domain_create_tree(handle, &its_domain_ops, its);
4915*4882a593Smuzhiyun if (!inner_domain) {
4916*4882a593Smuzhiyun kfree(info);
4917*4882a593Smuzhiyun return -ENOMEM;
4918*4882a593Smuzhiyun }
4919*4882a593Smuzhiyun
4920*4882a593Smuzhiyun inner_domain->parent = its_parent;
4921*4882a593Smuzhiyun irq_domain_update_bus_token(inner_domain, DOMAIN_BUS_NEXUS);
4922*4882a593Smuzhiyun inner_domain->flags |= its->msi_domain_flags;
4923*4882a593Smuzhiyun info->ops = &its_msi_domain_ops;
4924*4882a593Smuzhiyun info->data = its;
4925*4882a593Smuzhiyun inner_domain->host_data = info;
4926*4882a593Smuzhiyun
4927*4882a593Smuzhiyun return 0;
4928*4882a593Smuzhiyun }
4929*4882a593Smuzhiyun
its_init_vpe_domain(void)4930*4882a593Smuzhiyun static int its_init_vpe_domain(void)
4931*4882a593Smuzhiyun {
4932*4882a593Smuzhiyun struct its_node *its;
4933*4882a593Smuzhiyun u32 devid;
4934*4882a593Smuzhiyun int entries;
4935*4882a593Smuzhiyun
4936*4882a593Smuzhiyun if (gic_rdists->has_direct_lpi) {
4937*4882a593Smuzhiyun pr_info("ITS: Using DirectLPI for VPE invalidation\n");
4938*4882a593Smuzhiyun return 0;
4939*4882a593Smuzhiyun }
4940*4882a593Smuzhiyun
4941*4882a593Smuzhiyun /* Any ITS will do, even if not v4 */
4942*4882a593Smuzhiyun its = list_first_entry(&its_nodes, struct its_node, entry);
4943*4882a593Smuzhiyun
4944*4882a593Smuzhiyun entries = roundup_pow_of_two(nr_cpu_ids);
4945*4882a593Smuzhiyun vpe_proxy.vpes = kcalloc(entries, sizeof(*vpe_proxy.vpes),
4946*4882a593Smuzhiyun GFP_KERNEL);
4947*4882a593Smuzhiyun if (!vpe_proxy.vpes) {
4948*4882a593Smuzhiyun pr_err("ITS: Can't allocate GICv4 proxy device array\n");
4949*4882a593Smuzhiyun return -ENOMEM;
4950*4882a593Smuzhiyun }
4951*4882a593Smuzhiyun
4952*4882a593Smuzhiyun /* Use the last possible DevID */
4953*4882a593Smuzhiyun devid = GENMASK(device_ids(its) - 1, 0);
4954*4882a593Smuzhiyun vpe_proxy.dev = its_create_device(its, devid, entries, false);
4955*4882a593Smuzhiyun if (!vpe_proxy.dev) {
4956*4882a593Smuzhiyun kfree(vpe_proxy.vpes);
4957*4882a593Smuzhiyun pr_err("ITS: Can't allocate GICv4 proxy device\n");
4958*4882a593Smuzhiyun return -ENOMEM;
4959*4882a593Smuzhiyun }
4960*4882a593Smuzhiyun
4961*4882a593Smuzhiyun BUG_ON(entries > vpe_proxy.dev->nr_ites);
4962*4882a593Smuzhiyun
4963*4882a593Smuzhiyun raw_spin_lock_init(&vpe_proxy.lock);
4964*4882a593Smuzhiyun vpe_proxy.next_victim = 0;
4965*4882a593Smuzhiyun pr_info("ITS: Allocated DevID %x as GICv4 proxy device (%d slots)\n",
4966*4882a593Smuzhiyun devid, vpe_proxy.dev->nr_ites);
4967*4882a593Smuzhiyun
4968*4882a593Smuzhiyun return 0;
4969*4882a593Smuzhiyun }
4970*4882a593Smuzhiyun
its_compute_its_list_map(struct resource * res,void __iomem * its_base)4971*4882a593Smuzhiyun static int __init its_compute_its_list_map(struct resource *res,
4972*4882a593Smuzhiyun void __iomem *its_base)
4973*4882a593Smuzhiyun {
4974*4882a593Smuzhiyun int its_number;
4975*4882a593Smuzhiyun u32 ctlr;
4976*4882a593Smuzhiyun
4977*4882a593Smuzhiyun /*
4978*4882a593Smuzhiyun * This is assumed to be done early enough that we're
4979*4882a593Smuzhiyun * guaranteed to be single-threaded, hence no
4980*4882a593Smuzhiyun * locking. Should this change, we should address
4981*4882a593Smuzhiyun * this.
4982*4882a593Smuzhiyun */
4983*4882a593Smuzhiyun its_number = find_first_zero_bit(&its_list_map, GICv4_ITS_LIST_MAX);
4984*4882a593Smuzhiyun if (its_number >= GICv4_ITS_LIST_MAX) {
4985*4882a593Smuzhiyun pr_err("ITS@%pa: No ITSList entry available!\n",
4986*4882a593Smuzhiyun &res->start);
4987*4882a593Smuzhiyun return -EINVAL;
4988*4882a593Smuzhiyun }
4989*4882a593Smuzhiyun
4990*4882a593Smuzhiyun ctlr = readl_relaxed(its_base + GITS_CTLR);
4991*4882a593Smuzhiyun ctlr &= ~GITS_CTLR_ITS_NUMBER;
4992*4882a593Smuzhiyun ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT;
4993*4882a593Smuzhiyun writel_relaxed(ctlr, its_base + GITS_CTLR);
4994*4882a593Smuzhiyun ctlr = readl_relaxed(its_base + GITS_CTLR);
4995*4882a593Smuzhiyun if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) {
4996*4882a593Smuzhiyun its_number = ctlr & GITS_CTLR_ITS_NUMBER;
4997*4882a593Smuzhiyun its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT;
4998*4882a593Smuzhiyun }
4999*4882a593Smuzhiyun
5000*4882a593Smuzhiyun if (test_and_set_bit(its_number, &its_list_map)) {
5001*4882a593Smuzhiyun pr_err("ITS@%pa: Duplicate ITSList entry %d\n",
5002*4882a593Smuzhiyun &res->start, its_number);
5003*4882a593Smuzhiyun return -EINVAL;
5004*4882a593Smuzhiyun }
5005*4882a593Smuzhiyun
5006*4882a593Smuzhiyun return its_number;
5007*4882a593Smuzhiyun }
5008*4882a593Smuzhiyun
its_probe_one(struct resource * res,struct fwnode_handle * handle,int numa_node)5009*4882a593Smuzhiyun static int __init its_probe_one(struct resource *res,
5010*4882a593Smuzhiyun struct fwnode_handle *handle, int numa_node)
5011*4882a593Smuzhiyun {
5012*4882a593Smuzhiyun struct its_node *its;
5013*4882a593Smuzhiyun void __iomem *its_base;
5014*4882a593Smuzhiyun u32 val, ctlr;
5015*4882a593Smuzhiyun u64 baser, tmp, typer;
5016*4882a593Smuzhiyun struct page *page;
5017*4882a593Smuzhiyun int err;
5018*4882a593Smuzhiyun gfp_t gfp_flags;
5019*4882a593Smuzhiyun
5020*4882a593Smuzhiyun its_base = ioremap(res->start, SZ_64K);
5021*4882a593Smuzhiyun if (!its_base) {
5022*4882a593Smuzhiyun pr_warn("ITS@%pa: Unable to map ITS registers\n", &res->start);
5023*4882a593Smuzhiyun return -ENOMEM;
5024*4882a593Smuzhiyun }
5025*4882a593Smuzhiyun
5026*4882a593Smuzhiyun val = readl_relaxed(its_base + GITS_PIDR2) & GIC_PIDR2_ARCH_MASK;
5027*4882a593Smuzhiyun if (val != 0x30 && val != 0x40) {
5028*4882a593Smuzhiyun pr_warn("ITS@%pa: No ITS detected, giving up\n", &res->start);
5029*4882a593Smuzhiyun err = -ENODEV;
5030*4882a593Smuzhiyun goto out_unmap;
5031*4882a593Smuzhiyun }
5032*4882a593Smuzhiyun
5033*4882a593Smuzhiyun err = its_force_quiescent(its_base);
5034*4882a593Smuzhiyun if (err) {
5035*4882a593Smuzhiyun pr_warn("ITS@%pa: Failed to quiesce, giving up\n", &res->start);
5036*4882a593Smuzhiyun goto out_unmap;
5037*4882a593Smuzhiyun }
5038*4882a593Smuzhiyun
5039*4882a593Smuzhiyun pr_info("ITS %pR\n", res);
5040*4882a593Smuzhiyun
5041*4882a593Smuzhiyun its = kzalloc(sizeof(*its), GFP_KERNEL);
5042*4882a593Smuzhiyun if (!its) {
5043*4882a593Smuzhiyun err = -ENOMEM;
5044*4882a593Smuzhiyun goto out_unmap;
5045*4882a593Smuzhiyun }
5046*4882a593Smuzhiyun
5047*4882a593Smuzhiyun raw_spin_lock_init(&its->lock);
5048*4882a593Smuzhiyun mutex_init(&its->dev_alloc_lock);
5049*4882a593Smuzhiyun INIT_LIST_HEAD(&its->entry);
5050*4882a593Smuzhiyun INIT_LIST_HEAD(&its->its_device_list);
5051*4882a593Smuzhiyun typer = gic_read_typer(its_base + GITS_TYPER);
5052*4882a593Smuzhiyun its->typer = typer;
5053*4882a593Smuzhiyun its->base = its_base;
5054*4882a593Smuzhiyun its->phys_base = res->start;
5055*4882a593Smuzhiyun if (is_v4(its)) {
5056*4882a593Smuzhiyun if (!(typer & GITS_TYPER_VMOVP)) {
5057*4882a593Smuzhiyun err = its_compute_its_list_map(res, its_base);
5058*4882a593Smuzhiyun if (err < 0)
5059*4882a593Smuzhiyun goto out_free_its;
5060*4882a593Smuzhiyun
5061*4882a593Smuzhiyun its->list_nr = err;
5062*4882a593Smuzhiyun
5063*4882a593Smuzhiyun pr_info("ITS@%pa: Using ITS number %d\n",
5064*4882a593Smuzhiyun &res->start, err);
5065*4882a593Smuzhiyun } else {
5066*4882a593Smuzhiyun pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
5067*4882a593Smuzhiyun }
5068*4882a593Smuzhiyun
5069*4882a593Smuzhiyun if (is_v4_1(its)) {
5070*4882a593Smuzhiyun u32 svpet = FIELD_GET(GITS_TYPER_SVPET, typer);
5071*4882a593Smuzhiyun
5072*4882a593Smuzhiyun its->sgir_base = ioremap(res->start + SZ_128K, SZ_64K);
5073*4882a593Smuzhiyun if (!its->sgir_base) {
5074*4882a593Smuzhiyun err = -ENOMEM;
5075*4882a593Smuzhiyun goto out_free_its;
5076*4882a593Smuzhiyun }
5077*4882a593Smuzhiyun
5078*4882a593Smuzhiyun its->mpidr = readl_relaxed(its_base + GITS_MPIDR);
5079*4882a593Smuzhiyun
5080*4882a593Smuzhiyun pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n",
5081*4882a593Smuzhiyun &res->start, its->mpidr, svpet);
5082*4882a593Smuzhiyun }
5083*4882a593Smuzhiyun }
5084*4882a593Smuzhiyun
5085*4882a593Smuzhiyun its->numa_node = numa_node;
5086*4882a593Smuzhiyun
5087*4882a593Smuzhiyun gfp_flags = GFP_KERNEL | __GFP_ZERO;
5088*4882a593Smuzhiyun if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566"))
5089*4882a593Smuzhiyun gfp_flags |= GFP_DMA32;
5090*4882a593Smuzhiyun page = alloc_pages_node(its->numa_node, gfp_flags,
5091*4882a593Smuzhiyun get_order(ITS_CMD_QUEUE_SZ));
5092*4882a593Smuzhiyun if (!page) {
5093*4882a593Smuzhiyun err = -ENOMEM;
5094*4882a593Smuzhiyun goto out_unmap_sgir;
5095*4882a593Smuzhiyun }
5096*4882a593Smuzhiyun its->cmd_base = (void *)page_address(page);
5097*4882a593Smuzhiyun its->cmd_write = its->cmd_base;
5098*4882a593Smuzhiyun its->fwnode_handle = handle;
5099*4882a593Smuzhiyun its->get_msi_base = its_irq_get_msi_base;
5100*4882a593Smuzhiyun its->msi_domain_flags = IRQ_DOMAIN_FLAG_MSI_REMAP;
5101*4882a593Smuzhiyun
5102*4882a593Smuzhiyun its_enable_quirks(its);
5103*4882a593Smuzhiyun
5104*4882a593Smuzhiyun err = its_alloc_tables(its);
5105*4882a593Smuzhiyun if (err)
5106*4882a593Smuzhiyun goto out_free_cmd;
5107*4882a593Smuzhiyun
5108*4882a593Smuzhiyun err = its_alloc_collections(its);
5109*4882a593Smuzhiyun if (err)
5110*4882a593Smuzhiyun goto out_free_tables;
5111*4882a593Smuzhiyun
5112*4882a593Smuzhiyun baser = (virt_to_phys(its->cmd_base) |
5113*4882a593Smuzhiyun GITS_CBASER_RaWaWb |
5114*4882a593Smuzhiyun GITS_CBASER_InnerShareable |
5115*4882a593Smuzhiyun (ITS_CMD_QUEUE_SZ / SZ_4K - 1) |
5116*4882a593Smuzhiyun GITS_CBASER_VALID);
5117*4882a593Smuzhiyun
5118*4882a593Smuzhiyun gits_write_cbaser(baser, its->base + GITS_CBASER);
5119*4882a593Smuzhiyun tmp = gits_read_cbaser(its->base + GITS_CBASER);
5120*4882a593Smuzhiyun
5121*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_NO_GKI) &&
5122*4882a593Smuzhiyun (of_machine_is_compatible("rockchip,rk3568") ||
5123*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3566") ||
5124*4882a593Smuzhiyun of_machine_is_compatible("rockchip,rk3588")))
5125*4882a593Smuzhiyun tmp &= ~GITS_CBASER_SHAREABILITY_MASK;
5126*4882a593Smuzhiyun
5127*4882a593Smuzhiyun if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
5128*4882a593Smuzhiyun if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {
5129*4882a593Smuzhiyun /*
5130*4882a593Smuzhiyun * The HW reports non-shareable, we must
5131*4882a593Smuzhiyun * remove the cacheability attributes as
5132*4882a593Smuzhiyun * well.
5133*4882a593Smuzhiyun */
5134*4882a593Smuzhiyun baser &= ~(GITS_CBASER_SHAREABILITY_MASK |
5135*4882a593Smuzhiyun GITS_CBASER_CACHEABILITY_MASK);
5136*4882a593Smuzhiyun baser |= GITS_CBASER_nC;
5137*4882a593Smuzhiyun gits_write_cbaser(baser, its->base + GITS_CBASER);
5138*4882a593Smuzhiyun }
5139*4882a593Smuzhiyun pr_info("ITS: using cache flushing for cmd queue\n");
5140*4882a593Smuzhiyun its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING;
5141*4882a593Smuzhiyun }
5142*4882a593Smuzhiyun
5143*4882a593Smuzhiyun gits_write_cwriter(0, its->base + GITS_CWRITER);
5144*4882a593Smuzhiyun ctlr = readl_relaxed(its->base + GITS_CTLR);
5145*4882a593Smuzhiyun ctlr |= GITS_CTLR_ENABLE;
5146*4882a593Smuzhiyun if (is_v4(its))
5147*4882a593Smuzhiyun ctlr |= GITS_CTLR_ImDe;
5148*4882a593Smuzhiyun writel_relaxed(ctlr, its->base + GITS_CTLR);
5149*4882a593Smuzhiyun
5150*4882a593Smuzhiyun err = its_init_domain(handle, its);
5151*4882a593Smuzhiyun if (err)
5152*4882a593Smuzhiyun goto out_free_tables;
5153*4882a593Smuzhiyun
5154*4882a593Smuzhiyun raw_spin_lock(&its_lock);
5155*4882a593Smuzhiyun list_add(&its->entry, &its_nodes);
5156*4882a593Smuzhiyun raw_spin_unlock(&its_lock);
5157*4882a593Smuzhiyun
5158*4882a593Smuzhiyun return 0;
5159*4882a593Smuzhiyun
5160*4882a593Smuzhiyun out_free_tables:
5161*4882a593Smuzhiyun its_free_tables(its);
5162*4882a593Smuzhiyun out_free_cmd:
5163*4882a593Smuzhiyun free_pages((unsigned long)its->cmd_base, get_order(ITS_CMD_QUEUE_SZ));
5164*4882a593Smuzhiyun out_unmap_sgir:
5165*4882a593Smuzhiyun if (its->sgir_base)
5166*4882a593Smuzhiyun iounmap(its->sgir_base);
5167*4882a593Smuzhiyun out_free_its:
5168*4882a593Smuzhiyun kfree(its);
5169*4882a593Smuzhiyun out_unmap:
5170*4882a593Smuzhiyun iounmap(its_base);
5171*4882a593Smuzhiyun pr_err("ITS@%pa: failed probing (%d)\n", &res->start, err);
5172*4882a593Smuzhiyun return err;
5173*4882a593Smuzhiyun }
5174*4882a593Smuzhiyun
gic_rdists_supports_plpis(void)5175*4882a593Smuzhiyun static bool gic_rdists_supports_plpis(void)
5176*4882a593Smuzhiyun {
5177*4882a593Smuzhiyun return !!(gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER) & GICR_TYPER_PLPIS);
5178*4882a593Smuzhiyun }
5179*4882a593Smuzhiyun
redist_disable_lpis(void)5180*4882a593Smuzhiyun static int redist_disable_lpis(void)
5181*4882a593Smuzhiyun {
5182*4882a593Smuzhiyun void __iomem *rbase = gic_data_rdist_rd_base();
5183*4882a593Smuzhiyun u64 timeout = USEC_PER_SEC;
5184*4882a593Smuzhiyun u64 val;
5185*4882a593Smuzhiyun
5186*4882a593Smuzhiyun if (!gic_rdists_supports_plpis()) {
5187*4882a593Smuzhiyun pr_info("CPU%d: LPIs not supported\n", smp_processor_id());
5188*4882a593Smuzhiyun return -ENXIO;
5189*4882a593Smuzhiyun }
5190*4882a593Smuzhiyun
5191*4882a593Smuzhiyun val = readl_relaxed(rbase + GICR_CTLR);
5192*4882a593Smuzhiyun if (!(val & GICR_CTLR_ENABLE_LPIS))
5193*4882a593Smuzhiyun return 0;
5194*4882a593Smuzhiyun
5195*4882a593Smuzhiyun /*
5196*4882a593Smuzhiyun * If coming via a CPU hotplug event, we don't need to disable
5197*4882a593Smuzhiyun * LPIs before trying to re-enable them. They are already
5198*4882a593Smuzhiyun * configured and all is well in the world.
5199*4882a593Smuzhiyun *
5200*4882a593Smuzhiyun * If running with preallocated tables, there is nothing to do.
5201*4882a593Smuzhiyun */
5202*4882a593Smuzhiyun if (gic_data_rdist()->lpi_enabled ||
5203*4882a593Smuzhiyun (gic_rdists->flags & RDIST_FLAGS_RD_TABLES_PREALLOCATED))
5204*4882a593Smuzhiyun return 0;
5205*4882a593Smuzhiyun
5206*4882a593Smuzhiyun /*
5207*4882a593Smuzhiyun * From that point on, we only try to do some damage control.
5208*4882a593Smuzhiyun */
5209*4882a593Smuzhiyun pr_warn("GICv3: CPU%d: Booted with LPIs enabled, memory probably corrupted\n",
5210*4882a593Smuzhiyun smp_processor_id());
5211*4882a593Smuzhiyun add_taint(TAINT_CRAP, LOCKDEP_STILL_OK);
5212*4882a593Smuzhiyun
5213*4882a593Smuzhiyun /* Disable LPIs */
5214*4882a593Smuzhiyun val &= ~GICR_CTLR_ENABLE_LPIS;
5215*4882a593Smuzhiyun writel_relaxed(val, rbase + GICR_CTLR);
5216*4882a593Smuzhiyun
5217*4882a593Smuzhiyun /* Make sure any change to GICR_CTLR is observable by the GIC */
5218*4882a593Smuzhiyun dsb(sy);
5219*4882a593Smuzhiyun
5220*4882a593Smuzhiyun /*
5221*4882a593Smuzhiyun * Software must observe RWP==0 after clearing GICR_CTLR.EnableLPIs
5222*4882a593Smuzhiyun * from 1 to 0 before programming GICR_PEND{PROP}BASER registers.
5223*4882a593Smuzhiyun * Error out if we time out waiting for RWP to clear.
5224*4882a593Smuzhiyun */
5225*4882a593Smuzhiyun while (readl_relaxed(rbase + GICR_CTLR) & GICR_CTLR_RWP) {
5226*4882a593Smuzhiyun if (!timeout) {
5227*4882a593Smuzhiyun pr_err("CPU%d: Timeout while disabling LPIs\n",
5228*4882a593Smuzhiyun smp_processor_id());
5229*4882a593Smuzhiyun return -ETIMEDOUT;
5230*4882a593Smuzhiyun }
5231*4882a593Smuzhiyun udelay(1);
5232*4882a593Smuzhiyun timeout--;
5233*4882a593Smuzhiyun }
5234*4882a593Smuzhiyun
5235*4882a593Smuzhiyun /*
5236*4882a593Smuzhiyun * After it has been written to 1, it is IMPLEMENTATION
5237*4882a593Smuzhiyun * DEFINED whether GICR_CTLR.EnableLPI becomes RES1 or can be
5238*4882a593Smuzhiyun * cleared to 0. Error out if clearing the bit failed.
5239*4882a593Smuzhiyun */
5240*4882a593Smuzhiyun if (readl_relaxed(rbase + GICR_CTLR) & GICR_CTLR_ENABLE_LPIS) {
5241*4882a593Smuzhiyun pr_err("CPU%d: Failed to disable LPIs\n", smp_processor_id());
5242*4882a593Smuzhiyun return -EBUSY;
5243*4882a593Smuzhiyun }
5244*4882a593Smuzhiyun
5245*4882a593Smuzhiyun return 0;
5246*4882a593Smuzhiyun }
5247*4882a593Smuzhiyun
its_cpu_init(void)5248*4882a593Smuzhiyun int its_cpu_init(void)
5249*4882a593Smuzhiyun {
5250*4882a593Smuzhiyun if (!list_empty(&its_nodes)) {
5251*4882a593Smuzhiyun int ret;
5252*4882a593Smuzhiyun
5253*4882a593Smuzhiyun ret = redist_disable_lpis();
5254*4882a593Smuzhiyun if (ret)
5255*4882a593Smuzhiyun return ret;
5256*4882a593Smuzhiyun
5257*4882a593Smuzhiyun its_cpu_init_lpis();
5258*4882a593Smuzhiyun its_cpu_init_collections();
5259*4882a593Smuzhiyun }
5260*4882a593Smuzhiyun
5261*4882a593Smuzhiyun return 0;
5262*4882a593Smuzhiyun }
5263*4882a593Smuzhiyun
5264*4882a593Smuzhiyun static const struct of_device_id its_device_id[] = {
5265*4882a593Smuzhiyun { .compatible = "arm,gic-v3-its", },
5266*4882a593Smuzhiyun {},
5267*4882a593Smuzhiyun };
5268*4882a593Smuzhiyun
its_of_probe(struct device_node * node)5269*4882a593Smuzhiyun static int __init its_of_probe(struct device_node *node)
5270*4882a593Smuzhiyun {
5271*4882a593Smuzhiyun struct device_node *np;
5272*4882a593Smuzhiyun struct resource res;
5273*4882a593Smuzhiyun
5274*4882a593Smuzhiyun for (np = of_find_matching_node(node, its_device_id); np;
5275*4882a593Smuzhiyun np = of_find_matching_node(np, its_device_id)) {
5276*4882a593Smuzhiyun if (!of_device_is_available(np))
5277*4882a593Smuzhiyun continue;
5278*4882a593Smuzhiyun if (!of_property_read_bool(np, "msi-controller")) {
5279*4882a593Smuzhiyun pr_warn("%pOF: no msi-controller property, ITS ignored\n",
5280*4882a593Smuzhiyun np);
5281*4882a593Smuzhiyun continue;
5282*4882a593Smuzhiyun }
5283*4882a593Smuzhiyun
5284*4882a593Smuzhiyun if (of_address_to_resource(np, 0, &res)) {
5285*4882a593Smuzhiyun pr_warn("%pOF: no regs?\n", np);
5286*4882a593Smuzhiyun continue;
5287*4882a593Smuzhiyun }
5288*4882a593Smuzhiyun
5289*4882a593Smuzhiyun its_probe_one(&res, &np->fwnode, of_node_to_nid(np));
5290*4882a593Smuzhiyun }
5291*4882a593Smuzhiyun return 0;
5292*4882a593Smuzhiyun }
5293*4882a593Smuzhiyun
5294*4882a593Smuzhiyun #ifdef CONFIG_ACPI
5295*4882a593Smuzhiyun
5296*4882a593Smuzhiyun #define ACPI_GICV3_ITS_MEM_SIZE (SZ_128K)
5297*4882a593Smuzhiyun
5298*4882a593Smuzhiyun #ifdef CONFIG_ACPI_NUMA
5299*4882a593Smuzhiyun struct its_srat_map {
5300*4882a593Smuzhiyun /* numa node id */
5301*4882a593Smuzhiyun u32 numa_node;
5302*4882a593Smuzhiyun /* GIC ITS ID */
5303*4882a593Smuzhiyun u32 its_id;
5304*4882a593Smuzhiyun };
5305*4882a593Smuzhiyun
5306*4882a593Smuzhiyun static struct its_srat_map *its_srat_maps __initdata;
5307*4882a593Smuzhiyun static int its_in_srat __initdata;
5308*4882a593Smuzhiyun
acpi_get_its_numa_node(u32 its_id)5309*4882a593Smuzhiyun static int __init acpi_get_its_numa_node(u32 its_id)
5310*4882a593Smuzhiyun {
5311*4882a593Smuzhiyun int i;
5312*4882a593Smuzhiyun
5313*4882a593Smuzhiyun for (i = 0; i < its_in_srat; i++) {
5314*4882a593Smuzhiyun if (its_id == its_srat_maps[i].its_id)
5315*4882a593Smuzhiyun return its_srat_maps[i].numa_node;
5316*4882a593Smuzhiyun }
5317*4882a593Smuzhiyun return NUMA_NO_NODE;
5318*4882a593Smuzhiyun }
5319*4882a593Smuzhiyun
gic_acpi_match_srat_its(union acpi_subtable_headers * header,const unsigned long end)5320*4882a593Smuzhiyun static int __init gic_acpi_match_srat_its(union acpi_subtable_headers *header,
5321*4882a593Smuzhiyun const unsigned long end)
5322*4882a593Smuzhiyun {
5323*4882a593Smuzhiyun return 0;
5324*4882a593Smuzhiyun }
5325*4882a593Smuzhiyun
gic_acpi_parse_srat_its(union acpi_subtable_headers * header,const unsigned long end)5326*4882a593Smuzhiyun static int __init gic_acpi_parse_srat_its(union acpi_subtable_headers *header,
5327*4882a593Smuzhiyun const unsigned long end)
5328*4882a593Smuzhiyun {
5329*4882a593Smuzhiyun int node;
5330*4882a593Smuzhiyun struct acpi_srat_gic_its_affinity *its_affinity;
5331*4882a593Smuzhiyun
5332*4882a593Smuzhiyun its_affinity = (struct acpi_srat_gic_its_affinity *)header;
5333*4882a593Smuzhiyun if (!its_affinity)
5334*4882a593Smuzhiyun return -EINVAL;
5335*4882a593Smuzhiyun
5336*4882a593Smuzhiyun if (its_affinity->header.length < sizeof(*its_affinity)) {
5337*4882a593Smuzhiyun pr_err("SRAT: Invalid header length %d in ITS affinity\n",
5338*4882a593Smuzhiyun its_affinity->header.length);
5339*4882a593Smuzhiyun return -EINVAL;
5340*4882a593Smuzhiyun }
5341*4882a593Smuzhiyun
5342*4882a593Smuzhiyun /*
5343*4882a593Smuzhiyun * Note that in theory a new proximity node could be created by this
5344*4882a593Smuzhiyun * entry as it is an SRAT resource allocation structure.
5345*4882a593Smuzhiyun * We do not currently support doing so.
5346*4882a593Smuzhiyun */
5347*4882a593Smuzhiyun node = pxm_to_node(its_affinity->proximity_domain);
5348*4882a593Smuzhiyun
5349*4882a593Smuzhiyun if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
5350*4882a593Smuzhiyun pr_err("SRAT: Invalid NUMA node %d in ITS affinity\n", node);
5351*4882a593Smuzhiyun return 0;
5352*4882a593Smuzhiyun }
5353*4882a593Smuzhiyun
5354*4882a593Smuzhiyun its_srat_maps[its_in_srat].numa_node = node;
5355*4882a593Smuzhiyun its_srat_maps[its_in_srat].its_id = its_affinity->its_id;
5356*4882a593Smuzhiyun its_in_srat++;
5357*4882a593Smuzhiyun pr_info("SRAT: PXM %d -> ITS %d -> Node %d\n",
5358*4882a593Smuzhiyun its_affinity->proximity_domain, its_affinity->its_id, node);
5359*4882a593Smuzhiyun
5360*4882a593Smuzhiyun return 0;
5361*4882a593Smuzhiyun }
5362*4882a593Smuzhiyun
acpi_table_parse_srat_its(void)5363*4882a593Smuzhiyun static void __init acpi_table_parse_srat_its(void)
5364*4882a593Smuzhiyun {
5365*4882a593Smuzhiyun int count;
5366*4882a593Smuzhiyun
5367*4882a593Smuzhiyun count = acpi_table_parse_entries(ACPI_SIG_SRAT,
5368*4882a593Smuzhiyun sizeof(struct acpi_table_srat),
5369*4882a593Smuzhiyun ACPI_SRAT_TYPE_GIC_ITS_AFFINITY,
5370*4882a593Smuzhiyun gic_acpi_match_srat_its, 0);
5371*4882a593Smuzhiyun if (count <= 0)
5372*4882a593Smuzhiyun return;
5373*4882a593Smuzhiyun
5374*4882a593Smuzhiyun its_srat_maps = kmalloc_array(count, sizeof(struct its_srat_map),
5375*4882a593Smuzhiyun GFP_KERNEL);
5376*4882a593Smuzhiyun if (!its_srat_maps) {
5377*4882a593Smuzhiyun pr_warn("SRAT: Failed to allocate memory for its_srat_maps!\n");
5378*4882a593Smuzhiyun return;
5379*4882a593Smuzhiyun }
5380*4882a593Smuzhiyun
5381*4882a593Smuzhiyun acpi_table_parse_entries(ACPI_SIG_SRAT,
5382*4882a593Smuzhiyun sizeof(struct acpi_table_srat),
5383*4882a593Smuzhiyun ACPI_SRAT_TYPE_GIC_ITS_AFFINITY,
5384*4882a593Smuzhiyun gic_acpi_parse_srat_its, 0);
5385*4882a593Smuzhiyun }
5386*4882a593Smuzhiyun
5387*4882a593Smuzhiyun /* free the its_srat_maps after ITS probing */
acpi_its_srat_maps_free(void)5388*4882a593Smuzhiyun static void __init acpi_its_srat_maps_free(void)
5389*4882a593Smuzhiyun {
5390*4882a593Smuzhiyun kfree(its_srat_maps);
5391*4882a593Smuzhiyun }
5392*4882a593Smuzhiyun #else
acpi_table_parse_srat_its(void)5393*4882a593Smuzhiyun static void __init acpi_table_parse_srat_its(void) { }
acpi_get_its_numa_node(u32 its_id)5394*4882a593Smuzhiyun static int __init acpi_get_its_numa_node(u32 its_id) { return NUMA_NO_NODE; }
acpi_its_srat_maps_free(void)5395*4882a593Smuzhiyun static void __init acpi_its_srat_maps_free(void) { }
5396*4882a593Smuzhiyun #endif
5397*4882a593Smuzhiyun
gic_acpi_parse_madt_its(union acpi_subtable_headers * header,const unsigned long end)5398*4882a593Smuzhiyun static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header,
5399*4882a593Smuzhiyun const unsigned long end)
5400*4882a593Smuzhiyun {
5401*4882a593Smuzhiyun struct acpi_madt_generic_translator *its_entry;
5402*4882a593Smuzhiyun struct fwnode_handle *dom_handle;
5403*4882a593Smuzhiyun struct resource res;
5404*4882a593Smuzhiyun int err;
5405*4882a593Smuzhiyun
5406*4882a593Smuzhiyun its_entry = (struct acpi_madt_generic_translator *)header;
5407*4882a593Smuzhiyun memset(&res, 0, sizeof(res));
5408*4882a593Smuzhiyun res.start = its_entry->base_address;
5409*4882a593Smuzhiyun res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1;
5410*4882a593Smuzhiyun res.flags = IORESOURCE_MEM;
5411*4882a593Smuzhiyun
5412*4882a593Smuzhiyun dom_handle = irq_domain_alloc_fwnode(&res.start);
5413*4882a593Smuzhiyun if (!dom_handle) {
5414*4882a593Smuzhiyun pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n",
5415*4882a593Smuzhiyun &res.start);
5416*4882a593Smuzhiyun return -ENOMEM;
5417*4882a593Smuzhiyun }
5418*4882a593Smuzhiyun
5419*4882a593Smuzhiyun err = iort_register_domain_token(its_entry->translation_id, res.start,
5420*4882a593Smuzhiyun dom_handle);
5421*4882a593Smuzhiyun if (err) {
5422*4882a593Smuzhiyun pr_err("ITS@%pa: Unable to register GICv3 ITS domain token (ITS ID %d) to IORT\n",
5423*4882a593Smuzhiyun &res.start, its_entry->translation_id);
5424*4882a593Smuzhiyun goto dom_err;
5425*4882a593Smuzhiyun }
5426*4882a593Smuzhiyun
5427*4882a593Smuzhiyun err = its_probe_one(&res, dom_handle,
5428*4882a593Smuzhiyun acpi_get_its_numa_node(its_entry->translation_id));
5429*4882a593Smuzhiyun if (!err)
5430*4882a593Smuzhiyun return 0;
5431*4882a593Smuzhiyun
5432*4882a593Smuzhiyun iort_deregister_domain_token(its_entry->translation_id);
5433*4882a593Smuzhiyun dom_err:
5434*4882a593Smuzhiyun irq_domain_free_fwnode(dom_handle);
5435*4882a593Smuzhiyun return err;
5436*4882a593Smuzhiyun }
5437*4882a593Smuzhiyun
its_acpi_probe(void)5438*4882a593Smuzhiyun static void __init its_acpi_probe(void)
5439*4882a593Smuzhiyun {
5440*4882a593Smuzhiyun acpi_table_parse_srat_its();
5441*4882a593Smuzhiyun acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR,
5442*4882a593Smuzhiyun gic_acpi_parse_madt_its, 0);
5443*4882a593Smuzhiyun acpi_its_srat_maps_free();
5444*4882a593Smuzhiyun }
5445*4882a593Smuzhiyun #else
its_acpi_probe(void)5446*4882a593Smuzhiyun static void __init its_acpi_probe(void) { }
5447*4882a593Smuzhiyun #endif
5448*4882a593Smuzhiyun
its_init(struct fwnode_handle * handle,struct rdists * rdists,struct irq_domain * parent_domain)5449*4882a593Smuzhiyun int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
5450*4882a593Smuzhiyun struct irq_domain *parent_domain)
5451*4882a593Smuzhiyun {
5452*4882a593Smuzhiyun struct device_node *of_node;
5453*4882a593Smuzhiyun struct its_node *its;
5454*4882a593Smuzhiyun bool has_v4 = false;
5455*4882a593Smuzhiyun bool has_v4_1 = false;
5456*4882a593Smuzhiyun int err;
5457*4882a593Smuzhiyun
5458*4882a593Smuzhiyun gic_rdists = rdists;
5459*4882a593Smuzhiyun
5460*4882a593Smuzhiyun its_parent = parent_domain;
5461*4882a593Smuzhiyun of_node = to_of_node(handle);
5462*4882a593Smuzhiyun if (of_node)
5463*4882a593Smuzhiyun its_of_probe(of_node);
5464*4882a593Smuzhiyun else
5465*4882a593Smuzhiyun its_acpi_probe();
5466*4882a593Smuzhiyun
5467*4882a593Smuzhiyun if (list_empty(&its_nodes)) {
5468*4882a593Smuzhiyun pr_warn("ITS: No ITS available, not enabling LPIs\n");
5469*4882a593Smuzhiyun return -ENXIO;
5470*4882a593Smuzhiyun }
5471*4882a593Smuzhiyun
5472*4882a593Smuzhiyun err = allocate_lpi_tables();
5473*4882a593Smuzhiyun if (err)
5474*4882a593Smuzhiyun return err;
5475*4882a593Smuzhiyun
5476*4882a593Smuzhiyun list_for_each_entry(its, &its_nodes, entry) {
5477*4882a593Smuzhiyun has_v4 |= is_v4(its);
5478*4882a593Smuzhiyun has_v4_1 |= is_v4_1(its);
5479*4882a593Smuzhiyun }
5480*4882a593Smuzhiyun
5481*4882a593Smuzhiyun /* Don't bother with inconsistent systems */
5482*4882a593Smuzhiyun if (WARN_ON(!has_v4_1 && rdists->has_rvpeid))
5483*4882a593Smuzhiyun rdists->has_rvpeid = false;
5484*4882a593Smuzhiyun
5485*4882a593Smuzhiyun if (has_v4 & rdists->has_vlpis) {
5486*4882a593Smuzhiyun const struct irq_domain_ops *sgi_ops;
5487*4882a593Smuzhiyun
5488*4882a593Smuzhiyun if (has_v4_1)
5489*4882a593Smuzhiyun sgi_ops = &its_sgi_domain_ops;
5490*4882a593Smuzhiyun else
5491*4882a593Smuzhiyun sgi_ops = NULL;
5492*4882a593Smuzhiyun
5493*4882a593Smuzhiyun if (its_init_vpe_domain() ||
5494*4882a593Smuzhiyun its_init_v4(parent_domain, &its_vpe_domain_ops, sgi_ops)) {
5495*4882a593Smuzhiyun rdists->has_vlpis = false;
5496*4882a593Smuzhiyun pr_err("ITS: Disabling GICv4 support\n");
5497*4882a593Smuzhiyun }
5498*4882a593Smuzhiyun }
5499*4882a593Smuzhiyun
5500*4882a593Smuzhiyun register_syscore_ops(&its_syscore_ops);
5501*4882a593Smuzhiyun
5502*4882a593Smuzhiyun return 0;
5503*4882a593Smuzhiyun }
5504