^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/kernel/resource.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1999 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1999 Martin Mares <mj@ucw.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Arbitrary resource management.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/pfn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/resource_ext.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct resource ioport_resource = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .name = "PCI IO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .start = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .end = IO_SPACE_LIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .flags = IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) EXPORT_SYMBOL(ioport_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct resource iomem_resource = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .name = "PCI mem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .start = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .end = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) EXPORT_SYMBOL(iomem_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* constraints to be met while allocating resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct resource_constraint {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) resource_size_t min, max, align;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) resource_size_t (*alignf)(void *, const struct resource *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) resource_size_t, resource_size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) void *alignf_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static DEFINE_RWLOCK(resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * For memory hotplug, there is no way to free resource entries allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * by boot mem after the system is up. So for reusing the resource entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * we need to remember the resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static struct resource *bootmem_resource_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static DEFINE_SPINLOCK(bootmem_resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static struct resource *next_resource(struct resource *p, bool sibling_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* Caller wants to traverse through siblings only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (sibling_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return p->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (p->child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return p->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) while (!p->sibling && p->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) p = p->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return p->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static void *r_next(struct seq_file *m, void *v, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct resource *p = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) (*pos)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return (void *)next_resource(p, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) enum { MAX_IORES_LEVEL = 5 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void *r_start(struct seq_file *m, loff_t *pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) __acquires(resource_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct resource *p = PDE_DATA(file_inode(m->file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) loff_t l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) read_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) for (p = p->child; p && l < *pos; p = r_next(m, p, &l))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static void r_stop(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) __releases(resource_lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) read_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int r_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct resource *root = PDE_DATA(file_inode(m->file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct resource *r = v, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned long long start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int width = root->end < 0x10000 ? 4 : 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (p->parent == root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (file_ns_capable(m->file, &init_user_ns, CAP_SYS_ADMIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) start = r->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) end = r->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) start = end = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) seq_printf(m, "%*s%0*llx-%0*llx : %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) depth * 2, "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) width, start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) width, end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) r->name ? r->name : "<BAD>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static const struct seq_operations resource_op = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .start = r_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .next = r_next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .stop = r_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .show = r_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int __init ioresources_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) proc_create_seq_data("ioports", 0, NULL, &resource_op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) &ioport_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) proc_create_seq_data("iomem", 0, NULL, &resource_op, &iomem_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) __initcall(ioresources_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #endif /* CONFIG_PROC_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static void free_resource(struct resource *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!PageSlab(virt_to_head_page(res))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) spin_lock(&bootmem_resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) res->sibling = bootmem_resource_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) bootmem_resource_free = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) spin_unlock(&bootmem_resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static struct resource *alloc_resource(gfp_t flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct resource *res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) spin_lock(&bootmem_resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (bootmem_resource_free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) res = bootmem_resource_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) bootmem_resource_free = res->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) spin_unlock(&bootmem_resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) memset(res, 0, sizeof(struct resource));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) res = kzalloc(sizeof(struct resource), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /* Return the conflict entry if you can't request it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static struct resource * __request_resource(struct resource *root, struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) resource_size_t start = new->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) resource_size_t end = new->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct resource *tmp, **p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (end < start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (start < root->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (end > root->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) p = &root->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) tmp = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!tmp || tmp->start > end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) new->sibling = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) *p = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) new->parent = root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) p = &tmp->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (tmp->end < start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int __release_resource(struct resource *old, bool release_child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct resource *tmp, **p, *chd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) p = &old->parent->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) tmp = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (tmp == old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (release_child || !(tmp->child)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *p = tmp->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) for (chd = tmp->child;; chd = chd->sibling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) chd->parent = tmp->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!(chd->sibling))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *p = tmp->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) chd->sibling = tmp->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) old->parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) p = &tmp->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static void __release_child_resources(struct resource *r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct resource *tmp, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) resource_size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) p = r->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) r->child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) while (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) tmp = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) p = p->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) tmp->parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) tmp->sibling = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) __release_child_resources(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) printk(KERN_DEBUG "release child resource %pR\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* need to restore size, and keep flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) size = resource_size(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) tmp->start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) tmp->end = size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) void release_child_resources(struct resource *r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) __release_child_resources(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * request_resource_conflict - request and reserve an I/O or memory resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * @root: root resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * @new: resource descriptor desired by caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * Returns 0 for success, conflict resource on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct resource *request_resource_conflict(struct resource *root, struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct resource *conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) conflict = __request_resource(root, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * request_resource - request and reserve an I/O or memory resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * @root: root resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * @new: resource descriptor desired by caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * Returns 0 for success, negative error code on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int request_resource(struct resource *root, struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct resource *conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) conflict = request_resource_conflict(root, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return conflict ? -EBUSY : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) EXPORT_SYMBOL(request_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * release_resource - release a previously reserved resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * @old: resource pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int release_resource(struct resource *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) retval = __release_resource(old, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) EXPORT_SYMBOL(release_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * Finds the lowest iomem resource that covers part of [@start..@end]. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * caller must specify @start, @end, @flags, and @desc (which may be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * IORES_DESC_NONE).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * If a resource is found, returns 0 and @*res is overwritten with the part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * of the resource that's within [@start..@end]; if none is found, returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * -ENODEV. Returns -EINVAL for invalid parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * This function walks the whole tree and not just first level children
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * unless @first_lvl is true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * @start: start address of the resource searched for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) * @end: end address of same resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * @flags: flags which the resource must have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * @desc: descriptor the resource must have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * @first_lvl: walk only the first level children, if set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * @res: return ptr, if resource found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static int find_next_iomem_res(resource_size_t start, resource_size_t end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) unsigned long flags, unsigned long desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) bool first_lvl, struct resource *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) bool siblings_only = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct resource *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (start >= end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) read_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) for (p = iomem_resource.child; p; p = next_resource(p, siblings_only)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* If we passed the resource we are looking for, stop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (p->start > end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Skip until we find a range that matches what we look for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (p->end < start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * Now that we found a range that matches what we look for,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * check the flags and the descriptor. If we were not asked to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * use only the first level, start looking at children as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) siblings_only = first_lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if ((p->flags & flags) != flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if ((desc != IORES_DESC_NONE) && (desc != p->desc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* Found a match, break */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /* copy data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) *res = (struct resource) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .start = max(start, p->start),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .end = min(end, p->end),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .flags = p->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .desc = p->desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) .parent = p->parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) read_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return p ? 0 : -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned long flags, unsigned long desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) bool first_lvl, void *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int (*func)(struct resource *, void *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) while (start < end &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) !find_next_iomem_res(start, end, flags, desc, first_lvl, &res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) ret = (*func)(&res, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) start = res.end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * Walks through iomem resources and calls func() with matching resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * ranges. This walks through whole tree and not just first level children.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * All the memory ranges which overlap start,end and also match flags and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * desc are valid candidates.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * @desc: I/O resource descriptor. Use IORES_DESC_NONE to skip @desc check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * @flags: I/O resource flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * @start: start addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * @end: end addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * @arg: function argument for the callback @func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * @func: callback function that is called for each qualifying resource area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * NOTE: For a new descriptor search, define a new IORES_DESC in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * <linux/ioport.h> and set it in 'desc' of a target resource entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) u64 end, void *arg, int (*func)(struct resource *, void *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return __walk_iomem_res_desc(start, end, flags, desc, false, arg, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) EXPORT_SYMBOL_GPL(walk_iomem_res_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * This function calls the @func callback against all memory ranges of type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * Now, this function is only for System RAM, it deals with full ranges and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * not PFNs. If resources are not PFN-aligned, dealing with PFNs can truncate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * ranges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int walk_system_ram_res(u64 start, u64 end, void *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int (*func)(struct resource *, void *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) arg, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * This function calls the @func callback against all memory ranges, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * are ranges marked as IORESOURCE_MEM and IORESOUCE_BUSY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int walk_mem_res(u64 start, u64 end, void *arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int (*func)(struct resource *, void *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) arg, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * This function calls the @func callback against all memory ranges of type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * It is to be used only for System RAM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * This will find System RAM ranges that are children of top-level resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * in addition to top-level System RAM resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) void *arg, int (*func)(unsigned long, unsigned long, void *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) resource_size_t start, end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) unsigned long pfn, end_pfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) start = (u64) start_pfn << PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) while (start < end &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) !find_next_iomem_res(start, end, flags, IORES_DESC_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) false, &res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) pfn = PFN_UP(res.start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) end_pfn = PFN_DOWN(res.end + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (end_pfn > pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ret = (*func)(pfn, end_pfn - pfn, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) start = res.end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * This generic page_is_ram() returns true if specified address is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * registered as System RAM in iomem_resource list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) int __weak page_is_ram(unsigned long pfn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) EXPORT_SYMBOL_GPL(page_is_ram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * region_intersects() - determine intersection of region with known resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * @start: region start address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * @size: size of region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * @flags: flags of resource (in iomem_resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * @desc: descriptor of resource (in iomem_resource) or IORES_DESC_NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * Check if the specified region partially overlaps or fully eclipses a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * resource identified by @flags and @desc (optional with IORES_DESC_NONE).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * Return REGION_DISJOINT if the region does not overlap @flags/@desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * return REGION_MIXED if the region overlaps @flags/@desc and another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * resource, and return REGION_INTERSECTS if the region overlaps @flags/@desc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * and no other defined resource. Note that REGION_INTERSECTS is also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * returned in the case when the specified region overlaps RAM and undefined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * memory holes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * region_intersect() is used by memory remapping functions to ensure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * the user is not remapping RAM and is a vast speed up over walking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * through the resource table page by page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int region_intersects(resource_size_t start, size_t size, unsigned long flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) unsigned long desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int type = 0; int other = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct resource *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) res.start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) res.end = start + size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) read_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) for (p = iomem_resource.child; p ; p = p->sibling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) bool is_type = (((p->flags & flags) == flags) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ((desc == IORES_DESC_NONE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) (desc == p->desc)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (resource_overlaps(p, &res))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) is_type ? type++ : other++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) read_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (other == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return type ? REGION_INTERSECTS : REGION_DISJOINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return REGION_MIXED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return REGION_DISJOINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) EXPORT_SYMBOL_GPL(region_intersects);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) void __weak arch_remove_reservations(struct resource *avail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static resource_size_t simple_align_resource(void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) const struct resource *avail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) resource_size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) resource_size_t align)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return avail->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static void resource_clip(struct resource *res, resource_size_t min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) resource_size_t max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (res->start < min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) res->start = min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (res->end > max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) res->end = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * Find empty slot in the resource tree with the given range and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * alignment constraints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static int __find_resource(struct resource *root, struct resource *old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct resource *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) resource_size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct resource_constraint *constraint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct resource *this = root->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct resource tmp = *new, avail, alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) tmp.start = root->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * Skip past an allocated resource that starts at 0, since the assignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * of this->start - 1 to tmp->end below would cause an underflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (this && this->start == root->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) tmp.start = (this == old) ? old->start : this->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) this = this->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) for(;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (this)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) tmp.end = (this == old) ? this->end : this->start - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) tmp.end = root->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (tmp.end < tmp.start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) resource_clip(&tmp, constraint->min, constraint->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) arch_remove_reservations(&tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /* Check for overflow after ALIGN() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) avail.start = ALIGN(tmp.start, constraint->align);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) avail.end = tmp.end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) avail.flags = new->flags & ~IORESOURCE_UNSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (avail.start >= tmp.start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) alloc.flags = avail.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) alloc.start = constraint->alignf(constraint->alignf_data, &avail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) size, constraint->align);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) alloc.end = alloc.start + size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (alloc.start <= alloc.end &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) resource_contains(&avail, &alloc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) new->start = alloc.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) new->end = alloc.end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) next: if (!this || this->end == root->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (this != old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) tmp.start = this->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) this = this->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * Find empty slot in the resource tree given range and alignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) static int find_resource(struct resource *root, struct resource *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) resource_size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct resource_constraint *constraint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return __find_resource(root, NULL, new, size, constraint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * reallocate_resource - allocate a slot in the resource tree given range & alignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * The resource will be relocated if the new size cannot be reallocated in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * current location.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * @root: root resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * @old: resource descriptor desired by caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * @newsize: new size of the resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * @constraint: the size and alignment constraints to be met.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) static int reallocate_resource(struct resource *root, struct resource *old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) resource_size_t newsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct resource_constraint *constraint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) int err=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct resource new = *old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) struct resource *conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if ((err = __find_resource(root, old, &new, newsize, constraint)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (resource_contains(&new, old)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) old->start = new.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) old->end = new.end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (old->child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (resource_contains(old, &new)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) old->start = new.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) old->end = new.end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) __release_resource(old, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) *old = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) conflict = __request_resource(root, old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) BUG_ON(conflict);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * allocate_resource - allocate empty slot in the resource tree given range & alignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * The resource will be reallocated with a new size if it was already allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * @root: root resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * @new: resource descriptor desired by caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * @size: requested resource region size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * @min: minimum boundary to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * @max: maximum boundary to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * @align: alignment requested, in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * @alignf: alignment function, optional, called if not NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * @alignf_data: arbitrary data to pass to the @alignf function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int allocate_resource(struct resource *root, struct resource *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) resource_size_t size, resource_size_t min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) resource_size_t max, resource_size_t align,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) resource_size_t (*alignf)(void *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) const struct resource *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) resource_size_t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) resource_size_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) void *alignf_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct resource_constraint constraint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (!alignf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) alignf = simple_align_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) constraint.min = min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) constraint.max = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) constraint.align = align;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) constraint.alignf = alignf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) constraint.alignf_data = alignf_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if ( new->parent ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* resource is already allocated, try reallocating with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) the new constraints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return reallocate_resource(root, new, size, &constraint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) err = find_resource(root, new, size, &constraint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) if (err >= 0 && __request_resource(root, new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) EXPORT_SYMBOL(allocate_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) * lookup_resource - find an existing resource by a resource start address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * @root: root resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * @start: resource start address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * Returns a pointer to the resource if found, NULL otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct resource *lookup_resource(struct resource *root, resource_size_t start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) read_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) for (res = root->child; res; res = res->sibling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (res->start == start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) read_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * Insert a resource into the resource tree. If successful, return NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * otherwise return the conflicting resource (compare to __request_resource())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static struct resource * __insert_resource(struct resource *parent, struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) struct resource *first, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) for (;; parent = first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) first = __request_resource(parent, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (first == parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (WARN_ON(first == new)) /* duplicated insertion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if ((first->start > new->start) || (first->end < new->end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if ((first->start == new->start) && (first->end == new->end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) for (next = first; ; next = next->sibling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /* Partial overlap? Bad, and unfixable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (next->start < new->start || next->end > new->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) return next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (!next->sibling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (next->sibling->start > new->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) new->parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) new->sibling = next->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) new->child = first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) next->sibling = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) for (next = first; next; next = next->sibling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) next->parent = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (parent->child == first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) parent->child = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) next = parent->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) while (next->sibling != first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) next = next->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) next->sibling = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * insert_resource_conflict - Inserts resource in the resource tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * @parent: parent of the new resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) * @new: new resource to insert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * Returns 0 on success, conflict resource if the resource can't be inserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * This function is equivalent to request_resource_conflict when no conflict
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * happens. If a conflict happens, and the conflicting resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * entirely fit within the range of the new resource, then the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) * resource is inserted and the conflicting resources become children of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * the new resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * This function is intended for producers of resources, such as FW modules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * and bus drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct resource *insert_resource_conflict(struct resource *parent, struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct resource *conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) conflict = __insert_resource(parent, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * insert_resource - Inserts a resource in the resource tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * @parent: parent of the new resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * @new: new resource to insert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * Returns 0 on success, -EBUSY if the resource can't be inserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * This function is intended for producers of resources, such as FW modules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * and bus drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int insert_resource(struct resource *parent, struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct resource *conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) conflict = insert_resource_conflict(parent, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return conflict ? -EBUSY : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) EXPORT_SYMBOL_GPL(insert_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * insert_resource_expand_to_fit - Insert a resource into the resource tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * @root: root resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * @new: new resource to insert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * Insert a resource into the resource tree, possibly expanding it in order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * to make it encompass any conflicting resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) void insert_resource_expand_to_fit(struct resource *root, struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (new->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct resource *conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) conflict = __insert_resource(root, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (!conflict)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (conflict == root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* Ok, expand resource to cover the conflict, then try again .. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (conflict->start < new->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) new->start = conflict->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (conflict->end > new->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) new->end = conflict->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) printk("Expanded resource %s due to conflict with %s\n", new->name, conflict->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * remove_resource - Remove a resource in the resource tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * @old: resource to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * Returns 0 on success, -EINVAL if the resource is not valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * This function removes a resource previously inserted by insert_resource()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * or insert_resource_conflict(), and moves the children (if any) up to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * where they were before. insert_resource() and insert_resource_conflict()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * insert a new resource, and move any conflicting resources down to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * children of the new resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * insert_resource(), insert_resource_conflict() and remove_resource() are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * intended for producers of resources, such as FW modules and bus drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) int remove_resource(struct resource *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) retval = __release_resource(old, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) EXPORT_SYMBOL_GPL(remove_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static int __adjust_resource(struct resource *res, resource_size_t start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) resource_size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct resource *tmp, *parent = res->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) resource_size_t end = start + size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) int result = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if ((start < parent->start) || (end > parent->end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (res->sibling && (res->sibling->start <= end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) tmp = parent->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (tmp != res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) while (tmp->sibling != res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) tmp = tmp->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (start <= tmp->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) for (tmp = res->child; tmp; tmp = tmp->sibling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if ((tmp->start < start) || (tmp->end > end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) res->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) res->end = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) * adjust_resource - modify a resource's start and size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) * @res: resource to modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * @start: new start value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * @size: new size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * Given an existing resource, change its start and size to match the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) * arguments. Returns 0 on success, -EBUSY if it can't fit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) * Existing children of the resource are assumed to be immutable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) int adjust_resource(struct resource *res, resource_size_t start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) resource_size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) result = __adjust_resource(res, start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) EXPORT_SYMBOL(adjust_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) __reserve_region_with_split(struct resource *root, resource_size_t start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) resource_size_t end, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) struct resource *parent = root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) struct resource *conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) struct resource *res = alloc_resource(GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct resource *next_res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) int type = resource_type(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) res->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) res->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) res->end = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) res->flags = type | IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) res->desc = IORES_DESC_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) conflict = __request_resource(parent, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (!conflict) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (!next_res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) res = next_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) next_res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /* conflict covered whole area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (conflict->start <= res->start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) conflict->end >= res->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) free_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) WARN_ON(next_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) /* failed, split and try again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (conflict->start > res->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) end = res->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) res->end = conflict->start - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (conflict->end < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) next_res = alloc_resource(GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (!next_res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) free_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) next_res->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) next_res->start = conflict->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) next_res->end = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) next_res->flags = type | IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) next_res->desc = IORES_DESC_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) res->start = conflict->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) reserve_region_with_split(struct resource *root, resource_size_t start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) resource_size_t end, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) int abort = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) if (root->start > start || root->end < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) pr_err("requested range [0x%llx-0x%llx] not in root %pr\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) (unsigned long long)start, (unsigned long long)end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (start > root->end || end < root->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) abort = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (end > root->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) end = root->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (start < root->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) start = root->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) pr_err("fixing request to [0x%llx-0x%llx]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) (unsigned long long)start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) (unsigned long long)end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) dump_stack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (!abort)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) __reserve_region_with_split(root, start, end, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) * resource_alignment - calculate resource's alignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) * @res: resource pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) * Returns alignment on success, 0 (invalid alignment) on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) resource_size_t resource_alignment(struct resource *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) switch (res->flags & (IORESOURCE_SIZEALIGN | IORESOURCE_STARTALIGN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) case IORESOURCE_SIZEALIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) return resource_size(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) case IORESOURCE_STARTALIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) * This is compatibility stuff for IO resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) * Note how this, unlike the above, knows about
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) * the IO flag meanings (busy etc).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) * request_region creates a new busy region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * release_region releases a matching busy region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * __request_region - create a new busy resource region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) * @parent: parent resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * @start: resource start address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) * @n: resource region size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * @name: reserving caller's ID string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * @flags: IO resource flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) struct resource * __request_region(struct resource *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) resource_size_t start, resource_size_t n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) const char *name, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) struct resource *res = alloc_resource(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct resource *orig_parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) res->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) res->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) res->end = start + n - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) struct resource *conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) res->flags = resource_type(parent) | resource_ext_type(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) res->flags |= IORESOURCE_BUSY | flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) res->desc = parent->desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) conflict = __request_resource(parent, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (!conflict)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) * mm/hmm.c reserves physical addresses which then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) * become unavailable to other users. Conflicts are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) * not expected. Warn to aid debugging if encountered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (conflict->desc == IORES_DESC_DEVICE_PRIVATE_MEMORY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) pr_warn("Unaddressable device %s %pR conflicts with %pR",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) conflict->name, conflict, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (conflict != parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (!(conflict->flags & IORESOURCE_BUSY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) parent = conflict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (conflict->flags & flags & IORESOURCE_MUXED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) add_wait_queue(&muxed_resource_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) set_current_state(TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) remove_wait_queue(&muxed_resource_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) /* Uhhuh, that didn't work out.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) free_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (res && orig_parent == &iomem_resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) revoke_devmem(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) EXPORT_SYMBOL(__request_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) * __release_region - release a previously reserved resource region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) * @parent: parent resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) * @start: resource start address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) * @n: resource region size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) * The described resource region must match a currently busy region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) void __release_region(struct resource *parent, resource_size_t start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) resource_size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) struct resource **p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) resource_size_t end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) p = &parent->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) end = start + n - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) struct resource *res = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (res->start <= start && res->end >= end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (!(res->flags & IORESOURCE_BUSY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) p = &res->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (res->start != start || res->end != end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) *p = res->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (res->flags & IORESOURCE_MUXED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) wake_up(&muxed_resource_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) free_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) p = &res->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) printk(KERN_WARNING "Trying to free nonexistent resource "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) "<%016llx-%016llx>\n", (unsigned long long)start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) (unsigned long long)end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) EXPORT_SYMBOL(__release_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) #ifdef CONFIG_MEMORY_HOTREMOVE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) * release_mem_region_adjustable - release a previously reserved memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * @start: resource start address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) * @size: resource region size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * This interface is intended for memory hot-delete. The requested region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) * is released from a currently busy memory resource. The requested region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) * must either match exactly or fit into a single busy resource entry. In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) * the latter case, the remaining resource is adjusted accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * Existing children of the busy memory resource must be immutable in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) * request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * - Additional release conditions, such as overlapping region, can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * supported after they are confirmed as valid cases.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * - When a busy memory resource gets split into two entries, the code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * assumes that all children remain in the lower address entry for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * simplicity. Enhance this logic when necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) void release_mem_region_adjustable(resource_size_t start, resource_size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) struct resource *parent = &iomem_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) struct resource *new_res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) bool alloc_nofail = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) struct resource **p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) resource_size_t end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) end = start + size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (WARN_ON_ONCE((start < parent->start) || (end > parent->end)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * We free up quite a lot of memory on memory hotunplug (esp., memap),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * just before releasing the region. This is highly unlikely to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * fail - let's play save and make it never fail as the caller cannot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) * perform any error handling (e.g., trying to re-add memory will fail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) * similarly).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) new_res = alloc_resource(GFP_KERNEL | (alloc_nofail ? __GFP_NOFAIL : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) p = &parent->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) while ((res = *p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (res->start >= end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) /* look for the next resource if it does not fit into */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) if (res->start > start || res->end < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) p = &res->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * All memory regions added from memory-hotplug path have the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) * flag IORESOURCE_SYSTEM_RAM. If the resource does not have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * this flag, we know that we are dealing with a resource coming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) * from HMM/devm. HMM/devm use another mechanism to add/release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * a resource. This goes via devm_request_mem_region and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) * devm_release_mem_region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) * HMM/devm take care to release their resources when they want,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) * so if we are dealing with them, let us just back off here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (!(res->flags & IORESOURCE_SYSRAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (!(res->flags & IORESOURCE_MEM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (!(res->flags & IORESOURCE_BUSY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) p = &res->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) /* found the target resource; let's adjust accordingly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) if (res->start == start && res->end == end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) /* free the whole entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) *p = res->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) free_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) } else if (res->start == start && res->end != end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) /* adjust the start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) WARN_ON_ONCE(__adjust_resource(res, end + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) res->end - end));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) } else if (res->start != start && res->end == end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) /* adjust the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) WARN_ON_ONCE(__adjust_resource(res, res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) start - res->start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /* split into two entries - we need a new resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) if (!new_res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) new_res = alloc_resource(GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (!new_res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) alloc_nofail = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) new_res->name = res->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) new_res->start = end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) new_res->end = res->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) new_res->flags = res->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) new_res->desc = res->desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) new_res->parent = res->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) new_res->sibling = res->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) new_res->child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (WARN_ON_ONCE(__adjust_resource(res, res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) start - res->start)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) res->sibling = new_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) new_res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) free_resource(new_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) #endif /* CONFIG_MEMORY_HOTREMOVE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) #ifdef CONFIG_MEMORY_HOTPLUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) static bool system_ram_resources_mergeable(struct resource *r1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) struct resource *r2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /* We assume either r1 or r2 is IORESOURCE_SYSRAM_MERGEABLE. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return r1->flags == r2->flags && r1->end + 1 == r2->start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) r1->name == r2->name && r1->desc == r2->desc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) !r1->child && !r2->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) * merge_system_ram_resource - mark the System RAM resource mergeable and try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) * merge it with adjacent, mergeable resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * @res: resource descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * This interface is intended for memory hotplug, whereby lots of contiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * system ram resources are added (e.g., via add_memory*()) by a driver, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * the actual resource boundaries are not of interest (e.g., it might be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * relevant for DIMMs). Only resources that are marked mergeable, that have the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * same parent, and that don't have any children are considered. All mergeable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) * resources must be immutable during the request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * - The caller has to make sure that no pointers to resources that are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * marked mergeable are used anymore after this call - the resource might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) * be freed and the pointer might be stale!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * - release_mem_region_adjustable() will split on demand on memory hotunplug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) void merge_system_ram_resource(struct resource *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) const unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) struct resource *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) if (WARN_ON_ONCE((res->flags & flags) != flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) write_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) res->flags |= IORESOURCE_SYSRAM_MERGEABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /* Try to merge with next item in the list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) cur = res->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) if (cur && system_ram_resources_mergeable(res, cur)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) res->end = cur->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) res->sibling = cur->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) free_resource(cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) /* Try to merge with previous item in the list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) cur = res->parent->child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) while (cur && cur->sibling != res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) cur = cur->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) if (cur && system_ram_resources_mergeable(cur, res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) cur->end = res->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) cur->sibling = res->sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) free_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) write_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) #endif /* CONFIG_MEMORY_HOTPLUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * Managed region resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) static void devm_resource_release(struct device *dev, void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) struct resource **r = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) release_resource(*r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) * devm_request_resource() - request and reserve an I/O or memory resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) * @dev: device for which to request the resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) * @root: root of the resource tree from which to request the resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) * @new: descriptor of the resource to request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) * This is a device-managed version of request_resource(). There is usually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) * no need to release resources requested by this function explicitly since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) * that will be taken care of when the device is unbound from its driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) * If for some reason the resource needs to be released explicitly, because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) * of ordering issues for example, drivers must call devm_release_resource()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) * rather than the regular release_resource().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) * When a conflict is detected between any existing resources and the newly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) * requested resource, an error message will be printed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) * Returns 0 on success or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) int devm_request_resource(struct device *dev, struct resource *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) struct resource *conflict, **ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) ptr = devres_alloc(devm_resource_release, sizeof(*ptr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if (!ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) *ptr = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) conflict = request_resource_conflict(root, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) if (conflict) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) dev_err(dev, "resource collision: %pR conflicts with %s %pR\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) new, conflict->name, conflict);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) devres_free(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) devres_add(dev, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) EXPORT_SYMBOL(devm_request_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) static int devm_resource_match(struct device *dev, void *res, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) struct resource **ptr = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) return *ptr == data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) * devm_release_resource() - release a previously requested resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) * @dev: device for which to release the resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) * @new: descriptor of the resource to release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) * Releases a resource previously requested using devm_request_resource().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) void devm_release_resource(struct device *dev, struct resource *new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) WARN_ON(devres_release(dev, devm_resource_release, devm_resource_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) EXPORT_SYMBOL(devm_release_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) struct region_devres {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) struct resource *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) resource_size_t start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) resource_size_t n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) static void devm_region_release(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) struct region_devres *this = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) __release_region(this->parent, this->start, this->n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) static int devm_region_match(struct device *dev, void *res, void *match_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) struct region_devres *this = res, *match = match_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) return this->parent == match->parent &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) this->start == match->start && this->n == match->n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) struct resource *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) __devm_request_region(struct device *dev, struct resource *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) resource_size_t start, resource_size_t n, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) struct region_devres *dr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) dr = devres_alloc(devm_region_release, sizeof(struct region_devres),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) if (!dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) dr->parent = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) dr->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) dr->n = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) res = __request_region(parent, start, n, name, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) devres_add(dev, dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) devres_free(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) EXPORT_SYMBOL(__devm_request_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) void __devm_release_region(struct device *dev, struct resource *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) resource_size_t start, resource_size_t n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) struct region_devres match_data = { parent, start, n };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) __release_region(parent, start, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) WARN_ON(devres_destroy(dev, devm_region_release, devm_region_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) &match_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) EXPORT_SYMBOL(__devm_release_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) * Reserve I/O ports or memory based on "reserve=" kernel parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) #define MAXRESERVE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) static int __init reserve_setup(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) static int reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) static struct resource reserve[MAXRESERVE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) unsigned int io_start, io_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) int x = reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) struct resource *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) if (get_option(&str, &io_start) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (get_option(&str, &io_num) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) if (x < MAXRESERVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) struct resource *res = reserve + x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) * If the region starts below 0x10000, we assume it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) * I/O port space; otherwise assume it's memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) if (io_start < 0x10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) res->flags = IORESOURCE_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) parent = &ioport_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) res->flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) parent = &iomem_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) res->name = "reserved";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) res->start = io_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) res->end = io_start + io_num - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) res->flags |= IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) res->desc = IORES_DESC_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) res->child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) if (request_resource(parent, res) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) reserved = x+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) __setup("reserve=", reserve_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) * Check if the requested addr and size spans more than any slot in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) * iomem resource tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) int iomem_map_sanity_check(resource_size_t addr, unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) struct resource *p = &iomem_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) loff_t l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) read_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) for (p = p->child; p ; p = r_next(NULL, p, &l)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) * We can probably skip the resources without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) * IORESOURCE_IO attribute?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (p->start >= addr + size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) if (p->end < addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) if (PFN_DOWN(p->start) <= PFN_DOWN(addr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) PFN_DOWN(p->end) >= PFN_DOWN(addr + size - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) * if a resource is "BUSY", it's not a hardware resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) * but a driver mapping of such a resource; we don't want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) * to warn for those; some drivers legitimately map only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) * partial hardware resources. (example: vesafb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (p->flags & IORESOURCE_BUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) printk(KERN_WARNING "resource sanity check: requesting [mem %#010llx-%#010llx], which spans more than %s %pR\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) (unsigned long long)addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) (unsigned long long)(addr + size - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) p->name, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) err = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) read_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) #ifdef CONFIG_STRICT_DEVMEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) static int strict_iomem_checks = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) static int strict_iomem_checks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) * check if an address is reserved in the iomem resource tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * returns true if reserved, false if not reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) bool iomem_is_exclusive(u64 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) struct resource *p = &iomem_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) bool err = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) loff_t l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) int size = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) if (!strict_iomem_checks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) addr = addr & PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) read_lock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) for (p = p->child; p ; p = r_next(NULL, p, &l)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) * We can probably skip the resources without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) * IORESOURCE_IO attribute?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (p->start >= addr + size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (p->end < addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) * A resource is exclusive if IORESOURCE_EXCLUSIVE is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) * or CONFIG_IO_STRICT_DEVMEM is enabled and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) * resource is busy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) if ((p->flags & IORESOURCE_BUSY) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) if (IS_ENABLED(CONFIG_IO_STRICT_DEVMEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) || p->flags & IORESOURCE_EXCLUSIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) err = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) read_unlock(&resource_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) struct resource_entry *resource_list_create_entry(struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) size_t extra_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) struct resource_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) entry = kzalloc(sizeof(*entry) + extra_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) if (entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) INIT_LIST_HEAD(&entry->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) entry->res = res ? res : &entry->__res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) EXPORT_SYMBOL(resource_list_create_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) void resource_list_free(struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) struct resource_entry *entry, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) list_for_each_entry_safe(entry, tmp, head, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) resource_list_destroy_entry(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) EXPORT_SYMBOL(resource_list_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) #ifdef CONFIG_DEVICE_PRIVATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) static struct resource *__request_free_mem_region(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) struct resource *base, unsigned long size, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) resource_size_t end, addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) size = ALIGN(size, 1UL << PA_SECTION_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) end = min_t(unsigned long, base->end, (1UL << MAX_PHYSMEM_BITS) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) addr = end - size + 1UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) for (; addr > size && addr >= base->start; addr -= size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) if (region_intersects(addr, size, 0, IORES_DESC_NONE) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) REGION_DISJOINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) res = devm_request_mem_region(dev, addr, size, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) res = request_mem_region(addr, size, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) res->desc = IORES_DESC_DEVICE_PRIVATE_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) return ERR_PTR(-ERANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) * devm_request_free_mem_region - find free region for device private memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) * @dev: device struct to bind the resource to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) * @size: size in bytes of the device memory to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) * @base: resource tree to look in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) * This function tries to find an empty range of physical address big enough to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) * contain the new resource, so that it can later be hotplugged as ZONE_DEVICE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) * memory, which in turn allocates struct pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) struct resource *devm_request_free_mem_region(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) struct resource *base, unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) return __request_free_mem_region(dev, base, size, dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) EXPORT_SYMBOL_GPL(devm_request_free_mem_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) struct resource *request_free_mem_region(struct resource *base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) unsigned long size, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) return __request_free_mem_region(NULL, base, size, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) EXPORT_SYMBOL_GPL(request_free_mem_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) #endif /* CONFIG_DEVICE_PRIVATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) static int __init strict_iomem(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) if (strstr(str, "relaxed"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) strict_iomem_checks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) if (strstr(str, "strict"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) strict_iomem_checks = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) __setup("iomem=", strict_iomem);