Due to a silly oversight on my part, making the simple switch to of_io_request_and_map() in the DT path inadvertently introduced divergent behaviour, whereby failng to request an iomem region now becomes fatal for DT, vs. being silently ignored for ACPI. Refactor a bit harder, so that request errors are non-fatal in both paths as intended, but also consistently reported as well.
Unified · Split
| @@ -2042,15 +2042,40 @@ static void __init gic_of_setup_kvm_info(struct device_node *node) · 2041 unmodified lines | ||
| 2042 | 2042 | vgic_set_kvm_info(&gic_v3_kvm_info); |
| 2043 | 2043 | } |
| 2044 | 2044 | |
| 2045 | +static void gic_request_region(resource_size_t base, resource_size_t size, | |
| 2046 | + const char *name) | |
| 2047 | +{ | |
| 2048 | + if (!request_mem_region(base, size, name)) | |
| 2049 | + pr_warn_once(FW_BUG "%s region %pa has overlapping address\n", | |
| 2050 | + name, &base); | |
| 2051 | +} | |
| 2052 | + | |
| 2053 | +static void __iomem *gic_of_iomap(struct device_node *node, int idx, | |
| 2054 | + const char *name, struct resource *res) | |
| 2055 | +{ | |
| 2056 | + void __iomem *base; | |
| 2057 | + int ret; | |
| 2058 | + | |
| 2059 | + ret = of_address_to_resource(node, idx, res); | |
| 2060 | + if (ret) | |
| 2061 | + return IOMEM_ERR_PTR(ret); | |
| 2062 | + | |
| 2063 | + gic_request_region(res->start, resource_size(res), name); | |
| 2064 | + base = of_iomap(node, idx); | |
| 2065 | + | |
| 2066 | + return base ?: IOMEM_ERR_PTR(-ENOMEM); | |
| 2067 | +} | |
| 2068 | + | |
| 2045 | 2069 | static int __init gic_of_init(struct device_node *node, struct device_node *parent) |
| 2046 | 2070 | { |
| 2047 | 2071 | void __iomem *dist_base; |
| 2048 | 2072 | struct redist_region *rdist_regs; |
| 2073 | + struct resource res; | |
| 2049 | 2074 | u64 redist_stride; |
| 2050 | 2075 | u32 nr_redist_regions; |
| 2051 | 2076 | int err, i; |
| 2052 | 2077 | |
| 2053 | − dist_base = of_io_request_and_map(node, 0, "GICD"); | |
| 2078 | + dist_base = gic_of_iomap(node, 0, "GICD", &res); | |
| 2054 | 2079 | if (IS_ERR(dist_base)) { |
| 2055 | 2080 | pr_err("%pOF: unable to map gic dist registers\n", node); |
| 2056 | 2081 | return PTR_ERR(dist_base); |
| @@ -2073,12 +2098,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare · 16 unmodified lines | ||
| 2073 | 2098 | } |
| 2074 | 2099 | |
| 2075 | 2100 | for (i = 0; i < nr_redist_regions; i++) { |
| 2076 | − struct resource res; | |
| 2077 | − int ret; | |
| 2078 | − | |
| 2079 | − ret = of_address_to_resource(node, 1 + i, &res); | |
| 2080 | − rdist_regs[i].redist_base = of_io_request_and_map(node, 1 + i, "GICR"); | |
| 2081 | − if (ret || IS_ERR(rdist_regs[i].redist_base)) { | |
| 2101 | + rdist_regs[i].redist_base = gic_of_iomap(node, 1 + i, "GICR", &res); | |
| 2102 | + if (IS_ERR(rdist_regs[i].redist_base)) { | |
| 2082 | 2103 | pr_err("%pOF: couldn't map region %d\n", node, i); |
| 2083 | 2104 | err = -ENODEV; |
| 2084 | 2105 | goto out_unmap_rdist; |
| @@ -2151,7 +2172,7 @@ gic_acpi_parse_madt_redist(union acpi_subtable_headers *header, · 66 unmodified lines | ||
| 2151 | 2172 | pr_err("Couldn't map GICR region @%llx\n", redist->base_address); |
| 2152 | 2173 | return -ENOMEM; |
| 2153 | 2174 | } |
| 2154 | − request_mem_region(redist->base_address, redist->length, "GICR"); | |
| 2175 | + gic_request_region(redist->base_address, redist->length, "GICR"); | |
| 2155 | 2176 | |
| 2156 | 2177 | gic_acpi_register_redist(redist->base_address, redist_base); |
| 2157 | 2178 | return 0; |
| @@ -2174,7 +2195,7 @@ gic_acpi_parse_madt_gicc(union acpi_subtable_headers *header, · 16 unmodified lines | ||
| 2174 | 2195 | redist_base = ioremap(gicc->gicr_base_address, size); |
| 2175 | 2196 | if (!redist_base) |
| 2176 | 2197 | return -ENOMEM; |
| 2177 | − request_mem_region(gicc->gicr_base_address, size, "GICR"); | |
| 2198 | + gic_request_region(gicc->gicr_base_address, size, "GICR"); | |
| 2178 | 2199 | |
| 2179 | 2200 | gic_acpi_register_redist(gicc->gicr_base_address, redist_base); |
| 2180 | 2201 | return 0; |
| @@ -2376,7 +2397,7 @@ gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end) · 195 unmodified lines | ||
| 2376 | 2397 | pr_err("Unable to map GICD registers\n"); |
| 2377 | 2398 | return -ENOMEM; |
| 2378 | 2399 | } |
| 2379 | − request_mem_region(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE, "GICD"); | |
| 2400 | + gic_request_region(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE, "GICD"); | |
| 2380 | 2401 | |
| 2381 | 2402 | err = gic_validate_dist_version(acpi_data.dist_base); |
| 2382 | 2403 | if (err) { |