drivers/acpi/nvs.c

Source file repositories/reference/linux-study-clean/drivers/acpi/nvs.c

File Facts

System
Linux kernel
Corpus path
drivers/acpi/nvs.c
Extension
.c
Size
4637 bytes
Lines
214
Domain
Driver Families
Bucket
drivers/acpi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct nvs_region {
	__u64 phys_start;
	__u64 size;
	struct list_head node;
};

static LIST_HEAD(nvs_region_list);

#ifdef CONFIG_ACPI_SLEEP
static int suspend_nvs_register(unsigned long start, unsigned long size);
#else
static inline int suspend_nvs_register(unsigned long a, unsigned long b)
{
	return 0;
}
#endif

int acpi_nvs_register(__u64 start, __u64 size)
{
	struct nvs_region *region;

	region = kmalloc_obj(*region);
	if (!region)
		return -ENOMEM;
	region->phys_start = start;
	region->size = size;
	list_add_tail(&region->node, &nvs_region_list);

	return suspend_nvs_register(start, size);
}

int acpi_nvs_for_each_region(int (*func)(__u64 start, __u64 size, void *data),
			     void *data)
{
	int rc;
	struct nvs_region *region;

	list_for_each_entry(region, &nvs_region_list, node) {
		rc = func(region->phys_start, region->size, data);
		if (rc)
			return rc;
	}

	return 0;
}


#ifdef CONFIG_ACPI_SLEEP
/*
 * Platforms, like ACPI, may want us to save some memory used by them during
 * suspend and to restore the contents of this memory during the subsequent
 * resume.  The code below implements a mechanism allowing us to do that.
 */

struct nvs_page {
	unsigned long phys_start;
	unsigned int size;
	void *kaddr;
	void *data;
	bool unmap;
	struct list_head node;
};

static LIST_HEAD(nvs_list);

/**
 * suspend_nvs_register - register platform NVS memory region to save
 * @start: Physical address of the region.
 * @size: Size of the region.
 *
 * The NVS region need not be page-aligned (both ends) and we arrange
 * things so that the data from page-aligned addresses in this region will
 * be copied into separate RAM pages.
 */
static int suspend_nvs_register(unsigned long start, unsigned long size)
{
	struct nvs_page *entry, *next;

	pr_info("Registering ACPI NVS region [mem %#010lx-%#010lx] (%ld bytes)\n",
		start, start + size - 1, size);

	while (size > 0) {
		unsigned int nr_bytes;

		entry = kzalloc_obj(struct nvs_page);
		if (!entry)
			goto Error;

		list_add_tail(&entry->node, &nvs_list);
		entry->phys_start = start;

Annotation

Implementation Notes