Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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/drivers/firmware/memmap.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *  Copyright (C) 2008 SUSE LINUX Products GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  by Bernhard Walle <bernhard.walle@gmx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/firmware-map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * Data types ------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * Firmware map entry. Because firmware memory maps are flat and not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * hierarchical, it's ok to organise them in a linked list. No parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * information is necessary as for the resource tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) struct firmware_map_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	 * start and end must be u64 rather than resource_size_t, because e820
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	 * resources can lie at addresses above 4G.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	u64			start;	/* start of the memory range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	u64			end;	/* end of the memory range (incl.) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	const char		*type;	/* type of the memory range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	struct list_head	list;	/* entry for the linked list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	struct kobject		kobj;   /* kobject for each entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * Forward declarations --------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static ssize_t memmap_attr_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 				struct attribute *attr, char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static ssize_t start_show(struct firmware_map_entry *entry, char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static ssize_t end_show(struct firmware_map_entry *entry, char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static ssize_t type_show(struct firmware_map_entry *entry, char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static struct firmware_map_entry * __meminit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) firmware_map_find_entry(u64 start, u64 end, const char *type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * Static 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) struct memmap_attribute {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	ssize_t (*show)(struct firmware_map_entry *entry, char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static struct memmap_attribute memmap_start_attr = __ATTR_RO(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static struct memmap_attribute memmap_end_attr   = __ATTR_RO(end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static struct memmap_attribute memmap_type_attr  = __ATTR_RO(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * These are default attributes that are added for every memmap entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) static struct attribute *def_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	&memmap_start_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	&memmap_end_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	&memmap_type_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) static const struct sysfs_ops memmap_attr_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	.show = memmap_attr_show,
^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) /* Firmware memory map entries. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) static LIST_HEAD(map_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static DEFINE_SPINLOCK(map_entries_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * For memory hotplug, there is no way to free memory map entries allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * by boot mem after the system is up. So when we hot-remove memory whose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * map entry is allocated by bootmem, we need to remember the storage and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * reuse it when the memory is hot-added again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static LIST_HEAD(map_entries_bootmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static DEFINE_SPINLOCK(map_entries_bootmem_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) static inline struct firmware_map_entry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) to_memmap_entry(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	return container_of(kobj, struct firmware_map_entry, kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) static void __meminit release_firmware_map_entry(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	struct firmware_map_entry *entry = to_memmap_entry(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	if (PageReserved(virt_to_page(entry))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		 * Remember the storage allocated by bootmem, and reuse it when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		 * the memory is hot-added again. The entry will be added to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		 * map_entries_bootmem here, and deleted from &map_entries in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		 * firmware_map_remove_entry().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		spin_lock(&map_entries_bootmem_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		list_add(&entry->list, &map_entries_bootmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		spin_unlock(&map_entries_bootmem_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static struct kobj_type __refdata memmap_ktype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	.release	= release_firmware_map_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	.sysfs_ops	= &memmap_attr_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	.default_attrs	= def_attrs,
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * Registration functions ------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  * firmware_map_add_entry() - Does the real work to add a firmware memmap entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  * @start: Start of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  * @end:   End of the memory range (exclusive).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  * @type:  Type of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  * @entry: Pre-allocated (either kmalloc() or bootmem allocator), uninitialised
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)  *         entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  * Common implementation of firmware_map_add() and firmware_map_add_early()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)  * which expects a pre-allocated struct firmware_map_entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  * Return: 0 always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int firmware_map_add_entry(u64 start, u64 end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 				  const char *type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 				  struct firmware_map_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	BUG_ON(start > end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	entry->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	entry->end = end - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	entry->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	INIT_LIST_HEAD(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	kobject_init(&entry->kobj, &memmap_ktype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	spin_lock(&map_entries_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	list_add_tail(&entry->list, &map_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	spin_unlock(&map_entries_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  * firmware_map_remove_entry() - Does the real work to remove a firmware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  * memmap entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  * @entry: removed entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  * The caller must hold map_entries_lock, and release it properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static inline void firmware_map_remove_entry(struct firmware_map_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	list_del(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)  * Add memmap entry on sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	static int map_entries_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	static struct kset *mmap_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (entry->kobj.state_in_sysfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	if (!mmap_kset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		if (!mmap_kset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	entry->kobj.kset = mmap_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		kobject_put(&entry->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  * Remove memmap entry on sysfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static inline void remove_sysfs_fw_map_entry(struct firmware_map_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	kobject_put(&entry->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * firmware_map_find_entry_in_list() - Search memmap entry in a given list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  * @start: Start of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  * @end:   End of the memory range (exclusive).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  * @type:  Type of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)  * @list:  In which to find the entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)  * This function is to find the memmap entey of a given memory range in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  * given list. The caller must hold map_entries_lock, and must not release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  * the lock until the processing of the returned entry has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  * Return: Pointer to the entry to be found on success, or NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static struct firmware_map_entry * __meminit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) firmware_map_find_entry_in_list(u64 start, u64 end, const char *type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 				struct list_head *list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	struct firmware_map_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	list_for_each_entry(entry, list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		if ((entry->start == start) && (entry->end == end) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		    (!strcmp(entry->type, type))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)  * firmware_map_find_entry() - Search memmap entry in map_entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)  * @start: Start of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)  * @end:   End of the memory range (exclusive).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  * @type:  Type of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  * This function is to find the memmap entey of a given memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  * The caller must hold map_entries_lock, and must not release the lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  * until the processing of the returned entry has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  * Return: Pointer to the entry to be found on success, or NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static struct firmware_map_entry * __meminit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) firmware_map_find_entry(u64 start, u64 end, const char *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	return firmware_map_find_entry_in_list(start, end, type, &map_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  * firmware_map_find_entry_bootmem() - Search memmap entry in map_entries_bootmem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  * @start: Start of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)  * @end:   End of the memory range (exclusive).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  * @type:  Type of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  * This function is similar to firmware_map_find_entry except that it find the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  * given entry in map_entries_bootmem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)  * Return: Pointer to the entry to be found on success, or NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static struct firmware_map_entry * __meminit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) firmware_map_find_entry_bootmem(u64 start, u64 end, const char *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	return firmware_map_find_entry_in_list(start, end, type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 					       &map_entries_bootmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)  * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)  * memory hotplug.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)  * @start: Start of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)  * @end:   End of the memory range (exclusive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  * @type:  Type of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  * Adds a firmware mapping entry. This function is for memory hotplug, it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  * similar to function firmware_map_add_early(). The only difference is that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  * it will create the syfs entry dynamically.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  * Return: 0 on success, or -ENOMEM if no memory could be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	struct firmware_map_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	entry = firmware_map_find_entry(start, end - 1, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	entry = firmware_map_find_entry_bootmem(start, end - 1, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		/* Reuse storage allocated by bootmem. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		spin_lock(&map_entries_bootmem_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		list_del(&entry->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		spin_unlock(&map_entries_bootmem_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		memset(entry, 0, sizeof(*entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	firmware_map_add_entry(start, end, type, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	/* create the memmap entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	add_sysfs_fw_map_entry(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)  * firmware_map_add_early() - Adds a firmware mapping entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)  * @start: Start of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)  * @end:   End of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)  * @type:  Type of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)  * Adds a firmware mapping entry. This function uses the bootmem allocator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)  * for memory allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)  * That function must be called before late_initcall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  * Return: 0 on success, or -ENOMEM if no memory could be allocated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int __init firmware_map_add_early(u64 start, u64 end, const char *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	struct firmware_map_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	entry = memblock_alloc(sizeof(struct firmware_map_entry),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 			       SMP_CACHE_BYTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	if (WARN_ON(!entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	return firmware_map_add_entry(start, end, type, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  * firmware_map_remove() - remove a firmware mapping entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  * @start: Start of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)  * @end:   End of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)  * @type:  Type of the memory range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  * removes a firmware mapping entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)  * Return: 0 on success, or -EINVAL if no entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) int __meminit firmware_map_remove(u64 start, u64 end, const char *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	struct firmware_map_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	spin_lock(&map_entries_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	entry = firmware_map_find_entry(start, end - 1, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		spin_unlock(&map_entries_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	firmware_map_remove_entry(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	spin_unlock(&map_entries_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	/* remove the memmap entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	remove_sysfs_fw_map_entry(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)  * Sysfs functions -------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static ssize_t start_show(struct firmware_map_entry *entry, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	return snprintf(buf, PAGE_SIZE, "0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		(unsigned long long)entry->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static ssize_t end_show(struct firmware_map_entry *entry, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	return snprintf(buf, PAGE_SIZE, "0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		(unsigned long long)entry->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static ssize_t type_show(struct firmware_map_entry *entry, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	return snprintf(buf, PAGE_SIZE, "%s\n", entry->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static inline struct memmap_attribute *to_memmap_attr(struct attribute *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	return container_of(attr, struct memmap_attribute, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static ssize_t memmap_attr_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 				struct attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	struct firmware_map_entry *entry = to_memmap_entry(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	struct memmap_attribute *memmap_attr = to_memmap_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	return memmap_attr->show(entry, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)  * Initialises stuff and adds the entries in the map_entries list to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)  * sysfs. Important is that firmware_map_add() and firmware_map_add_early()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)  * must be called before late_initcall. That's just because that function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)  * is called as late_initcall() function, which means that if you call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)  * firmware_map_add() or firmware_map_add_early() afterwards, the entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)  * are not added to sysfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int __init firmware_memmap_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	struct firmware_map_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	list_for_each_entry(entry, &map_entries, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		add_sysfs_fw_map_entry(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) late_initcall(firmware_memmap_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)