drivers/pci/devres.c

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

File Facts

System
Linux kernel
Corpus path
drivers/pci/devres.c
Extension
.c
Size
21336 bytes
Lines
862
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pcim_iomap_devres {
	void __iomem *table[PCI_NUM_RESOURCES];
};

/* Used to restore the old INTx state on driver detach. */
struct pcim_intx_devres {
	int orig_intx;
};

enum pcim_addr_devres_type {
	/* Default initializer. */
	PCIM_ADDR_DEVRES_TYPE_INVALID,

	/* A requested region spanning an entire BAR. */
	PCIM_ADDR_DEVRES_TYPE_REGION,

	/*
	 * A requested region spanning an entire BAR, and a mapping for
	 * the entire BAR.
	 */
	PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING,

	/*
	 * A mapping within a BAR, either spanning the whole BAR or just a
	 * range.  Without a requested region.
	 */
	PCIM_ADDR_DEVRES_TYPE_MAPPING,
};

/*
 * This struct envelops IO or MEM addresses, i.e., mappings and region
 * requests, because those are very frequently requested and released
 * together.
 */
struct pcim_addr_devres {
	enum pcim_addr_devres_type type;
	void __iomem *baseaddr;
	unsigned long offset;
	unsigned long len;
	int bar;
};

static inline void pcim_addr_devres_clear(struct pcim_addr_devres *res)
{
	memset(res, 0, sizeof(*res));
	res->bar = -1;
}

static void pcim_addr_resource_release(struct device *dev, void *resource_raw)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	struct pcim_addr_devres *res = resource_raw;

	switch (res->type) {
	case PCIM_ADDR_DEVRES_TYPE_REGION:
		pci_release_region(pdev, res->bar);
		break;
	case PCIM_ADDR_DEVRES_TYPE_REGION_MAPPING:
		pci_iounmap(pdev, res->baseaddr);
		pci_release_region(pdev, res->bar);
		break;
	case PCIM_ADDR_DEVRES_TYPE_MAPPING:
		pci_iounmap(pdev, res->baseaddr);
		break;
	default:
		break;
	}
}

static struct pcim_addr_devres *pcim_addr_devres_alloc(struct pci_dev *pdev)
{
	struct pcim_addr_devres *res;

	res = devres_alloc_node(pcim_addr_resource_release, sizeof(*res),
				GFP_KERNEL, dev_to_node(&pdev->dev));
	if (res)
		pcim_addr_devres_clear(res);
	return res;
}

/* Just for consistency and readability. */
static inline void pcim_addr_devres_free(struct pcim_addr_devres *res)
{
	devres_free(res);
}

/*
 * Used by devres to identify a pcim_addr_devres.
 */
static int pcim_addr_resources_match(struct device *dev,

Annotation

Implementation Notes