/* SPDX-License-Identifier: GPL-2.0 */
#ifndef DRIVERS_PCI_H
#define DRIVERS_PCI_H
#include <linux/align.h>
#include <linux/bitfield.h>
#include <linux/pci.h>
struct pcie_tlp_log;
/* Number of possible devfns: 0.0 to 1f.7 inclusive */
#define MAX_NR_DEVFNS 256
#define PCI_MAX_NR_DEVS 32
#define MAX_NR_LANES 16
#define PCI_FIND_CAP_TTL 48
#define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */
#define PCIE_LINK_RETRAIN_TIMEOUT_MS 1000
/*
* Power stable to PERST# inactive.
*
* See the "Power Sequencing and Reset Signal Timings" table of the PCI Express
* Card Electromechanical Specification, Revision 5.1, Section 2.9.2, Symbol
* "T_PVPERL".
*/
#define PCIE_T_PVPERL_MS 100
/*
* REFCLK stable before PERST# inactive.
*
* See the "Power Sequencing and Reset Signal Timings" table of the PCI Express
* Card Electromechanical Specification, Revision 5.1, Section 2.9.2, Symbol
* "T_PERST-CLK".
*/
#define PCIE_T_PERST_CLK_US 100
/*
* PCIe r6.0, sec 5.3.3.2.1 <PME Synchronization>
* Recommends 1ms to 10ms timeout to check L2 ready.
*/
#define PCIE_PME_TO_L2_TIMEOUT_US 10000
/*
* PCIe r6.0, sec 6.6.1 <Conventional Reset>
*
* - "With a Downstream Port that does not support Link speeds greater
* than 5.0 GT/s, software must wait a minimum of 100 ms following exit
* from a Conventional Reset before sending a Configuration Request to
* the device immediately below that Port."
*
* - "With a Downstream Port that supports Link speeds greater than
* 5.0 GT/s, software must wait a minimum of 100 ms after Link training
* completes before sending a Configuration Request to the device
* immediately below that Port."
*/
#define PCIE_RESET_CONFIG_WAIT_MS 100
/* Parameters for the waiting for link up routine */
#define PCIE_LINK_WAIT_MAX_RETRIES 10
#define PCIE_LINK_WAIT_SLEEP_MS 90
/* Message Routing (r[2:0]); PCIe r6.0, sec 2.2.8 */
#define PCIE_MSG_TYPE_R_RC 0
#define PCIE_MSG_TYPE_R_ADDR 1
#define PCIE_MSG_TYPE_R_ID 2
#define PCIE_MSG_TYPE_R_BC 3
#define PCIE_MSG_TYPE_R_LOCAL 4
#define PCIE_MSG_TYPE_R_GATHER 5
/* Power Management Messages; PCIe r6.0, sec 2.2.8.2 */
#define PCIE_MSG_CODE_PME_TURN_OFF 0x19
/* INTx Mechanism Messages; PCIe r6.0, sec 2.2.8.1 */
#define PCIE_MSG_CODE_ASSERT_INTA 0x20
#define PCIE_MSG_CODE_ASSERT_INTB 0x21
#define PCIE_MSG_CODE_ASSERT_INTC 0x22
#define PCIE_MSG_CODE_ASSERT_INTD 0x23
#define PCIE_MSG_CODE_DEASSERT_INTA 0x24
#define PCIE_MSG_CODE_DEASSERT_INTB 0x25
#define PCIE_MSG_CODE_DEASSERT_INTC 0x26
#define PCIE_MSG_CODE_DEASSERT_INTD 0x27
#define PCI_BUS_BRIDGE_IO_WINDOW 0
#define PCI_BUS_BRIDGE_MEM_WINDOW 1
#define PCI_BUS_BRIDGE_PREF_MEM_WINDOW 2
extern const unsigned char pcie_link_speed[];
extern bool pci_early_dump;
extern struct mutex pci_rescan_remove_lock;
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
bool pcie_cap_has_lnkctl2(const struct pci_dev *dev);
bool pcie_cap_has_rtctl(const struct pci_dev *dev);
/* Standard Capability finder */
/**
* PCI_FIND_NEXT_CAP - Find a PCI standard capability
* @read_cfg: Function pointer for reading PCI config space
* @start: Starting position to begin search
* @cap: Capability ID to find
* @args: Arguments to pass to read_cfg function
*
* Search the capability list in PCI config space to find @cap.
* Implements TTL (time-to-live) protection against infinite loops.
*
* Return: Position of the capability if found, 0 otherwise.
*/
#define PCI_FIND_NEXT_CAP(read_cfg, start, cap, args...) \
({ \
int __ttl = PCI_FIND_CAP_TTL; \
u8 __id, __found_pos = 0; \
u8 __pos = (start); \
u16 __ent; \
\
read_cfg##_byte(args, __pos, &__pos); \
\
while (__ttl--) { \
if (__pos < PCI_STD_HEADER_SIZEOF) \
break; \
\
__pos = ALIGN_DOWN(__pos, 4); \
read_cfg##_word(args, __pos, &__ent); \
\
__id = FIELD_GET(PCI_CAP_ID_MASK, __ent); \
if (__id == 0xff) \
break; \
\
if (__id == (cap)) { \
__found_pos = __pos; \
break; \
} \
\
__pos = FIELD_GET(PCI_CAP_LIST_NEXT_MASK, __ent); \
} \
__found_pos; \
})
/* Extended Capability finder */
/**
* PCI_FIND_NEXT_EXT_CAP - Find a PCI extended capability
* @read_cfg: Function pointer for reading PCI config space
* @start: Starting position to begin search (0 for initial search)
* @cap: Extended capability ID to find
* @args: Arguments to pass to read_cfg function
*
* Search the extended capability list in PCI config space to find @cap.
* Implements TTL protection against infinite loops using a calculated
* maximum search count.
*
* Return: Position of the capability if found, 0 otherwise.
*/
#define PCI_FIND_NEXT_EXT_CAP(read_cfg, start, cap, args...) \
({ \
u16 __pos = (start) ?: PCI_CFG_SPACE_SIZE; \
u16 __found_pos = 0; \
int __ttl, __ret; \
u32 __header; \
\
__ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; \
while (__ttl-- > 0 && __pos >= PCI_CFG_SPACE_SIZE) { \
__ret = read_cfg##_dword(args, __pos, &__header); \
if (__ret != PCIBIOS_SUCCESSFUL) \
break; \
\
if (__header == 0) \
break; \
\
if (PCI_EXT_CAP_ID(__header) == (cap) && __pos != start) {\
__found_pos = __pos; \
break; \