drivers/cxl/pci.c

Source file repositories/reference/linux-study-clean/drivers/cxl/pci.c

File Facts

System
Linux kernel
Corpus path
drivers/cxl/pci.c
Extension
.c
Size
30791 bytes
Lines
1095
Domain
Driver Families
Bucket
drivers/cxl
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static struct pci_driver cxl_pci_driver = {
	.name			= KBUILD_MODNAME,
	.id_table		= cxl_mem_pci_tbl,
	.probe			= cxl_pci_probe,
	.err_handler		= &cxl_error_handlers,
	.dev_groups		= cxl_rcd_groups,
	.driver	= {
		.probe_type	= PROBE_PREFER_ASYNCHRONOUS,
	},
};

#define CXL_EVENT_HDR_FLAGS_REC_SEVERITY GENMASK(1, 0)
static void cxl_handle_cper_event(enum cxl_event_type ev_type,
				  struct cxl_cper_event_rec *rec)
{
	struct cper_cxl_event_devid *device_id = &rec->hdr.device_id;
	struct pci_dev *pdev __free(pci_dev_put) = NULL;
	enum cxl_event_log_type log_type;
	struct cxl_dev_state *cxlds;
	unsigned int devfn;
	u32 hdr_flags;

	pr_debug("CPER event %d for device %u:%u:%u.%u\n", ev_type,
		 device_id->segment_num, device_id->bus_num,
		 device_id->device_num, device_id->func_num);

	devfn = PCI_DEVFN(device_id->device_num, device_id->func_num);
	pdev = pci_get_domain_bus_and_slot(device_id->segment_num,
					   device_id->bus_num, devfn);
	if (!pdev)
		return;

	guard(device)(&pdev->dev);
	if (pdev->driver != &cxl_pci_driver)
		return;

	cxlds = pci_get_drvdata(pdev);
	if (!cxlds)
		return;

	/* Fabricate a log type */
	hdr_flags = get_unaligned_le24(rec->event.generic.hdr.flags);
	log_type = FIELD_GET(CXL_EVENT_HDR_FLAGS_REC_SEVERITY, hdr_flags);

	cxl_event_trace_record(cxlds->cxlmd, log_type, ev_type,
			       &uuid_null, &rec->event);
}

static void cxl_cper_work_fn(struct work_struct *work)
{
	struct cxl_cper_work_data wd;

	while (cxl_cper_kfifo_get(&wd))
		cxl_handle_cper_event(wd.event_type, &wd.rec);
}
static DECLARE_WORK(cxl_cper_work, cxl_cper_work_fn);

static int __init cxl_pci_driver_init(void)
{
	int rc;

	rc = pci_register_driver(&cxl_pci_driver);
	if (rc)
		return rc;

	rc = cxl_cper_register_work(&cxl_cper_work);
	if (rc)
		pci_unregister_driver(&cxl_pci_driver);

	return rc;
}

static void __exit cxl_pci_driver_exit(void)
{
	cxl_cper_unregister_work(&cxl_cper_work);
	cancel_work_sync(&cxl_cper_work);
	pci_unregister_driver(&cxl_pci_driver);
}

module_init(cxl_pci_driver_init);
module_exit(cxl_pci_driver_exit);
MODULE_DESCRIPTION("CXL: PCI manageability");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS("CXL");

Annotation

Implementation Notes