Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Device tree based initialization code for reserved memory.
0004  *
0005  * Copyright (c) 2013, 2015 The Linux Foundation. All Rights Reserved.
0006  * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd.
0007  *      http://www.samsung.com
0008  * Author: Marek Szyprowski <m.szyprowski@samsung.com>
0009  * Author: Josh Cartwright <joshc@codeaurora.org>
0010  */
0011 
0012 #define pr_fmt(fmt) "OF: reserved mem: " fmt
0013 
0014 #include <linux/err.h>
0015 #include <linux/of.h>
0016 #include <linux/of_fdt.h>
0017 #include <linux/of_platform.h>
0018 #include <linux/mm.h>
0019 #include <linux/sizes.h>
0020 #include <linux/of_reserved_mem.h>
0021 #include <linux/sort.h>
0022 #include <linux/slab.h>
0023 #include <linux/memblock.h>
0024 #include <linux/kmemleak.h>
0025 #include <linux/cma.h>
0026 
0027 #include "of_private.h"
0028 
0029 #define MAX_RESERVED_REGIONS    64
0030 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
0031 static int reserved_mem_count;
0032 
0033 static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
0034     phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap,
0035     phys_addr_t *res_base)
0036 {
0037     phys_addr_t base;
0038     int err = 0;
0039 
0040     end = !end ? MEMBLOCK_ALLOC_ANYWHERE : end;
0041     align = !align ? SMP_CACHE_BYTES : align;
0042     base = memblock_phys_alloc_range(size, align, start, end);
0043     if (!base)
0044         return -ENOMEM;
0045 
0046     *res_base = base;
0047     if (nomap) {
0048         err = memblock_mark_nomap(base, size);
0049         if (err)
0050             memblock_phys_free(base, size);
0051         kmemleak_ignore_phys(base);
0052     }
0053 
0054     return err;
0055 }
0056 
0057 /*
0058  * fdt_reserved_mem_save_node() - save fdt node for second pass initialization
0059  */
0060 void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname,
0061                       phys_addr_t base, phys_addr_t size)
0062 {
0063     struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
0064 
0065     if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) {
0066         pr_err("not enough space for all defined regions.\n");
0067         return;
0068     }
0069 
0070     rmem->fdt_node = node;
0071     rmem->name = uname;
0072     rmem->base = base;
0073     rmem->size = size;
0074 
0075     reserved_mem_count++;
0076     return;
0077 }
0078 
0079 /*
0080  * __reserved_mem_alloc_size() - allocate reserved memory described by
0081  *  'size', 'alignment'  and 'alloc-ranges' properties.
0082  */
0083 static int __init __reserved_mem_alloc_size(unsigned long node,
0084     const char *uname, phys_addr_t *res_base, phys_addr_t *res_size)
0085 {
0086     int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
0087     phys_addr_t start = 0, end = 0;
0088     phys_addr_t base = 0, align = 0, size;
0089     int len;
0090     const __be32 *prop;
0091     bool nomap;
0092     int ret;
0093 
0094     prop = of_get_flat_dt_prop(node, "size", &len);
0095     if (!prop)
0096         return -EINVAL;
0097 
0098     if (len != dt_root_size_cells * sizeof(__be32)) {
0099         pr_err("invalid size property in '%s' node.\n", uname);
0100         return -EINVAL;
0101     }
0102     size = dt_mem_next_cell(dt_root_size_cells, &prop);
0103 
0104     prop = of_get_flat_dt_prop(node, "alignment", &len);
0105     if (prop) {
0106         if (len != dt_root_addr_cells * sizeof(__be32)) {
0107             pr_err("invalid alignment property in '%s' node.\n",
0108                 uname);
0109             return -EINVAL;
0110         }
0111         align = dt_mem_next_cell(dt_root_addr_cells, &prop);
0112     }
0113 
0114     nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
0115 
0116     /* Need adjust the alignment to satisfy the CMA requirement */
0117     if (IS_ENABLED(CONFIG_CMA)
0118         && of_flat_dt_is_compatible(node, "shared-dma-pool")
0119         && of_get_flat_dt_prop(node, "reusable", NULL)
0120         && !nomap)
0121         align = max_t(phys_addr_t, align, CMA_MIN_ALIGNMENT_BYTES);
0122 
0123     prop = of_get_flat_dt_prop(node, "alloc-ranges", &len);
0124     if (prop) {
0125 
0126         if (len % t_len != 0) {
0127             pr_err("invalid alloc-ranges property in '%s', skipping node.\n",
0128                    uname);
0129             return -EINVAL;
0130         }
0131 
0132         base = 0;
0133 
0134         while (len > 0) {
0135             start = dt_mem_next_cell(dt_root_addr_cells, &prop);
0136             end = start + dt_mem_next_cell(dt_root_size_cells,
0137                                &prop);
0138 
0139             ret = early_init_dt_alloc_reserved_memory_arch(size,
0140                     align, start, end, nomap, &base);
0141             if (ret == 0) {
0142                 pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
0143                     uname, &base,
0144                     (unsigned long)(size / SZ_1M));
0145                 break;
0146             }
0147             len -= t_len;
0148         }
0149 
0150     } else {
0151         ret = early_init_dt_alloc_reserved_memory_arch(size, align,
0152                             0, 0, nomap, &base);
0153         if (ret == 0)
0154             pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
0155                 uname, &base, (unsigned long)(size / SZ_1M));
0156     }
0157 
0158     if (base == 0) {
0159         pr_err("failed to allocate memory for node '%s': size %lu MiB\n",
0160                uname, (unsigned long)(size / SZ_1M));
0161         return -ENOMEM;
0162     }
0163 
0164     *res_base = base;
0165     *res_size = size;
0166 
0167     return 0;
0168 }
0169 
0170 static const struct of_device_id __rmem_of_table_sentinel
0171     __used __section("__reservedmem_of_table_end");
0172 
0173 /*
0174  * __reserved_mem_init_node() - call region specific reserved memory init code
0175  */
0176 static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
0177 {
0178     extern const struct of_device_id __reservedmem_of_table[];
0179     const struct of_device_id *i;
0180     int ret = -ENOENT;
0181 
0182     for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) {
0183         reservedmem_of_init_fn initfn = i->data;
0184         const char *compat = i->compatible;
0185 
0186         if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
0187             continue;
0188 
0189         ret = initfn(rmem);
0190         if (ret == 0) {
0191             pr_info("initialized node %s, compatible id %s\n",
0192                 rmem->name, compat);
0193             break;
0194         }
0195     }
0196     return ret;
0197 }
0198 
0199 static int __init __rmem_cmp(const void *a, const void *b)
0200 {
0201     const struct reserved_mem *ra = a, *rb = b;
0202 
0203     if (ra->base < rb->base)
0204         return -1;
0205 
0206     if (ra->base > rb->base)
0207         return 1;
0208 
0209     /*
0210      * Put the dynamic allocations (address == 0, size == 0) before static
0211      * allocations at address 0x0 so that overlap detection works
0212      * correctly.
0213      */
0214     if (ra->size < rb->size)
0215         return -1;
0216     if (ra->size > rb->size)
0217         return 1;
0218 
0219     return 0;
0220 }
0221 
0222 static void __init __rmem_check_for_overlap(void)
0223 {
0224     int i;
0225 
0226     if (reserved_mem_count < 2)
0227         return;
0228 
0229     sort(reserved_mem, reserved_mem_count, sizeof(reserved_mem[0]),
0230          __rmem_cmp, NULL);
0231     for (i = 0; i < reserved_mem_count - 1; i++) {
0232         struct reserved_mem *this, *next;
0233 
0234         this = &reserved_mem[i];
0235         next = &reserved_mem[i + 1];
0236 
0237         if (this->base + this->size > next->base) {
0238             phys_addr_t this_end, next_end;
0239 
0240             this_end = this->base + this->size;
0241             next_end = next->base + next->size;
0242             pr_err("OVERLAP DETECTED!\n%s (%pa--%pa) overlaps with %s (%pa--%pa)\n",
0243                    this->name, &this->base, &this_end,
0244                    next->name, &next->base, &next_end);
0245         }
0246     }
0247 }
0248 
0249 /**
0250  * fdt_init_reserved_mem() - allocate and init all saved reserved memory regions
0251  */
0252 void __init fdt_init_reserved_mem(void)
0253 {
0254     int i;
0255 
0256     /* check for overlapping reserved regions */
0257     __rmem_check_for_overlap();
0258 
0259     for (i = 0; i < reserved_mem_count; i++) {
0260         struct reserved_mem *rmem = &reserved_mem[i];
0261         unsigned long node = rmem->fdt_node;
0262         int len;
0263         const __be32 *prop;
0264         int err = 0;
0265         bool nomap;
0266 
0267         nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL;
0268         prop = of_get_flat_dt_prop(node, "phandle", &len);
0269         if (!prop)
0270             prop = of_get_flat_dt_prop(node, "linux,phandle", &len);
0271         if (prop)
0272             rmem->phandle = of_read_number(prop, len/4);
0273 
0274         if (rmem->size == 0)
0275             err = __reserved_mem_alloc_size(node, rmem->name,
0276                          &rmem->base, &rmem->size);
0277         if (err == 0) {
0278             err = __reserved_mem_init_node(rmem);
0279             if (err != 0 && err != -ENOENT) {
0280                 pr_info("node %s compatible matching fail\n",
0281                     rmem->name);
0282                 if (nomap)
0283                     memblock_clear_nomap(rmem->base, rmem->size);
0284                 else
0285                     memblock_phys_free(rmem->base,
0286                                rmem->size);
0287             }
0288         }
0289     }
0290 }
0291 
0292 static inline struct reserved_mem *__find_rmem(struct device_node *node)
0293 {
0294     unsigned int i;
0295 
0296     if (!node->phandle)
0297         return NULL;
0298 
0299     for (i = 0; i < reserved_mem_count; i++)
0300         if (reserved_mem[i].phandle == node->phandle)
0301             return &reserved_mem[i];
0302     return NULL;
0303 }
0304 
0305 struct rmem_assigned_device {
0306     struct device *dev;
0307     struct reserved_mem *rmem;
0308     struct list_head list;
0309 };
0310 
0311 static LIST_HEAD(of_rmem_assigned_device_list);
0312 static DEFINE_MUTEX(of_rmem_assigned_device_mutex);
0313 
0314 /**
0315  * of_reserved_mem_device_init_by_idx() - assign reserved memory region to
0316  *                    given device
0317  * @dev:    Pointer to the device to configure
0318  * @np:     Pointer to the device_node with 'reserved-memory' property
0319  * @idx:    Index of selected region
0320  *
0321  * This function assigns respective DMA-mapping operations based on reserved
0322  * memory region specified by 'memory-region' property in @np node to the @dev
0323  * device. When driver needs to use more than one reserved memory region, it
0324  * should allocate child devices and initialize regions by name for each of
0325  * child device.
0326  *
0327  * Returns error code or zero on success.
0328  */
0329 int of_reserved_mem_device_init_by_idx(struct device *dev,
0330                        struct device_node *np, int idx)
0331 {
0332     struct rmem_assigned_device *rd;
0333     struct device_node *target;
0334     struct reserved_mem *rmem;
0335     int ret;
0336 
0337     if (!np || !dev)
0338         return -EINVAL;
0339 
0340     target = of_parse_phandle(np, "memory-region", idx);
0341     if (!target)
0342         return -ENODEV;
0343 
0344     if (!of_device_is_available(target)) {
0345         of_node_put(target);
0346         return 0;
0347     }
0348 
0349     rmem = __find_rmem(target);
0350     of_node_put(target);
0351 
0352     if (!rmem || !rmem->ops || !rmem->ops->device_init)
0353         return -EINVAL;
0354 
0355     rd = kmalloc(sizeof(struct rmem_assigned_device), GFP_KERNEL);
0356     if (!rd)
0357         return -ENOMEM;
0358 
0359     ret = rmem->ops->device_init(rmem, dev);
0360     if (ret == 0) {
0361         rd->dev = dev;
0362         rd->rmem = rmem;
0363 
0364         mutex_lock(&of_rmem_assigned_device_mutex);
0365         list_add(&rd->list, &of_rmem_assigned_device_list);
0366         mutex_unlock(&of_rmem_assigned_device_mutex);
0367 
0368         dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
0369     } else {
0370         kfree(rd);
0371     }
0372 
0373     return ret;
0374 }
0375 EXPORT_SYMBOL_GPL(of_reserved_mem_device_init_by_idx);
0376 
0377 /**
0378  * of_reserved_mem_device_init_by_name() - assign named reserved memory region
0379  *                     to given device
0380  * @dev: pointer to the device to configure
0381  * @np: pointer to the device node with 'memory-region' property
0382  * @name: name of the selected memory region
0383  *
0384  * Returns: 0 on success or a negative error-code on failure.
0385  */
0386 int of_reserved_mem_device_init_by_name(struct device *dev,
0387                     struct device_node *np,
0388                     const char *name)
0389 {
0390     int idx = of_property_match_string(np, "memory-region-names", name);
0391 
0392     return of_reserved_mem_device_init_by_idx(dev, np, idx);
0393 }
0394 EXPORT_SYMBOL_GPL(of_reserved_mem_device_init_by_name);
0395 
0396 /**
0397  * of_reserved_mem_device_release() - release reserved memory device structures
0398  * @dev:    Pointer to the device to deconfigure
0399  *
0400  * This function releases structures allocated for memory region handling for
0401  * the given device.
0402  */
0403 void of_reserved_mem_device_release(struct device *dev)
0404 {
0405     struct rmem_assigned_device *rd, *tmp;
0406     LIST_HEAD(release_list);
0407 
0408     mutex_lock(&of_rmem_assigned_device_mutex);
0409     list_for_each_entry_safe(rd, tmp, &of_rmem_assigned_device_list, list) {
0410         if (rd->dev == dev)
0411             list_move_tail(&rd->list, &release_list);
0412     }
0413     mutex_unlock(&of_rmem_assigned_device_mutex);
0414 
0415     list_for_each_entry_safe(rd, tmp, &release_list, list) {
0416         if (rd->rmem && rd->rmem->ops && rd->rmem->ops->device_release)
0417             rd->rmem->ops->device_release(rd->rmem, dev);
0418 
0419         kfree(rd);
0420     }
0421 }
0422 EXPORT_SYMBOL_GPL(of_reserved_mem_device_release);
0423 
0424 /**
0425  * of_reserved_mem_lookup() - acquire reserved_mem from a device node
0426  * @np:     node pointer of the desired reserved-memory region
0427  *
0428  * This function allows drivers to acquire a reference to the reserved_mem
0429  * struct based on a device node handle.
0430  *
0431  * Returns a reserved_mem reference, or NULL on error.
0432  */
0433 struct reserved_mem *of_reserved_mem_lookup(struct device_node *np)
0434 {
0435     const char *name;
0436     int i;
0437 
0438     if (!np->full_name)
0439         return NULL;
0440 
0441     name = kbasename(np->full_name);
0442     for (i = 0; i < reserved_mem_count; i++)
0443         if (!strcmp(reserved_mem[i].name, name))
0444             return &reserved_mem[i];
0445 
0446     return NULL;
0447 }
0448 EXPORT_SYMBOL_GPL(of_reserved_mem_lookup);