drivers/acpi/riscv/rimt.c

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

File Facts

System
Linux kernel
Corpus path
drivers/acpi/riscv/rimt.c
Extension
.c
Size
13488 bytes
Lines
528
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 rimt_fwnode {
	struct list_head list;
	struct acpi_rimt_node *rimt_node;
	struct fwnode_handle *fwnode;
};

static LIST_HEAD(rimt_fwnode_list);
static DEFINE_SPINLOCK(rimt_fwnode_lock);

#define RIMT_TYPE_MASK(type)	(1 << (type))
#define RIMT_IOMMU_TYPE		BIT(0)

/* Root pointer to the mapped RIMT table */
static struct acpi_table_header *rimt_table;

/**
 * rimt_set_fwnode() - Create rimt_fwnode and use it to register
 *		       iommu data in the rimt_fwnode_list
 *
 * @rimt_node: RIMT table node associated with the IOMMU
 * @fwnode: fwnode associated with the RIMT node
 *
 * Returns: 0 on success
 *          <0 on failure
 */
static int rimt_set_fwnode(struct acpi_rimt_node *rimt_node,
			   struct fwnode_handle *fwnode)
{
	struct rimt_fwnode *np;

	np = kzalloc_obj(*np, GFP_ATOMIC);

	if (WARN_ON(!np))
		return -ENOMEM;

	INIT_LIST_HEAD(&np->list);
	np->rimt_node = rimt_node;
	np->fwnode = fwnode;

	spin_lock(&rimt_fwnode_lock);
	list_add_tail(&np->list, &rimt_fwnode_list);
	spin_unlock(&rimt_fwnode_lock);

	return 0;
}

static acpi_status rimt_match_node_callback(struct acpi_rimt_node *node,
					    void *context)
{
	acpi_status status = AE_NOT_FOUND;
	struct device *dev = context;

	if (node->type == ACPI_RIMT_NODE_TYPE_IOMMU) {
		struct acpi_rimt_iommu *iommu_node = (struct acpi_rimt_iommu *)&node->node_data;

		if (dev_is_pci(dev)) {
			struct pci_dev *pdev;
			u16 bdf;

			pdev = to_pci_dev(dev);
			bdf = PCI_DEVID(pdev->bus->number, pdev->devfn);
			if ((pci_domain_nr(pdev->bus) == iommu_node->pcie_segment_number) &&
			    bdf == iommu_node->pcie_bdf) {
				status = AE_OK;
			} else {
				status = AE_NOT_FOUND;
			}
		} else {
			struct platform_device *pdev = to_platform_device(dev);
			struct resource *res;

			res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
			if (res && res->start == iommu_node->base_address)
				status = AE_OK;
			else
				status = AE_NOT_FOUND;
		}
	} else if (node->type == ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX) {
		struct acpi_rimt_pcie_rc *pci_rc;
		struct pci_bus *bus;

		bus = to_pci_bus(dev);
		pci_rc = (struct acpi_rimt_pcie_rc *)node->node_data;

		/*
		 * It is assumed that PCI segment numbers maps one-to-one
		 * with root complexes. Each segment number can represent only
		 * one root complex.
		 */
		status = pci_rc->pcie_segment_number == pci_domain_nr(bus) ?

Annotation

Implementation Notes