|
47 | 47 | #define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1)
|
48 | 48 |
|
49 | 49 | #define RD_LOCAL_LPI_ENABLED BIT(0)
|
| 50 | +#define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1) |
| 51 | +#define RD_LOCAL_MEMRESERVE_DONE BIT(2) |
50 | 52 |
|
51 | 53 | static u32 lpi_id_bits;
|
52 | 54 |
|
@@ -3065,15 +3067,13 @@ static void its_cpu_init_lpis(void)
|
3065 | 3067 | paddr &= GENMASK_ULL(51, 16);
|
3066 | 3068 |
|
3067 | 3069 | WARN_ON(!gic_check_reserved_range(paddr, LPI_PENDBASE_SZ));
|
3068 |
| - its_free_pending_table(gic_data_rdist()->pend_page); |
3069 |
| - gic_data_rdist()->pend_page = NULL; |
| 3070 | + gic_data_rdist()->flags |= RD_LOCAL_PENDTABLE_PREALLOCATED; |
3070 | 3071 |
|
3071 | 3072 | goto out;
|
3072 | 3073 | }
|
3073 | 3074 |
|
3074 | 3075 | pend_page = gic_data_rdist()->pend_page;
|
3075 | 3076 | paddr = page_to_phys(pend_page);
|
3076 |
| - WARN_ON(gic_reserve_range(paddr, LPI_PENDBASE_SZ)); |
3077 | 3077 |
|
3078 | 3078 | /* set PROPBASE */
|
3079 | 3079 | val = (gic_rdists->prop_table_pa |
|
@@ -3163,7 +3163,8 @@ static void its_cpu_init_lpis(void)
|
3163 | 3163 | gic_data_rdist()->flags |= RD_LOCAL_LPI_ENABLED;
|
3164 | 3164 | pr_info("GICv3: CPU%d: using %s LPI pending table @%pa\n",
|
3165 | 3165 | smp_processor_id(),
|
3166 |
| - gic_data_rdist()->pend_page ? "allocated" : "reserved", |
| 3166 | + gic_data_rdist()->flags & RD_LOCAL_PENDTABLE_PREALLOCATED ? |
| 3167 | + "reserved" : "allocated", |
3167 | 3168 | &paddr);
|
3168 | 3169 | }
|
3169 | 3170 |
|
@@ -5202,6 +5203,38 @@ int its_cpu_init(void)
|
5202 | 5203 | return 0;
|
5203 | 5204 | }
|
5204 | 5205 |
|
| 5206 | +static int its_cpu_memreserve_lpi(unsigned int cpu) |
| 5207 | +{ |
| 5208 | + struct page *pend_page; |
| 5209 | + int ret = 0; |
| 5210 | + |
| 5211 | + /* This gets to run exactly once per CPU */ |
| 5212 | + if (gic_data_rdist()->flags & RD_LOCAL_MEMRESERVE_DONE) |
| 5213 | + return 0; |
| 5214 | + |
| 5215 | + pend_page = gic_data_rdist()->pend_page; |
| 5216 | + if (WARN_ON(!pend_page)) { |
| 5217 | + ret = -ENOMEM; |
| 5218 | + goto out; |
| 5219 | + } |
| 5220 | + /* |
| 5221 | + * If the pending table was pre-programmed, free the memory we |
| 5222 | + * preemptively allocated. Otherwise, reserve that memory for |
| 5223 | + * later kexecs. |
| 5224 | + */ |
| 5225 | + if (gic_data_rdist()->flags & RD_LOCAL_PENDTABLE_PREALLOCATED) { |
| 5226 | + its_free_pending_table(pend_page); |
| 5227 | + gic_data_rdist()->pend_page = NULL; |
| 5228 | + } else { |
| 5229 | + phys_addr_t paddr = page_to_phys(pend_page); |
| 5230 | + WARN_ON(gic_reserve_range(paddr, LPI_PENDBASE_SZ)); |
| 5231 | + } |
| 5232 | + |
| 5233 | +out: |
| 5234 | + gic_data_rdist()->flags |= RD_LOCAL_MEMRESERVE_DONE; |
| 5235 | + return ret; |
| 5236 | +} |
| 5237 | + |
5205 | 5238 | static const struct of_device_id its_device_id[] = {
|
5206 | 5239 | { .compatible = "arm,gic-v3-its", },
|
5207 | 5240 | {},
|
@@ -5385,6 +5418,23 @@ static void __init its_acpi_probe(void)
|
5385 | 5418 | static void __init its_acpi_probe(void) { }
|
5386 | 5419 | #endif
|
5387 | 5420 |
|
| 5421 | +int __init its_lpi_memreserve_init(void) |
| 5422 | +{ |
| 5423 | + int state; |
| 5424 | + |
| 5425 | + if (!efi_enabled(EFI_CONFIG_TABLES)) |
| 5426 | + return 0; |
| 5427 | + |
| 5428 | + state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, |
| 5429 | + "irqchip/arm/gicv3/memreserve:online", |
| 5430 | + its_cpu_memreserve_lpi, |
| 5431 | + NULL); |
| 5432 | + if (state < 0) |
| 5433 | + return state; |
| 5434 | + |
| 5435 | + return 0; |
| 5436 | +} |
| 5437 | + |
5388 | 5438 | int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
|
5389 | 5439 | struct irq_domain *parent_domain)
|
5390 | 5440 | {
|
|
0 commit comments