drivers/acpi/apei/hest.c

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

File Facts

System
Linux kernel
Corpus path
drivers/acpi/apei/hest.c
Extension
.c
Size
8570 bytes
Lines
327
Domain
Driver Families
Bucket
drivers/acpi
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 ghes_arr {
	struct platform_device **ghes_devs;
	unsigned int count;
};

static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data)
{
	int *count = data;

	if (is_generic_error(hest_hdr))
		(*count)++;
	return 0;
}

static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
{
	struct platform_device *ghes_dev;
	struct ghes_arr *ghes_arr = data;
	int rc, i;

	if (!is_generic_error(hest_hdr))
		return 0;

	if (!((struct acpi_hest_generic *)hest_hdr)->enabled)
		return 0;
	for (i = 0; i < ghes_arr->count; i++) {
		struct acpi_hest_header *hdr;
		ghes_dev = ghes_arr->ghes_devs[i];
		hdr = *(struct acpi_hest_header **)ghes_dev->dev.platform_data;
		if (hdr->source_id == hest_hdr->source_id) {
			pr_warn(FW_WARN HEST_PFX "Duplicated hardware error source ID: %d.\n",
				hdr->source_id);
			return -EIO;
		}
	}
	ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id);
	if (!ghes_dev)
		return -ENOMEM;

	rc = platform_device_add_data(ghes_dev, &hest_hdr, sizeof(void *));
	if (rc)
		goto err;

	rc = platform_device_add(ghes_dev);
	if (rc)
		goto err;
	ghes_arr->ghes_devs[ghes_arr->count++] = ghes_dev;

	return 0;
err:
	platform_device_put(ghes_dev);
	return rc;
}

static int __init hest_ghes_dev_register(unsigned int ghes_count)
{
	int rc, i;
	struct ghes_arr ghes_arr;

	ghes_arr.count = 0;
	ghes_arr.ghes_devs = kmalloc_array(ghes_count, sizeof(void *),
					   GFP_KERNEL);
	if (!ghes_arr.ghes_devs)
		return -ENOMEM;

	rc = apei_hest_parse(hest_parse_ghes, &ghes_arr);
	if (rc)
		goto err;

	rc = ghes_estatus_pool_init(ghes_count);
	if (rc)
		goto err;

out:
	kfree(ghes_arr.ghes_devs);
	return rc;
err:
	for (i = 0; i < ghes_arr.count; i++)
		platform_device_unregister(ghes_arr.ghes_devs[i]);
	goto out;
}

static int __init setup_hest_disable(char *str)
{
	hest_disable = HEST_DISABLED;
	return 1;
}

__setup("hest_disable", setup_hest_disable);

Annotation

Implementation Notes