/* * This interrupt-safe spinlock protects all accesses to PCI * configuration space.
*/
DEFINE_RAW_SPINLOCK(pci_lock);
/* * Wrappers for all PCI configuration access functions. They just check * alignment, do locking and call the low-level functions pointed to * by pci_dev->ops.
*/
int pci_generic_config_write32(struct pci_bus *bus, unsignedint devfn, int where, int size, u32 val)
{ void __iomem *addr;
u32 mask, tmp;
addr = bus->ops->map_bus(bus, devfn, where & ~0x3); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND;
if (size == 4) {
writel(val, addr); return PCIBIOS_SUCCESSFUL;
}
/* * In general, hardware that supports only 32-bit writes on PCI is * not spec-compliant. For example, software may perform a 16-bit * write. If the hardware only supports 32-bit accesses, we must * do a 32-bit read, merge in the 16 bits we intend to write, * followed by a 32-bit write. If the 16 bits we *don't* intend to * write happen to have any RW1C (write-one-to-clear) bits set, we * just inadvertently cleared something we shouldn't have.
*/ if (!bus->unsafe_warn) {
dev_warn(&bus->dev, "%d-byte config write to %04x:%02x:%02x.%d offset %#x may corrupt adjacent RW1C bits\n",
size, pci_domain_nr(bus), bus->number,
PCI_SLOT(devfn), PCI_FUNC(devfn), where);
bus->unsafe_warn = 1;
}
/* * The following routines are to prevent the user from accessing PCI config * space when it's unsafe to do so. Some devices require this during BIST and * we're required to prevent it during D-state transitions. * * We have a bit per device to indicate it's blocked and a global wait queue * for callers to sleep on until devices are unblocked.
*/ static DECLARE_WAIT_QUEUE_HEAD(pci_cfg_wait);
static noinline void pci_wait_cfg(struct pci_dev *dev)
__must_hold(&pci_lock)
{ do {
raw_spin_unlock_irq(&pci_lock);
wait_event(pci_cfg_wait, !dev->block_cfg_access);
raw_spin_lock_irq(&pci_lock);
} while (dev->block_cfg_access);
}
/* Returns 0 on success, negative values indicate error. */ #define PCI_USER_READ_CONFIG(size, type) \ int pci_user_read_config_##size \
(struct pci_dev *dev, int pos, type *val) \
{ \
u32 data = -1; \ int ret; \
\ if (PCI_##size##_BAD) \ return -EINVAL; \
\
raw_spin_lock_irq(&pci_lock); \ if (unlikely(dev->block_cfg_access)) \
pci_wait_cfg(dev); \
ret = dev->bus->ops->read(dev->bus, dev->devfn, \
pos, sizeof(type), &data); \
raw_spin_unlock_irq(&pci_lock); \ if (ret) \
PCI_SET_ERROR_RESPONSE(val); \ else \
*val = (type)data; \
\ return pcibios_err_to_errno(ret); \
} \
EXPORT_SYMBOL_GPL(pci_user_read_config_##size);
/* Returns 0 on success, negative values indicate error. */ #define PCI_USER_WRITE_CONFIG(size, type) \ int pci_user_write_config_##size \
(struct pci_dev *dev, int pos, type val) \
{ \ int ret; \
\ if (PCI_##size##_BAD) \ return -EINVAL; \
\
raw_spin_lock_irq(&pci_lock); \ if (unlikely(dev->block_cfg_access)) \
pci_wait_cfg(dev); \
ret = dev->bus->ops->write(dev->bus, dev->devfn, \
pos, sizeof(type), val); \
raw_spin_unlock_irq(&pci_lock); \
\ return pcibios_err_to_errno(ret); \
} \
EXPORT_SYMBOL_GPL(pci_user_write_config_##size);
/** * pci_cfg_access_lock - Lock PCI config reads/writes * @dev: pci device struct * * When access is locked, any userspace reads or writes to config * space and concurrent lock requests will sleep until access is * allowed via pci_cfg_access_unlock() again.
*/ void pci_cfg_access_lock(struct pci_dev *dev)
{
might_sleep();
raw_spin_lock_irq(&pci_lock); if (dev->block_cfg_access)
pci_wait_cfg(dev);
dev->block_cfg_access = 1;
raw_spin_unlock_irq(&pci_lock);
}
EXPORT_SYMBOL_GPL(pci_cfg_access_lock);
/** * pci_cfg_access_trylock - try to lock PCI config reads/writes * @dev: pci device struct * * Same as pci_cfg_access_lock, but will return 0 if access is * already locked, 1 otherwise. This function can be used from * atomic contexts.
*/ bool pci_cfg_access_trylock(struct pci_dev *dev)
{ unsignedlong flags; bool locked = true;
bool pcie_cap_has_lnkctl(conststruct pci_dev *dev)
{ int type = pci_pcie_type(dev);
return type == PCI_EXP_TYPE_ENDPOINT ||
type == PCI_EXP_TYPE_LEG_END ||
type == PCI_EXP_TYPE_ROOT_PORT ||
type == PCI_EXP_TYPE_UPSTREAM ||
type == PCI_EXP_TYPE_DOWNSTREAM ||
type == PCI_EXP_TYPE_PCI_BRIDGE ||
type == PCI_EXP_TYPE_PCIE_BRIDGE;
}
bool pcie_cap_has_rtctl(conststruct pci_dev *dev)
{ int type = pci_pcie_type(dev);
return type == PCI_EXP_TYPE_ROOT_PORT ||
type == PCI_EXP_TYPE_RC_EC;
}
staticbool pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
{ if (!pci_is_pcie(dev)) returnfalse;
switch (pos) { case PCI_EXP_FLAGS: returntrue; case PCI_EXP_DEVCAP: case PCI_EXP_DEVCTL: case PCI_EXP_DEVSTA: returntrue; case PCI_EXP_LNKCAP: case PCI_EXP_LNKCTL: case PCI_EXP_LNKSTA: return pcie_cap_has_lnkctl(dev); case PCI_EXP_SLTCAP: case PCI_EXP_SLTCTL: case PCI_EXP_SLTSTA: return pcie_cap_has_sltctl(dev); case PCI_EXP_RTCTL: case PCI_EXP_RTCAP: case PCI_EXP_RTSTA: return pcie_cap_has_rtctl(dev); case PCI_EXP_DEVCAP2: case PCI_EXP_DEVCTL2: return pcie_cap_version(dev) > 1; case PCI_EXP_LNKCAP2: case PCI_EXP_LNKCTL2: case PCI_EXP_LNKSTA2: return pcie_cap_has_lnkctl2(dev); default: returnfalse;
}
}
/* * Note that these accessor functions are only for the "PCI Express * Capability" (see PCIe spec r3.0, sec 7.8). They do not apply to the * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.)
*/ int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
{ int ret;
*val = 0; if (pos & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
if (pcie_capability_reg_implemented(dev, pos)) {
ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val); /* * Reset *val to 0 if pci_read_config_word() fails; it may * have been written as 0xFFFF (PCI_ERROR_RESPONSE) if the * config read failed on PCI.
*/ if (ret)
*val = 0; return ret;
}
/* * For Functions that do not implement the Slot Capabilities, * Slot Status, and Slot Control registers, these spaces must * be hardwired to 0b, with the exception of the Presence Detect * State bit in the Slot Status register of Downstream Ports, * which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8)
*/ if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
pos == PCI_EXP_SLTSTA)
*val = PCI_EXP_SLTSTA_PDS;
int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val)
{ int ret;
*val = 0; if (pos & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
if (pcie_capability_reg_implemented(dev, pos)) {
ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val); /* * Reset *val to 0 if pci_read_config_dword() fails; it may * have been written as 0xFFFFFFFF (PCI_ERROR_RESPONSE) if * the config read failed on PCI.
*/ if (ret)
*val = 0; return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.