drivers/pci/controller/pcie-xilinx-dma-pl.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/pcie-xilinx-dma-pl.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/pcie-xilinx-dma-pl.c
Extension
.c
Size
22603 bytes
Lines
848
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: implementation source
Status
source 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 xilinx_pl_dma_variant {
	enum xilinx_pl_dma_version version;
};

struct xilinx_msi {
	unsigned long		*bitmap;
	struct irq_domain	*dev_domain;
	struct mutex		lock;		/* Protect bitmap variable */
	int			irq_msi0;
	int			irq_msi1;
};

/**
 * struct pl_dma_pcie - PCIe port information
 * @dev: Device pointer
 * @reg_base: IO Mapped Register Base
 * @cfg_base: IO Mapped Configuration Base
 * @irq: Interrupt number
 * @cfg: Holds mappings of config space window
 * @phys_reg_base: Physical address of reg base
 * @intx_domain: Legacy IRQ domain pointer
 * @pldma_domain: PL DMA IRQ domain pointer
 * @resources: Bus Resources
 * @msi: MSI information
 * @intx_irq: INTx error interrupt number
 * @lock: Lock protecting shared register access
 * @variant: PL DMA PCIe version check pointer
 */
struct pl_dma_pcie {
	struct device			*dev;
	void __iomem			*reg_base;
	void __iomem			*cfg_base;
	int				irq;
	struct pci_config_window	*cfg;
	phys_addr_t			phys_reg_base;
	struct irq_domain		*intx_domain;
	struct irq_domain		*pldma_domain;
	struct list_head		resources;
	struct xilinx_msi		msi;
	int				intx_irq;
	raw_spinlock_t			lock;
	const struct xilinx_pl_dma_variant   *variant;
};

static inline u32 pcie_read(struct pl_dma_pcie *port, u32 reg)
{
	if (port->variant->version == QDMA)
		return readl(port->reg_base + reg + QDMA_BRIDGE_BASE_OFF);

	return readl(port->reg_base + reg);
}

static inline void pcie_write(struct pl_dma_pcie *port, u32 val, u32 reg)
{
	if (port->variant->version == QDMA)
		writel(val, port->reg_base + reg + QDMA_BRIDGE_BASE_OFF);
	else
		writel(val, port->reg_base + reg);
}

static inline bool xilinx_pl_dma_pcie_link_up(struct pl_dma_pcie *port)
{
	return (pcie_read(port, XILINX_PCIE_DMA_REG_PSCR) &
		XILINX_PCIE_DMA_REG_PSCR_LNKUP) ? true : false;
}

static void xilinx_pl_dma_pcie_clear_err_interrupts(struct pl_dma_pcie *port)
{
	unsigned long val = pcie_read(port, XILINX_PCIE_DMA_REG_RPEFR);

	if (val & XILINX_PCIE_DMA_RPEFR_ERR_VALID) {
		dev_dbg(port->dev, "Requester ID %lu\n",
			val & XILINX_PCIE_DMA_RPEFR_REQ_ID);
		pcie_write(port, XILINX_PCIE_DMA_RPEFR_ALL_MASK,
			   XILINX_PCIE_DMA_REG_RPEFR);
	}
}

static bool xilinx_pl_dma_pcie_valid_device(struct pci_bus *bus,
					    unsigned int devfn)
{
	struct pl_dma_pcie *port = bus->sysdata;

	if (!pci_is_root_bus(bus)) {
		/*
		 * Checking whether the link is up is the last line of
		 * defense, and this check is inherently racy by definition.
		 * Sending a PIO request to a downstream device when the link is
		 * down causes an unrecoverable error, and a reset of the entire
		 * PCIe controller will be needed. We can reduce the likelihood

Annotation

Implementation Notes