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 | vgic_set_kvm_info(&gic_v3_kvm_info); | 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 | static int __init gic_of_init(struct device_node *node, struct device_node *parent) | 2069 | static int __init gic_of_init(struct device_node *node, struct device_node *parent) |
| 2046 | { | 2070 | { |
| 2047 | void __iomem *dist_base; | 2071 | void __iomem *dist_base; |
| 2048 | struct redist_region *rdist_regs; | 2072 | struct redist_region *rdist_regs; |
| 2073 | struct resource res; | ||
| 2049 | u64 redist_stride; | 2074 | u64 redist_stride; |
| 2050 | u32 nr_redist_regions; | 2075 | u32 nr_redist_regions; |
| 2051 | int err, i; | 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 | if (IS_ERR(dist_base)) { | 2079 | if (IS_ERR(dist_base)) { |
| 2055 | pr_err("%pOF: unable to map gic dist registers\n", node); | 2080 | pr_err("%pOF: unable to map gic dist registers\n", node); |
| 2056 | return PTR_ERR(dist_base); | 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 | for (i = 0; i < nr_redist_regions; i++) { | 2100 | for (i = 0; i < nr_redist_regions; i++) { |
| 2076 | struct resource res; | 2101 | rdist_regs[i].redist_base = gic_of_iomap(node, 1 + i, "GICR", &res); |
| 2077 | int ret; | 2102 | if (IS_ERR(rdist_regs[i].redist_base)) { |
| 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)) { | ||
| 2082 | pr_err("%pOF: couldn't map region %d\n", node, i); | 2103 | pr_err("%pOF: couldn't map region %d\n", node, i); |
| 2083 | err = -ENODEV; | 2104 | err = -ENODEV; |
| 2084 | goto out_unmap_rdist; | 2105 | goto out_unmap_rdist; |
| @@ -2151,7 +2172,7 @@ gic_acpi_parse_madt_redist(union acpi_subtable_headers *header, · 66 unmodified lines | |||
| 2151 | pr_err("Couldn't map GICR region @%llx\n", redist->base_address); | 2172 | pr_err("Couldn't map GICR region @%llx\n", redist->base_address); |
| 2152 | return -ENOMEM; | 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 | gic_acpi_register_redist(redist->base_address, redist_base); | 2177 | gic_acpi_register_redist(redist->base_address, redist_base); |
| 2157 | return 0; | 2178 | return 0; |
| @@ -2174,7 +2195,7 @@ gic_acpi_parse_madt_gicc(union acpi_subtable_headers *header, · 16 unmodified lines | |||
| 2174 | redist_base = ioremap(gicc->gicr_base_address, size); | 2195 | redist_base = ioremap(gicc->gicr_base_address, size); |
| 2175 | if (!redist_base) | 2196 | if (!redist_base) |
| 2176 | return -ENOMEM; | 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 | gic_acpi_register_redist(gicc->gicr_base_address, redist_base); | 2200 | gic_acpi_register_redist(gicc->gicr_base_address, redist_base); |
| 2180 | return 0; | 2201 | return 0; |
| @@ -2376,7 +2397,7 @@ gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end) · 195 unmodified lines | |||
| 2376 | pr_err("Unable to map GICD registers\n"); | 2397 | pr_err("Unable to map GICD registers\n"); |
| 2377 | return -ENOMEM; | 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 | err = gic_validate_dist_version(acpi_data.dist_base); | 2402 | err = gic_validate_dist_version(acpi_data.dist_base); |
| 2382 | if (err) { | 2403 | if (err) { |