drivers/acpi/arm64/agdi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/acpi/arm64/agdi.c
Extension
.c
Size
4676 bytes
Lines
206
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 agdi_data {
	unsigned char flags; /* AGDI Signaling Mode */
	int sdei_event;
	unsigned int gsiv;
	bool use_nmi;
	int irq;
};

static int agdi_sdei_handler(u32 sdei_event, struct pt_regs *regs, void *arg)
{
	nmi_panic(regs, "Arm Generic Diagnostic Dump and Reset SDEI event issued");
	return 0;
}

static int agdi_sdei_probe(struct platform_device *pdev,
			   struct agdi_data *adata)
{
	int err;

	err = sdei_event_register(adata->sdei_event, agdi_sdei_handler, pdev);
	if (err) {
		dev_err(&pdev->dev, "Failed to register for SDEI event %d\n",
			adata->sdei_event);
		return err;
	}

	err = sdei_event_enable(adata->sdei_event);
	if (err)  {
		sdei_event_unregister(adata->sdei_event);
		dev_err(&pdev->dev, "Failed to enable event %d\n",
			adata->sdei_event);
		return err;
	}

	return 0;
}

static irqreturn_t agdi_interrupt_handler_nmi(int irq, void *dev_id)
{
	nmi_panic(NULL, "Arm Generic Diagnostic Dump and Reset NMI Interrupt event issued\n");
	return IRQ_HANDLED;
}

static irqreturn_t agdi_interrupt_handler_irq(int irq, void *dev_id)
{
	panic("Arm Generic Diagnostic Dump and Reset Interrupt event issued\n");
	return IRQ_HANDLED;
}

static int agdi_interrupt_probe(struct platform_device *pdev,
				struct agdi_data *adata)
{
	unsigned long irq_flags;
	int ret;
	int irq;

	irq = acpi_register_gsi(NULL, adata->gsiv, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH);
	if (irq < 0) {
		dev_err(&pdev->dev, "cannot register GSI#%d (%d)\n", adata->gsiv, irq);
		return irq;
	}

	irq_flags = IRQF_PERCPU | IRQF_NOBALANCING | IRQF_NO_AUTOEN |
		    IRQF_NO_THREAD;
	/* try NMI first */
	ret = request_nmi(irq, &agdi_interrupt_handler_nmi, irq_flags,
			  "agdi_interrupt_nmi", NULL);
	if (!ret) {
		enable_nmi(irq);
		adata->irq = irq;
		adata->use_nmi = true;
		return 0;
	}

	/* Then try normal interrupt */
	ret = request_irq(irq, &agdi_interrupt_handler_irq,
			  irq_flags, "agdi_interrupt_irq", NULL);
	if (ret) {
		dev_err(&pdev->dev, "cannot register IRQ %d\n", ret);
		acpi_unregister_gsi(adata->gsiv);
		return ret;
	}
	enable_irq(irq);
	adata->irq = irq;

	return 0;
}

static int agdi_probe(struct platform_device *pdev)
{

Annotation

Implementation Notes