Commit 8ffc9f23 authored by Hans Zhang's avatar Hans Zhang Committed by Bjorn Helgaas
Browse files

PCI: dwc: Implement capability search using PCI core APIs



The PCI core now provides generic PCI_FIND_NEXT_CAP() and
PCI_FIND_NEXT_EXT_CAP() macros to search for PCI capabilities, using
config accessors we supply.

Use them in the DWC driver to implement dw_pcie_find_capability() and
dw_pcie_find_ext_capability() instead of duplicating the algorithm.

Signed-off-by: default avatarHans Zhang <18255117159@163.com>
[bhelgaas: commit log]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20250813144529.303548-5-18255117159@163.com
parent 4d909bf1
Loading
Loading
Loading
Loading
+5 −72
Original line number Diff line number Diff line
@@ -213,83 +213,16 @@ void dw_pcie_version_detect(struct dw_pcie *pci)
		pci->type = ver;
}

/*
 * These interfaces resemble the pci_find_*capability() interfaces, but these
 * are for configuring host controllers, which are bridges *to* PCI devices but
 * are not PCI devices themselves.
 */
static u8 __dw_pcie_find_next_cap(struct dw_pcie *pci, u8 cap_ptr,
				  u8 cap)
{
	u8 cap_id, next_cap_ptr;
	u16 reg;

	if (!cap_ptr)
		return 0;

	reg = dw_pcie_readw_dbi(pci, cap_ptr);
	cap_id = (reg & 0x00ff);

	if (cap_id > PCI_CAP_ID_MAX)
		return 0;

	if (cap_id == cap)
		return cap_ptr;

	next_cap_ptr = (reg & 0xff00) >> 8;
	return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap);
}

u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap)
{
	u8 next_cap_ptr;
	u16 reg;

	reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST);
	next_cap_ptr = (reg & 0x00ff);

	return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap);
	return PCI_FIND_NEXT_CAP(dw_pcie_read_cfg, PCI_CAPABILITY_LIST, cap,
				 pci);
}
EXPORT_SYMBOL_GPL(dw_pcie_find_capability);

static u16 dw_pcie_find_next_ext_capability(struct dw_pcie *pci, u16 start,
					    u8 cap)
{
	u32 header;
	int ttl;
	int pos = PCI_CFG_SPACE_SIZE;

	/* minimum 8 bytes per capability */
	ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;

	if (start)
		pos = start;

	header = dw_pcie_readl_dbi(pci, pos);
	/*
	 * If we have no capabilities, this is indicated by cap ID,
	 * cap version and next pointer all being 0.
	 */
	if (header == 0)
		return 0;

	while (ttl-- > 0) {
		if (PCI_EXT_CAP_ID(header) == cap && pos != start)
			return pos;

		pos = PCI_EXT_CAP_NEXT(header);
		if (pos < PCI_CFG_SPACE_SIZE)
			break;

		header = dw_pcie_readl_dbi(pci, pos);
	}

	return 0;
}

u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap)
{
	return dw_pcie_find_next_ext_capability(pci, 0, cap);
	return PCI_FIND_NEXT_EXT_CAP(dw_pcie_read_cfg, 0, cap, pci);
}
EXPORT_SYMBOL_GPL(dw_pcie_find_ext_capability);

@@ -302,8 +235,8 @@ static u16 __dw_pcie_find_vsec_capability(struct dw_pcie *pci, u16 vendor_id,
	if (vendor_id != dw_pcie_readw_dbi(pci, PCI_VENDOR_ID))
		return 0;

	while ((vsec = dw_pcie_find_next_ext_capability(pci, vsec,
						       PCI_EXT_CAP_ID_VNDR))) {
	while ((vsec = PCI_FIND_NEXT_EXT_CAP(dw_pcie_read_cfg, vsec,
					     PCI_EXT_CAP_ID_VNDR, pci))) {
		header = dw_pcie_readl_dbi(pci, vsec + PCI_VNDR_HEADER);
		if (PCI_VNDR_HEADER_ID(header) == vsec_id)
			return vsec;
+21 −0
Original line number Diff line number Diff line
@@ -609,6 +609,27 @@ static inline void dw_pcie_writel_dbi2(struct dw_pcie *pci, u32 reg, u32 val)
	dw_pcie_write_dbi2(pci, reg, 0x4, val);
}

static inline int dw_pcie_read_cfg_byte(struct dw_pcie *pci, int where,
					u8 *val)
{
	*val = dw_pcie_readb_dbi(pci, where);
	return PCIBIOS_SUCCESSFUL;
}

static inline int dw_pcie_read_cfg_word(struct dw_pcie *pci, int where,
					u16 *val)
{
	*val = dw_pcie_readw_dbi(pci, where);
	return PCIBIOS_SUCCESSFUL;
}

static inline int dw_pcie_read_cfg_dword(struct dw_pcie *pci, int where,
					 u32 *val)
{
	*val = dw_pcie_readl_dbi(pci, where);
	return PCIBIOS_SUCCESSFUL;
}

static inline unsigned int dw_pcie_ep_get_dbi_offset(struct dw_pcie_ep *ep,
						     u8 func_no)
{