drivers/acpi/acpi_memhotplug.c

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

File Facts

System
Linux kernel
Corpus path
drivers/acpi/acpi_memhotplug.c
Extension
.c
Size
9467 bytes
Lines
368
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 acpi_memory_info {
	struct list_head list;
	u64 start_addr;		/* Memory Range start physical addr */
	u64 length;		/* Memory Range length */
	unsigned short caching;	/* memory cache attribute */
	unsigned short write_protect;	/* memory read/write attribute */
	unsigned int enabled:1;
};

struct acpi_memory_device {
	struct acpi_device *device;
	struct list_head res_list;
	int mgid;
};

static acpi_status
acpi_memory_get_resource(struct acpi_resource *resource, void *context)
{
	struct acpi_memory_device *mem_device = context;
	struct acpi_resource_address64 address64;
	struct acpi_memory_info *info, *new;
	acpi_status status;

	status = acpi_resource_to_address64(resource, &address64);
	if (ACPI_FAILURE(status) ||
	    (address64.resource_type != ACPI_MEMORY_RANGE))
		return AE_OK;

	list_for_each_entry(info, &mem_device->res_list, list) {
		/* Can we combine the resource range information? */
		if ((info->caching == address64.info.mem.caching) &&
		    (info->write_protect == address64.info.mem.write_protect) &&
		    (info->start_addr + info->length == address64.address.minimum)) {
			info->length += address64.address.address_length;
			return AE_OK;
		}
	}

	new = kzalloc_obj(struct acpi_memory_info);
	if (!new)
		return AE_ERROR;

	INIT_LIST_HEAD(&new->list);
	new->caching = address64.info.mem.caching;
	new->write_protect = address64.info.mem.write_protect;
	new->start_addr = address64.address.minimum;
	new->length = address64.address.address_length;
	list_add_tail(&new->list, &mem_device->res_list);

	return AE_OK;
}

static void
acpi_memory_free_device_resources(struct acpi_memory_device *mem_device)
{
	struct acpi_memory_info *info, *n;

	list_for_each_entry_safe(info, n, &mem_device->res_list, list)
		kfree(info);
	INIT_LIST_HEAD(&mem_device->res_list);
}

static int
acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
{
	acpi_status status;

	if (!list_empty(&mem_device->res_list))
		return 0;

	status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
				     acpi_memory_get_resource, mem_device);
	if (ACPI_FAILURE(status)) {
		acpi_memory_free_device_resources(mem_device);
		return -EINVAL;
	}

	return 0;
}

static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
{
	unsigned long long current_status;

	/* Get device present/absent information from the _STA */
	if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle,
					       METHOD_NAME__STA, NULL,
					       &current_status)))
		return -ENODEV;
	/*

Annotation

Implementation Notes