drivers/pci/controller/dwc/pcie-designware-ep.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/dwc/pcie-designware-ep.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/dwc/pcie-designware-ep.c
Extension
.c
Size
39304 bytes
Lines
1432
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

if (off > (~0ULL) - base) {
			ret = -EINVAL;
			goto err;
		}

		pci_addr = base + off;
		off += size;

		free_win = find_first_zero_bit(ep->ib_window_map,
					       pci->num_ib_windows);
		if (free_win >= pci->num_ib_windows) {
			ret = -ENOSPC;
			goto err;
		}

		ret = dw_pcie_prog_inbound_atu(pci, free_win, type,
					       parent_bus_addr, pci_addr, size);
		if (ret)
			goto err;

		set_bit(free_win, ep->ib_window_map);
		indexes[i] = free_win;
		ep_func->num_ib_atu_indexes[bar] = i + 1;
	}
	return 0;
err:
	dw_pcie_ep_clear_ib_maps(ep, func_no, bar);
	return ret;
}

static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep,
				   struct dw_pcie_ob_atu_cfg *atu)
{
	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
	u32 free_win;
	int ret;

	free_win = find_first_zero_bit(ep->ob_window_map, pci->num_ob_windows);
	if (free_win >= pci->num_ob_windows) {
		dev_err(pci->dev, "No free outbound window\n");
		return -EINVAL;
	}

	atu->index = free_win;
	ret = dw_pcie_prog_outbound_atu(pci, atu);
	if (ret)
		return ret;

	set_bit(free_win, ep->ob_window_map);
	ep->outbound_addr[free_win] = atu->parent_bus_addr;

	return 0;
}

static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
				 struct pci_epf_bar *epf_bar)
{
	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
	enum pci_barno bar = epf_bar->barno;
	struct dw_pcie_ep_func *ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no);

	if (!ep_func || !ep_func->epf_bar[bar])
		return;

	__dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);

	dw_pcie_ep_clear_ib_maps(ep, func_no, bar);

	ep_func->epf_bar[bar] = NULL;
}

static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie_ep *ep, u8 func_no,
						enum pci_barno bar)
{
	u32 reg, bar_index;
	unsigned int offset, nbars;
	int i;

	offset = dw_pcie_ep_find_ext_capability(ep, func_no, PCI_EXT_CAP_ID_REBAR);
	if (!offset)
		return offset;

	reg = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_REBAR_CTRL);
	nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, reg);

	for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) {
		reg = dw_pcie_ep_readl_dbi(ep, func_no, offset + PCI_REBAR_CTRL);
		bar_index = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, reg);
		if (bar_index == bar)

Annotation

Implementation Notes