162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/pci.h>
362306a36Sopenharmony_ci#include <linux/module.h>
462306a36Sopenharmony_ci#include <linux/slab.h>
562306a36Sopenharmony_ci#include <linux/ioport.h>
662306a36Sopenharmony_ci#include <linux/wait.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "pci.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/*
1162306a36Sopenharmony_ci * This interrupt-safe spinlock protects all accesses to PCI
1262306a36Sopenharmony_ci * configuration space.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ciDEFINE_RAW_SPINLOCK(pci_lock);
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * Wrappers for all PCI configuration access functions.  They just check
1962306a36Sopenharmony_ci * alignment, do locking and call the low-level functions pointed to
2062306a36Sopenharmony_ci * by pci_dev->ops.
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define PCI_byte_BAD 0
2462306a36Sopenharmony_ci#define PCI_word_BAD (pos & 1)
2562306a36Sopenharmony_ci#define PCI_dword_BAD (pos & 3)
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#ifdef CONFIG_PCI_LOCKLESS_CONFIG
2862306a36Sopenharmony_ci# define pci_lock_config(f)	do { (void)(f); } while (0)
2962306a36Sopenharmony_ci# define pci_unlock_config(f)	do { (void)(f); } while (0)
3062306a36Sopenharmony_ci#else
3162306a36Sopenharmony_ci# define pci_lock_config(f)	raw_spin_lock_irqsave(&pci_lock, f)
3262306a36Sopenharmony_ci# define pci_unlock_config(f)	raw_spin_unlock_irqrestore(&pci_lock, f)
3362306a36Sopenharmony_ci#endif
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define PCI_OP_READ(size, type, len) \
3662306a36Sopenharmony_ciint noinline pci_bus_read_config_##size \
3762306a36Sopenharmony_ci	(struct pci_bus *bus, unsigned int devfn, int pos, type *value)	\
3862306a36Sopenharmony_ci{									\
3962306a36Sopenharmony_ci	int res;							\
4062306a36Sopenharmony_ci	unsigned long flags;						\
4162306a36Sopenharmony_ci	u32 data = 0;							\
4262306a36Sopenharmony_ci	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
4362306a36Sopenharmony_ci	pci_lock_config(flags);						\
4462306a36Sopenharmony_ci	res = bus->ops->read(bus, devfn, pos, len, &data);		\
4562306a36Sopenharmony_ci	if (res)							\
4662306a36Sopenharmony_ci		PCI_SET_ERROR_RESPONSE(value);				\
4762306a36Sopenharmony_ci	else								\
4862306a36Sopenharmony_ci		*value = (type)data;					\
4962306a36Sopenharmony_ci	pci_unlock_config(flags);					\
5062306a36Sopenharmony_ci	return res;							\
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define PCI_OP_WRITE(size, type, len) \
5462306a36Sopenharmony_ciint noinline pci_bus_write_config_##size \
5562306a36Sopenharmony_ci	(struct pci_bus *bus, unsigned int devfn, int pos, type value)	\
5662306a36Sopenharmony_ci{									\
5762306a36Sopenharmony_ci	int res;							\
5862306a36Sopenharmony_ci	unsigned long flags;						\
5962306a36Sopenharmony_ci	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
6062306a36Sopenharmony_ci	pci_lock_config(flags);						\
6162306a36Sopenharmony_ci	res = bus->ops->write(bus, devfn, pos, len, value);		\
6262306a36Sopenharmony_ci	pci_unlock_config(flags);					\
6362306a36Sopenharmony_ci	return res;							\
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ciPCI_OP_READ(byte, u8, 1)
6762306a36Sopenharmony_ciPCI_OP_READ(word, u16, 2)
6862306a36Sopenharmony_ciPCI_OP_READ(dword, u32, 4)
6962306a36Sopenharmony_ciPCI_OP_WRITE(byte, u8, 1)
7062306a36Sopenharmony_ciPCI_OP_WRITE(word, u16, 2)
7162306a36Sopenharmony_ciPCI_OP_WRITE(dword, u32, 4)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_read_config_byte);
7462306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_read_config_word);
7562306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_read_config_dword);
7662306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_write_config_byte);
7762306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_write_config_word);
7862306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_write_config_dword);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ciint pci_generic_config_read(struct pci_bus *bus, unsigned int devfn,
8162306a36Sopenharmony_ci			    int where, int size, u32 *val)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	void __iomem *addr;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	addr = bus->ops->map_bus(bus, devfn, where);
8662306a36Sopenharmony_ci	if (!addr)
8762306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	if (size == 1)
9062306a36Sopenharmony_ci		*val = readb(addr);
9162306a36Sopenharmony_ci	else if (size == 2)
9262306a36Sopenharmony_ci		*val = readw(addr);
9362306a36Sopenharmony_ci	else
9462306a36Sopenharmony_ci		*val = readl(addr);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	return PCIBIOS_SUCCESSFUL;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_generic_config_read);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciint pci_generic_config_write(struct pci_bus *bus, unsigned int devfn,
10162306a36Sopenharmony_ci			     int where, int size, u32 val)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	void __iomem *addr;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	addr = bus->ops->map_bus(bus, devfn, where);
10662306a36Sopenharmony_ci	if (!addr)
10762306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	if (size == 1)
11062306a36Sopenharmony_ci		writeb(val, addr);
11162306a36Sopenharmony_ci	else if (size == 2)
11262306a36Sopenharmony_ci		writew(val, addr);
11362306a36Sopenharmony_ci	else
11462306a36Sopenharmony_ci		writel(val, addr);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	return PCIBIOS_SUCCESSFUL;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_generic_config_write);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciint pci_generic_config_read32(struct pci_bus *bus, unsigned int devfn,
12162306a36Sopenharmony_ci			      int where, int size, u32 *val)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	void __iomem *addr;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	addr = bus->ops->map_bus(bus, devfn, where & ~0x3);
12662306a36Sopenharmony_ci	if (!addr)
12762306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	*val = readl(addr);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	if (size <= 2)
13262306a36Sopenharmony_ci		*val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	return PCIBIOS_SUCCESSFUL;
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_generic_config_read32);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ciint pci_generic_config_write32(struct pci_bus *bus, unsigned int devfn,
13962306a36Sopenharmony_ci			       int where, int size, u32 val)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	void __iomem *addr;
14262306a36Sopenharmony_ci	u32 mask, tmp;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	addr = bus->ops->map_bus(bus, devfn, where & ~0x3);
14562306a36Sopenharmony_ci	if (!addr)
14662306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	if (size == 4) {
14962306a36Sopenharmony_ci		writel(val, addr);
15062306a36Sopenharmony_ci		return PCIBIOS_SUCCESSFUL;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	/*
15462306a36Sopenharmony_ci	 * In general, hardware that supports only 32-bit writes on PCI is
15562306a36Sopenharmony_ci	 * not spec-compliant.  For example, software may perform a 16-bit
15662306a36Sopenharmony_ci	 * write.  If the hardware only supports 32-bit accesses, we must
15762306a36Sopenharmony_ci	 * do a 32-bit read, merge in the 16 bits we intend to write,
15862306a36Sopenharmony_ci	 * followed by a 32-bit write.  If the 16 bits we *don't* intend to
15962306a36Sopenharmony_ci	 * write happen to have any RW1C (write-one-to-clear) bits set, we
16062306a36Sopenharmony_ci	 * just inadvertently cleared something we shouldn't have.
16162306a36Sopenharmony_ci	 */
16262306a36Sopenharmony_ci	if (!bus->unsafe_warn) {
16362306a36Sopenharmony_ci		dev_warn(&bus->dev, "%d-byte config write to %04x:%02x:%02x.%d offset %#x may corrupt adjacent RW1C bits\n",
16462306a36Sopenharmony_ci			 size, pci_domain_nr(bus), bus->number,
16562306a36Sopenharmony_ci			 PCI_SLOT(devfn), PCI_FUNC(devfn), where);
16662306a36Sopenharmony_ci		bus->unsafe_warn = 1;
16762306a36Sopenharmony_ci	}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
17062306a36Sopenharmony_ci	tmp = readl(addr) & mask;
17162306a36Sopenharmony_ci	tmp |= val << ((where & 0x3) * 8);
17262306a36Sopenharmony_ci	writel(tmp, addr);
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	return PCIBIOS_SUCCESSFUL;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_generic_config_write32);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci/**
17962306a36Sopenharmony_ci * pci_bus_set_ops - Set raw operations of pci bus
18062306a36Sopenharmony_ci * @bus:	pci bus struct
18162306a36Sopenharmony_ci * @ops:	new raw operations
18262306a36Sopenharmony_ci *
18362306a36Sopenharmony_ci * Return previous raw operations
18462306a36Sopenharmony_ci */
18562306a36Sopenharmony_cistruct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	struct pci_ops *old_ops;
18862306a36Sopenharmony_ci	unsigned long flags;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pci_lock, flags);
19162306a36Sopenharmony_ci	old_ops = bus->ops;
19262306a36Sopenharmony_ci	bus->ops = ops;
19362306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pci_lock, flags);
19462306a36Sopenharmony_ci	return old_ops;
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_set_ops);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci/*
19962306a36Sopenharmony_ci * The following routines are to prevent the user from accessing PCI config
20062306a36Sopenharmony_ci * space when it's unsafe to do so.  Some devices require this during BIST and
20162306a36Sopenharmony_ci * we're required to prevent it during D-state transitions.
20262306a36Sopenharmony_ci *
20362306a36Sopenharmony_ci * We have a bit per device to indicate it's blocked and a global wait queue
20462306a36Sopenharmony_ci * for callers to sleep on until devices are unblocked.
20562306a36Sopenharmony_ci */
20662306a36Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(pci_cfg_wait);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cistatic noinline void pci_wait_cfg(struct pci_dev *dev)
20962306a36Sopenharmony_ci	__must_hold(&pci_lock)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	do {
21262306a36Sopenharmony_ci		raw_spin_unlock_irq(&pci_lock);
21362306a36Sopenharmony_ci		wait_event(pci_cfg_wait, !dev->block_cfg_access);
21462306a36Sopenharmony_ci		raw_spin_lock_irq(&pci_lock);
21562306a36Sopenharmony_ci	} while (dev->block_cfg_access);
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/* Returns 0 on success, negative values indicate error. */
21962306a36Sopenharmony_ci#define PCI_USER_READ_CONFIG(size, type)					\
22062306a36Sopenharmony_ciint pci_user_read_config_##size						\
22162306a36Sopenharmony_ci	(struct pci_dev *dev, int pos, type *val)			\
22262306a36Sopenharmony_ci{									\
22362306a36Sopenharmony_ci	int ret = PCIBIOS_SUCCESSFUL;					\
22462306a36Sopenharmony_ci	u32 data = -1;							\
22562306a36Sopenharmony_ci	if (PCI_##size##_BAD)						\
22662306a36Sopenharmony_ci		return -EINVAL;						\
22762306a36Sopenharmony_ci	raw_spin_lock_irq(&pci_lock);				\
22862306a36Sopenharmony_ci	if (unlikely(dev->block_cfg_access))				\
22962306a36Sopenharmony_ci		pci_wait_cfg(dev);					\
23062306a36Sopenharmony_ci	ret = dev->bus->ops->read(dev->bus, dev->devfn,			\
23162306a36Sopenharmony_ci					pos, sizeof(type), &data);	\
23262306a36Sopenharmony_ci	raw_spin_unlock_irq(&pci_lock);				\
23362306a36Sopenharmony_ci	if (ret)							\
23462306a36Sopenharmony_ci		PCI_SET_ERROR_RESPONSE(val);				\
23562306a36Sopenharmony_ci	else								\
23662306a36Sopenharmony_ci		*val = (type)data;					\
23762306a36Sopenharmony_ci	return pcibios_err_to_errno(ret);				\
23862306a36Sopenharmony_ci}									\
23962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_user_read_config_##size);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci/* Returns 0 on success, negative values indicate error. */
24262306a36Sopenharmony_ci#define PCI_USER_WRITE_CONFIG(size, type)				\
24362306a36Sopenharmony_ciint pci_user_write_config_##size					\
24462306a36Sopenharmony_ci	(struct pci_dev *dev, int pos, type val)			\
24562306a36Sopenharmony_ci{									\
24662306a36Sopenharmony_ci	int ret = PCIBIOS_SUCCESSFUL;					\
24762306a36Sopenharmony_ci	if (PCI_##size##_BAD)						\
24862306a36Sopenharmony_ci		return -EINVAL;						\
24962306a36Sopenharmony_ci	raw_spin_lock_irq(&pci_lock);				\
25062306a36Sopenharmony_ci	if (unlikely(dev->block_cfg_access))				\
25162306a36Sopenharmony_ci		pci_wait_cfg(dev);					\
25262306a36Sopenharmony_ci	ret = dev->bus->ops->write(dev->bus, dev->devfn,		\
25362306a36Sopenharmony_ci					pos, sizeof(type), val);	\
25462306a36Sopenharmony_ci	raw_spin_unlock_irq(&pci_lock);				\
25562306a36Sopenharmony_ci	return pcibios_err_to_errno(ret);				\
25662306a36Sopenharmony_ci}									\
25762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_user_write_config_##size);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ciPCI_USER_READ_CONFIG(byte, u8)
26062306a36Sopenharmony_ciPCI_USER_READ_CONFIG(word, u16)
26162306a36Sopenharmony_ciPCI_USER_READ_CONFIG(dword, u32)
26262306a36Sopenharmony_ciPCI_USER_WRITE_CONFIG(byte, u8)
26362306a36Sopenharmony_ciPCI_USER_WRITE_CONFIG(word, u16)
26462306a36Sopenharmony_ciPCI_USER_WRITE_CONFIG(dword, u32)
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci/**
26762306a36Sopenharmony_ci * pci_cfg_access_lock - Lock PCI config reads/writes
26862306a36Sopenharmony_ci * @dev:	pci device struct
26962306a36Sopenharmony_ci *
27062306a36Sopenharmony_ci * When access is locked, any userspace reads or writes to config
27162306a36Sopenharmony_ci * space and concurrent lock requests will sleep until access is
27262306a36Sopenharmony_ci * allowed via pci_cfg_access_unlock() again.
27362306a36Sopenharmony_ci */
27462306a36Sopenharmony_civoid pci_cfg_access_lock(struct pci_dev *dev)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	might_sleep();
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	raw_spin_lock_irq(&pci_lock);
27962306a36Sopenharmony_ci	if (dev->block_cfg_access)
28062306a36Sopenharmony_ci		pci_wait_cfg(dev);
28162306a36Sopenharmony_ci	dev->block_cfg_access = 1;
28262306a36Sopenharmony_ci	raw_spin_unlock_irq(&pci_lock);
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_cfg_access_lock);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci/**
28762306a36Sopenharmony_ci * pci_cfg_access_trylock - try to lock PCI config reads/writes
28862306a36Sopenharmony_ci * @dev:	pci device struct
28962306a36Sopenharmony_ci *
29062306a36Sopenharmony_ci * Same as pci_cfg_access_lock, but will return 0 if access is
29162306a36Sopenharmony_ci * already locked, 1 otherwise. This function can be used from
29262306a36Sopenharmony_ci * atomic contexts.
29362306a36Sopenharmony_ci */
29462306a36Sopenharmony_cibool pci_cfg_access_trylock(struct pci_dev *dev)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	unsigned long flags;
29762306a36Sopenharmony_ci	bool locked = true;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pci_lock, flags);
30062306a36Sopenharmony_ci	if (dev->block_cfg_access)
30162306a36Sopenharmony_ci		locked = false;
30262306a36Sopenharmony_ci	else
30362306a36Sopenharmony_ci		dev->block_cfg_access = 1;
30462306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pci_lock, flags);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	return locked;
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_cfg_access_trylock);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci/**
31162306a36Sopenharmony_ci * pci_cfg_access_unlock - Unlock PCI config reads/writes
31262306a36Sopenharmony_ci * @dev:	pci device struct
31362306a36Sopenharmony_ci *
31462306a36Sopenharmony_ci * This function allows PCI config accesses to resume.
31562306a36Sopenharmony_ci */
31662306a36Sopenharmony_civoid pci_cfg_access_unlock(struct pci_dev *dev)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	unsigned long flags;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pci_lock, flags);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	/*
32362306a36Sopenharmony_ci	 * This indicates a problem in the caller, but we don't need
32462306a36Sopenharmony_ci	 * to kill them, unlike a double-block above.
32562306a36Sopenharmony_ci	 */
32662306a36Sopenharmony_ci	WARN_ON(!dev->block_cfg_access);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	dev->block_cfg_access = 0;
32962306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pci_lock, flags);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	wake_up_all(&pci_cfg_wait);
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cistatic inline int pcie_cap_version(const struct pci_dev *dev)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cibool pcie_cap_has_lnkctl(const struct pci_dev *dev)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	int type = pci_pcie_type(dev);
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	return type == PCI_EXP_TYPE_ENDPOINT ||
34562306a36Sopenharmony_ci	       type == PCI_EXP_TYPE_LEG_END ||
34662306a36Sopenharmony_ci	       type == PCI_EXP_TYPE_ROOT_PORT ||
34762306a36Sopenharmony_ci	       type == PCI_EXP_TYPE_UPSTREAM ||
34862306a36Sopenharmony_ci	       type == PCI_EXP_TYPE_DOWNSTREAM ||
34962306a36Sopenharmony_ci	       type == PCI_EXP_TYPE_PCI_BRIDGE ||
35062306a36Sopenharmony_ci	       type == PCI_EXP_TYPE_PCIE_BRIDGE;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_cibool pcie_cap_has_lnkctl2(const struct pci_dev *dev)
35462306a36Sopenharmony_ci{
35562306a36Sopenharmony_ci	return pcie_cap_has_lnkctl(dev) && pcie_cap_version(dev) > 1;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
35962306a36Sopenharmony_ci{
36062306a36Sopenharmony_ci	return pcie_downstream_port(dev) &&
36162306a36Sopenharmony_ci	       pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT;
36262306a36Sopenharmony_ci}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_cibool pcie_cap_has_rtctl(const struct pci_dev *dev)
36562306a36Sopenharmony_ci{
36662306a36Sopenharmony_ci	int type = pci_pcie_type(dev);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	return type == PCI_EXP_TYPE_ROOT_PORT ||
36962306a36Sopenharmony_ci	       type == PCI_EXP_TYPE_RC_EC;
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistatic bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	if (!pci_is_pcie(dev))
37562306a36Sopenharmony_ci		return false;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	switch (pos) {
37862306a36Sopenharmony_ci	case PCI_EXP_FLAGS:
37962306a36Sopenharmony_ci		return true;
38062306a36Sopenharmony_ci	case PCI_EXP_DEVCAP:
38162306a36Sopenharmony_ci	case PCI_EXP_DEVCTL:
38262306a36Sopenharmony_ci	case PCI_EXP_DEVSTA:
38362306a36Sopenharmony_ci		return true;
38462306a36Sopenharmony_ci	case PCI_EXP_LNKCAP:
38562306a36Sopenharmony_ci	case PCI_EXP_LNKCTL:
38662306a36Sopenharmony_ci	case PCI_EXP_LNKSTA:
38762306a36Sopenharmony_ci		return pcie_cap_has_lnkctl(dev);
38862306a36Sopenharmony_ci	case PCI_EXP_SLTCAP:
38962306a36Sopenharmony_ci	case PCI_EXP_SLTCTL:
39062306a36Sopenharmony_ci	case PCI_EXP_SLTSTA:
39162306a36Sopenharmony_ci		return pcie_cap_has_sltctl(dev);
39262306a36Sopenharmony_ci	case PCI_EXP_RTCTL:
39362306a36Sopenharmony_ci	case PCI_EXP_RTCAP:
39462306a36Sopenharmony_ci	case PCI_EXP_RTSTA:
39562306a36Sopenharmony_ci		return pcie_cap_has_rtctl(dev);
39662306a36Sopenharmony_ci	case PCI_EXP_DEVCAP2:
39762306a36Sopenharmony_ci	case PCI_EXP_DEVCTL2:
39862306a36Sopenharmony_ci		return pcie_cap_version(dev) > 1;
39962306a36Sopenharmony_ci	case PCI_EXP_LNKCAP2:
40062306a36Sopenharmony_ci	case PCI_EXP_LNKCTL2:
40162306a36Sopenharmony_ci	case PCI_EXP_LNKSTA2:
40262306a36Sopenharmony_ci		return pcie_cap_has_lnkctl2(dev);
40362306a36Sopenharmony_ci	default:
40462306a36Sopenharmony_ci		return false;
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci/*
40962306a36Sopenharmony_ci * Note that these accessor functions are only for the "PCI Express
41062306a36Sopenharmony_ci * Capability" (see PCIe spec r3.0, sec 7.8).  They do not apply to the
41162306a36Sopenharmony_ci * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.)
41262306a36Sopenharmony_ci */
41362306a36Sopenharmony_ciint pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	int ret;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	*val = 0;
41862306a36Sopenharmony_ci	if (pos & 1)
41962306a36Sopenharmony_ci		return PCIBIOS_BAD_REGISTER_NUMBER;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	if (pcie_capability_reg_implemented(dev, pos)) {
42262306a36Sopenharmony_ci		ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val);
42362306a36Sopenharmony_ci		/*
42462306a36Sopenharmony_ci		 * Reset *val to 0 if pci_read_config_word() fails; it may
42562306a36Sopenharmony_ci		 * have been written as 0xFFFF (PCI_ERROR_RESPONSE) if the
42662306a36Sopenharmony_ci		 * config read failed on PCI.
42762306a36Sopenharmony_ci		 */
42862306a36Sopenharmony_ci		if (ret)
42962306a36Sopenharmony_ci			*val = 0;
43062306a36Sopenharmony_ci		return ret;
43162306a36Sopenharmony_ci	}
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	/*
43462306a36Sopenharmony_ci	 * For Functions that do not implement the Slot Capabilities,
43562306a36Sopenharmony_ci	 * Slot Status, and Slot Control registers, these spaces must
43662306a36Sopenharmony_ci	 * be hardwired to 0b, with the exception of the Presence Detect
43762306a36Sopenharmony_ci	 * State bit in the Slot Status register of Downstream Ports,
43862306a36Sopenharmony_ci	 * which must be hardwired to 1b.  (PCIe Base Spec 3.0, sec 7.8)
43962306a36Sopenharmony_ci	 */
44062306a36Sopenharmony_ci	if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
44162306a36Sopenharmony_ci	    pos == PCI_EXP_SLTSTA)
44262306a36Sopenharmony_ci		*val = PCI_EXP_SLTSTA_PDS;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	return 0;
44562306a36Sopenharmony_ci}
44662306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_capability_read_word);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ciint pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val)
44962306a36Sopenharmony_ci{
45062306a36Sopenharmony_ci	int ret;
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	*val = 0;
45362306a36Sopenharmony_ci	if (pos & 3)
45462306a36Sopenharmony_ci		return PCIBIOS_BAD_REGISTER_NUMBER;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	if (pcie_capability_reg_implemented(dev, pos)) {
45762306a36Sopenharmony_ci		ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val);
45862306a36Sopenharmony_ci		/*
45962306a36Sopenharmony_ci		 * Reset *val to 0 if pci_read_config_dword() fails; it may
46062306a36Sopenharmony_ci		 * have been written as 0xFFFFFFFF (PCI_ERROR_RESPONSE) if
46162306a36Sopenharmony_ci		 * the config read failed on PCI.
46262306a36Sopenharmony_ci		 */
46362306a36Sopenharmony_ci		if (ret)
46462306a36Sopenharmony_ci			*val = 0;
46562306a36Sopenharmony_ci		return ret;
46662306a36Sopenharmony_ci	}
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
46962306a36Sopenharmony_ci	    pos == PCI_EXP_SLTSTA)
47062306a36Sopenharmony_ci		*val = PCI_EXP_SLTSTA_PDS;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	return 0;
47362306a36Sopenharmony_ci}
47462306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_capability_read_dword);
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ciint pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	if (pos & 1)
47962306a36Sopenharmony_ci		return PCIBIOS_BAD_REGISTER_NUMBER;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	if (!pcie_capability_reg_implemented(dev, pos))
48262306a36Sopenharmony_ci		return 0;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val);
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_capability_write_word);
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ciint pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	if (pos & 3)
49162306a36Sopenharmony_ci		return PCIBIOS_BAD_REGISTER_NUMBER;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	if (!pcie_capability_reg_implemented(dev, pos))
49462306a36Sopenharmony_ci		return 0;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val);
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_capability_write_dword);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ciint pcie_capability_clear_and_set_word_unlocked(struct pci_dev *dev, int pos,
50162306a36Sopenharmony_ci						u16 clear, u16 set)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	int ret;
50462306a36Sopenharmony_ci	u16 val;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	ret = pcie_capability_read_word(dev, pos, &val);
50762306a36Sopenharmony_ci	if (ret)
50862306a36Sopenharmony_ci		return ret;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	val &= ~clear;
51162306a36Sopenharmony_ci	val |= set;
51262306a36Sopenharmony_ci	return pcie_capability_write_word(dev, pos, val);
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_capability_clear_and_set_word_unlocked);
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ciint pcie_capability_clear_and_set_word_locked(struct pci_dev *dev, int pos,
51762306a36Sopenharmony_ci					      u16 clear, u16 set)
51862306a36Sopenharmony_ci{
51962306a36Sopenharmony_ci	unsigned long flags;
52062306a36Sopenharmony_ci	int ret;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	spin_lock_irqsave(&dev->pcie_cap_lock, flags);
52362306a36Sopenharmony_ci	ret = pcie_capability_clear_and_set_word_unlocked(dev, pos, clear, set);
52462306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->pcie_cap_lock, flags);
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	return ret;
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_capability_clear_and_set_word_locked);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ciint pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos,
53162306a36Sopenharmony_ci					u32 clear, u32 set)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	int ret;
53462306a36Sopenharmony_ci	u32 val;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	ret = pcie_capability_read_dword(dev, pos, &val);
53762306a36Sopenharmony_ci	if (ret)
53862306a36Sopenharmony_ci		return ret;
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	val &= ~clear;
54162306a36Sopenharmony_ci	val |= set;
54262306a36Sopenharmony_ci	return pcie_capability_write_dword(dev, pos, val);
54362306a36Sopenharmony_ci}
54462306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_capability_clear_and_set_dword);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ciint pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
54762306a36Sopenharmony_ci{
54862306a36Sopenharmony_ci	if (pci_dev_is_disconnected(dev)) {
54962306a36Sopenharmony_ci		PCI_SET_ERROR_RESPONSE(val);
55062306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
55162306a36Sopenharmony_ci	}
55262306a36Sopenharmony_ci	return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ciEXPORT_SYMBOL(pci_read_config_byte);
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ciint pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	if (pci_dev_is_disconnected(dev)) {
55962306a36Sopenharmony_ci		PCI_SET_ERROR_RESPONSE(val);
56062306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
56162306a36Sopenharmony_ci	}
56262306a36Sopenharmony_ci	return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ciEXPORT_SYMBOL(pci_read_config_word);
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ciint pci_read_config_dword(const struct pci_dev *dev, int where,
56762306a36Sopenharmony_ci					u32 *val)
56862306a36Sopenharmony_ci{
56962306a36Sopenharmony_ci	if (pci_dev_is_disconnected(dev)) {
57062306a36Sopenharmony_ci		PCI_SET_ERROR_RESPONSE(val);
57162306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci	return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ciEXPORT_SYMBOL(pci_read_config_dword);
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ciint pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
57862306a36Sopenharmony_ci{
57962306a36Sopenharmony_ci	if (pci_dev_is_disconnected(dev))
58062306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
58162306a36Sopenharmony_ci	return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
58262306a36Sopenharmony_ci}
58362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_write_config_byte);
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ciint pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
58662306a36Sopenharmony_ci{
58762306a36Sopenharmony_ci	if (pci_dev_is_disconnected(dev))
58862306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
58962306a36Sopenharmony_ci	return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
59062306a36Sopenharmony_ci}
59162306a36Sopenharmony_ciEXPORT_SYMBOL(pci_write_config_word);
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ciint pci_write_config_dword(const struct pci_dev *dev, int where,
59462306a36Sopenharmony_ci					 u32 val)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	if (pci_dev_is_disconnected(dev))
59762306a36Sopenharmony_ci		return PCIBIOS_DEVICE_NOT_FOUND;
59862306a36Sopenharmony_ci	return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
59962306a36Sopenharmony_ci}
60062306a36Sopenharmony_ciEXPORT_SYMBOL(pci_write_config_dword);
601