mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-22 23:04:43 +00:00
PCI changes for the v3.14 merge window:
Resource management - Change pci_bus_region addresses to dma_addr_t (Bjorn Helgaas) - Support 64-bit AGP BARs (Bjorn Helgaas, Yinghai Lu) - Add pci_bus_address() to get bus address of a BAR (Bjorn Helgaas) - Use pci_resource_start() for CPU address of AGP BARs (Bjorn Helgaas) - Enforce bus address limits in resource allocation (Yinghai Lu) - Allocate 64-bit BARs above 4G when possible (Yinghai Lu) - Convert pcibios_resource_to_bus() to take pci_bus, not pci_dev (Yinghai Lu) PCI device hotplug - Major rescan/remove locking update (Rafael J. Wysocki) - Make ioapic builtin only (not modular) (Yinghai Lu) - Fix release/free issues (Yinghai Lu) - Clean up pciehp (Bjorn Helgaas) - Announce pciehp slot info during enumeration (Bjorn Helgaas) MSI - Add pci_msi_vec_count(), pci_msix_vec_count() (Alexander Gordeev) - Add pci_enable_msi_range(), pci_enable_msix_range() (Alexander Gordeev) - Deprecate "tri-state" interfaces: fail/success/fail+info (Alexander Gordeev) - Export MSI mode using attributes, not kobjects (Greg Kroah-Hartman) - Drop "irq" param from *_restore_msi_irqs() (DuanZhenzhong) SR-IOV - Clear NumVFs when disabling SR-IOV in sriov_init() (ethan.zhao) Virtualization - Add support for save/restore of extended capabilities (Alex Williamson) - Add Virtual Channel to save/restore support (Alex Williamson) - Never treat a VF as a multifunction device (Alex Williamson) - Add pci_try_reset_function(), et al (Alex Williamson) AER - Ignore non-PCIe error sources (Betty Dall) - Support ACPI HEST error sources for domains other than 0 (Betty Dall) - Consolidate HEST error source parsers (Bjorn Helgaas) - Add a TLP header print helper (Borislav Petkov) Freescale i.MX6 - Remove unnecessary code (Fabio Estevam) - Make reset-gpio optional (Marek Vasut) - Report "link up" only after link training completes (Marek Vasut) - Start link in Gen1 before negotiating for Gen2 mode (Marek Vasut) - Fix PCIe startup code (Richard Zhu) Marvell MVEBU - Remove duplicate of_clk_get_by_name() call (Andrew Lunn) - Drop writes to bridge Secondary Status register (Jason Gunthorpe) - Obey bridge PCI_COMMAND_MEM and PCI_COMMAND_IO bits (Jason Gunthorpe) - Support a bridge with no IO port window (Jason Gunthorpe) - Use max_t() instead of max(resource_size_t,) (Jingoo Han) - Remove redundant of_match_ptr (Sachin Kamat) - Call pci_ioremap_io() at startup instead of dynamically (Thomas Petazzoni) NVIDIA Tegra - Disable Gen2 for Tegra20 and Tegra30 (Eric Brower) Renesas R-Car - Add runtime PM support (Valentine Barshak) - Fix rcar_pci_probe() return value check (Wei Yongjun) Synopsys DesignWare - Fix crash in dw_msi_teardown_irq() (Bjørn Erik Nilsen) - Remove redundant call to pci_write_config_word() (Bjørn Erik Nilsen) - Fix missing MSI IRQs (Harro Haan) - Add dw_pcie prefix before cfg_read/write (Pratyush Anand) - Fix I/O transfers by using CPU (not realio) address (Pratyush Anand) - Whitespace cleanup (Jingoo Han) EISA - Call put_device() if device_register() fails (Levente Kurusa) - Revert EISA initialization breakage ((Bjorn Helgaas) Miscellaneous - Remove unused code, including PCIe 3.0 interfaces (Stephen Hemminger) - Prevent bus conflicts while checking for bridge apertures (Bjorn Helgaas) - Stop clearing bridge Secondary Status when setting up I/O aperture (Bjorn Helgaas) - Use dev_is_pci() to identify PCI devices (Yijing Wang) - Deprecate DEFINE_PCI_DEVICE_TABLE (Joe Perches) - Update documentation 00-INDEX (Erik Ekman) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJS3ujEAAoJEFmIoMA60/r8A4EQAK9AZSUSVNWvlKdC1PrBfT3w 7fVILx5A4KWsOU8eoFwCPQLrgvUtMltg16yN2tbCjqpKEdrVc36biMO9bwhnXSyZ KopHKMWnn0sza/z2H8mcGy+0azGdWcIjcErX/a8WeS6zyWBjm+yzckrHNVpPu4Ca SpCBhfgBMjKyIZyLtP6juFSH34S2DfQex4oUSyPC+gjqPy5wW/xw/kBxZfOXl+yU P9pQT+geMIc31pETMdG9wd/TT+47YAui4ieSggoVxfVrphCXv6S8mOMCMuQc2bAy MHy9uFm1jbvKZZIYrzJ+9HFiiU/6MNiOO3Ygua52xuSp1Zrcjwi2CLD9/QBXbDVs pTKU5JIO7q43llkQUpIXTwBvEApSZRhuqzXegsMAYIg4AWmbfm/2fXkfWlQThYMp J48blAJZ4t0vhMr9usgwbtdBe8F5euExOxpwH0QMCMABbuu8/B3TLm39+LTcIbsw Efgm3N9iUTyiV5fe9Rr62nflhyqXjTevPl4wbZZe4OOdm0MXZY+/BzuNJhg3wyY8 QKz2J3FB6OR7BCLHCp80l50s5+Ih4F5kmOXwFKjT1D1MFRaNaPDmp9BY6TitU6hg zj55gP4c8x6n3alakbf972Yhgs/4oi1va8cZL+pCYWb8nPO5ldaMiT7QBBLUreQV BtDtC7u/AFWJ5e73+jVO =La1R -----END PGP SIGNATURE----- Merge tag 'pci-v3.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci Pull PCI updates from Bjorn Helgaas: "PCI changes for the v3.14 merge window: Resource management - Change pci_bus_region addresses to dma_addr_t (Bjorn Helgaas) - Support 64-bit AGP BARs (Bjorn Helgaas, Yinghai Lu) - Add pci_bus_address() to get bus address of a BAR (Bjorn Helgaas) - Use pci_resource_start() for CPU address of AGP BARs (Bjorn Helgaas) - Enforce bus address limits in resource allocation (Yinghai Lu) - Allocate 64-bit BARs above 4G when possible (Yinghai Lu) - Convert pcibios_resource_to_bus() to take pci_bus, not pci_dev (Yinghai Lu) PCI device hotplug - Major rescan/remove locking update (Rafael J. Wysocki) - Make ioapic builtin only (not modular) (Yinghai Lu) - Fix release/free issues (Yinghai Lu) - Clean up pciehp (Bjorn Helgaas) - Announce pciehp slot info during enumeration (Bjorn Helgaas) MSI - Add pci_msi_vec_count(), pci_msix_vec_count() (Alexander Gordeev) - Add pci_enable_msi_range(), pci_enable_msix_range() (Alexander Gordeev) - Deprecate "tri-state" interfaces: fail/success/fail+info (Alexander Gordeev) - Export MSI mode using attributes, not kobjects (Greg Kroah-Hartman) - Drop "irq" param from *_restore_msi_irqs() (DuanZhenzhong) SR-IOV - Clear NumVFs when disabling SR-IOV in sriov_init() (ethan.zhao) Virtualization - Add support for save/restore of extended capabilities (Alex Williamson) - Add Virtual Channel to save/restore support (Alex Williamson) - Never treat a VF as a multifunction device (Alex Williamson) - Add pci_try_reset_function(), et al (Alex Williamson) AER - Ignore non-PCIe error sources (Betty Dall) - Support ACPI HEST error sources for domains other than 0 (Betty Dall) - Consolidate HEST error source parsers (Bjorn Helgaas) - Add a TLP header print helper (Borislav Petkov) Freescale i.MX6 - Remove unnecessary code (Fabio Estevam) - Make reset-gpio optional (Marek Vasut) - Report "link up" only after link training completes (Marek Vasut) - Start link in Gen1 before negotiating for Gen2 mode (Marek Vasut) - Fix PCIe startup code (Richard Zhu) Marvell MVEBU - Remove duplicate of_clk_get_by_name() call (Andrew Lunn) - Drop writes to bridge Secondary Status register (Jason Gunthorpe) - Obey bridge PCI_COMMAND_MEM and PCI_COMMAND_IO bits (Jason Gunthorpe) - Support a bridge with no IO port window (Jason Gunthorpe) - Use max_t() instead of max(resource_size_t,) (Jingoo Han) - Remove redundant of_match_ptr (Sachin Kamat) - Call pci_ioremap_io() at startup instead of dynamically (Thomas Petazzoni) NVIDIA Tegra - Disable Gen2 for Tegra20 and Tegra30 (Eric Brower) Renesas R-Car - Add runtime PM support (Valentine Barshak) - Fix rcar_pci_probe() return value check (Wei Yongjun) Synopsys DesignWare - Fix crash in dw_msi_teardown_irq() (Bjørn Erik Nilsen) - Remove redundant call to pci_write_config_word() (Bjørn Erik Nilsen) - Fix missing MSI IRQs (Harro Haan) - Add dw_pcie prefix before cfg_read/write (Pratyush Anand) - Fix I/O transfers by using CPU (not realio) address (Pratyush Anand) - Whitespace cleanup (Jingoo Han) EISA - Call put_device() if device_register() fails (Levente Kurusa) - Revert EISA initialization breakage ((Bjorn Helgaas) Miscellaneous - Remove unused code, including PCIe 3.0 interfaces (Stephen Hemminger) - Prevent bus conflicts while checking for bridge apertures (Bjorn Helgaas) - Stop clearing bridge Secondary Status when setting up I/O aperture (Bjorn Helgaas) - Use dev_is_pci() to identify PCI devices (Yijing Wang) - Deprecate DEFINE_PCI_DEVICE_TABLE (Joe Perches) - Update documentation 00-INDEX (Erik Ekman)" * tag 'pci-v3.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (119 commits) Revert "EISA: Initialize device before its resources" Revert "EISA: Log device resources in dmesg" vfio-pci: Use pci "try" reset interface PCI: Check parent kobject in pci_destroy_dev() xen/pcifront: Use global PCI rescan-remove locking powerpc/eeh: Use global PCI rescan-remove locking PCI: Fix pci_check_and_unmask_intx() comment typos PCI: Add pci_try_reset_function(), pci_try_reset_slot(), pci_try_reset_bus() MPT / PCI: Use pci_stop_and_remove_bus_device_locked() platform / x86: Use global PCI rescan-remove locking PCI: hotplug: Use global PCI rescan-remove locking pcmcia: Use global PCI rescan-remove locking ACPI / hotplug / PCI: Use global PCI rescan-remove locking ACPI / PCI: Use global PCI rescan-remove locking in PCI root hotplug PCI: Add global pci_lock_rescan_remove() PCI: Cleanup pci.h whitespace PCI: Reorder so actual code comes before stubs PCI/AER: Support ACPI HEST AER error sources for PCI domains other than 0 ACPICA: Add helper macros to extract bus/segment numbers from HEST table. PCI: Make local functions static ...
This commit is contained in:
commit
e1ba84597c
109 changed files with 2523 additions and 1998 deletions
|
@ -430,6 +430,32 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
|
|||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos
|
||||
* @dev: the PCI device to operate on
|
||||
* @pos: config space offset of status word
|
||||
* @mask: mask of bit(s) to care about in status word
|
||||
*
|
||||
* Return 1 when mask bit(s) in status word clear, 0 otherwise.
|
||||
*/
|
||||
int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Wait for Transaction Pending bit clean */
|
||||
for (i = 0; i < 4; i++) {
|
||||
u16 status;
|
||||
if (i)
|
||||
msleep((1 << (i - 1)) * 100);
|
||||
|
||||
pci_read_config_word(dev, pos, &status);
|
||||
if (!(status & mask))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_restore_bars - restore a devices BAR values (e.g. after wake-up)
|
||||
* @dev: PCI device to have its BARs restored
|
||||
|
@ -656,6 +682,28 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
|
|||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_wakeup - Wake up a PCI device
|
||||
* @pci_dev: Device to handle.
|
||||
* @ign: ignored parameter
|
||||
*/
|
||||
static int pci_wakeup(struct pci_dev *pci_dev, void *ign)
|
||||
{
|
||||
pci_wakeup_event(pci_dev);
|
||||
pm_request_resume(&pci_dev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_wakeup_bus - Walk given bus and wake up devices on it
|
||||
* @bus: Top bus of the subtree to walk.
|
||||
*/
|
||||
static void pci_wakeup_bus(struct pci_bus *bus)
|
||||
{
|
||||
if (bus)
|
||||
pci_walk_bus(bus, pci_wakeup, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* __pci_start_power_transition - Start power transition of a PCI device
|
||||
* @dev: PCI device to handle.
|
||||
|
@ -835,18 +883,28 @@ EXPORT_SYMBOL(pci_choose_state);
|
|||
#define PCI_EXP_SAVE_REGS 7
|
||||
|
||||
|
||||
static struct pci_cap_saved_state *pci_find_saved_cap(
|
||||
struct pci_dev *pci_dev, char cap)
|
||||
static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev,
|
||||
u16 cap, bool extended)
|
||||
{
|
||||
struct pci_cap_saved_state *tmp;
|
||||
|
||||
hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) {
|
||||
if (tmp->cap.cap_nr == cap)
|
||||
if (tmp->cap.cap_extended == extended && tmp->cap.cap_nr == cap)
|
||||
return tmp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap)
|
||||
{
|
||||
return _pci_find_saved_cap(dev, cap, false);
|
||||
}
|
||||
|
||||
struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, u16 cap)
|
||||
{
|
||||
return _pci_find_saved_cap(dev, cap, true);
|
||||
}
|
||||
|
||||
static int pci_save_pcie_state(struct pci_dev *dev)
|
||||
{
|
||||
int i = 0;
|
||||
|
@ -948,6 +1006,8 @@ pci_save_state(struct pci_dev *dev)
|
|||
return i;
|
||||
if ((i = pci_save_pcix_state(dev)) != 0)
|
||||
return i;
|
||||
if ((i = pci_save_vc_state(dev)) != 0)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1010,6 +1070,7 @@ void pci_restore_state(struct pci_dev *dev)
|
|||
/* PCI Express register must be restored first */
|
||||
pci_restore_pcie_state(dev);
|
||||
pci_restore_ats_state(dev);
|
||||
pci_restore_vc_state(dev);
|
||||
|
||||
pci_restore_config_space(dev);
|
||||
|
||||
|
@ -1071,7 +1132,8 @@ EXPORT_SYMBOL_GPL(pci_store_saved_state);
|
|||
* @dev: PCI device that we're dealing with
|
||||
* @state: Saved state returned from pci_store_saved_state()
|
||||
*/
|
||||
int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)
|
||||
static int pci_load_saved_state(struct pci_dev *dev,
|
||||
struct pci_saved_state *state)
|
||||
{
|
||||
struct pci_cap_saved_data *cap;
|
||||
|
||||
|
@ -1087,7 +1149,7 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)
|
|||
while (cap->size) {
|
||||
struct pci_cap_saved_state *tmp;
|
||||
|
||||
tmp = pci_find_saved_cap(dev, cap->cap_nr);
|
||||
tmp = _pci_find_saved_cap(dev, cap->cap_nr, cap->cap_extended);
|
||||
if (!tmp || tmp->cap.size != cap->size)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1099,7 +1161,6 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)
|
|||
dev->state_saved = true;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_load_saved_state);
|
||||
|
||||
/**
|
||||
* pci_load_and_free_saved_state - Reload the save state pointed to by state,
|
||||
|
@ -1531,27 +1592,6 @@ void pci_pme_wakeup_bus(struct pci_bus *bus)
|
|||
pci_walk_bus(bus, pci_pme_wakeup, (void *)true);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_wakeup - Wake up a PCI device
|
||||
* @pci_dev: Device to handle.
|
||||
* @ign: ignored parameter
|
||||
*/
|
||||
static int pci_wakeup(struct pci_dev *pci_dev, void *ign)
|
||||
{
|
||||
pci_wakeup_event(pci_dev);
|
||||
pm_request_resume(&pci_dev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_wakeup_bus - Walk given bus and wake up devices on it
|
||||
* @bus: Top bus of the subtree to walk.
|
||||
*/
|
||||
void pci_wakeup_bus(struct pci_bus *bus)
|
||||
{
|
||||
if (bus)
|
||||
pci_walk_bus(bus, pci_wakeup, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_pme_capable - check the capability of PCI device to generate PME#
|
||||
|
@ -1765,7 +1805,7 @@ int pci_wake_from_d3(struct pci_dev *dev, bool enable)
|
|||
* If the platform can't manage @dev, return the deepest state from which it
|
||||
* can generate wake events, based on any available PME info.
|
||||
*/
|
||||
pci_power_t pci_target_state(struct pci_dev *dev)
|
||||
static pci_power_t pci_target_state(struct pci_dev *dev)
|
||||
{
|
||||
pci_power_t target_state = PCI_D3hot;
|
||||
|
||||
|
@ -2021,18 +2061,24 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev,
|
|||
}
|
||||
|
||||
/**
|
||||
* pci_add_cap_save_buffer - allocate buffer for saving given capability registers
|
||||
* _pci_add_cap_save_buffer - allocate buffer for saving given
|
||||
* capability registers
|
||||
* @dev: the PCI device
|
||||
* @cap: the capability to allocate the buffer for
|
||||
* @extended: Standard or Extended capability ID
|
||||
* @size: requested size of the buffer
|
||||
*/
|
||||
static int pci_add_cap_save_buffer(
|
||||
struct pci_dev *dev, char cap, unsigned int size)
|
||||
static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
|
||||
bool extended, unsigned int size)
|
||||
{
|
||||
int pos;
|
||||
struct pci_cap_saved_state *save_state;
|
||||
|
||||
pos = pci_find_capability(dev, cap);
|
||||
if (extended)
|
||||
pos = pci_find_ext_capability(dev, cap);
|
||||
else
|
||||
pos = pci_find_capability(dev, cap);
|
||||
|
||||
if (pos <= 0)
|
||||
return 0;
|
||||
|
||||
|
@ -2041,12 +2087,23 @@ static int pci_add_cap_save_buffer(
|
|||
return -ENOMEM;
|
||||
|
||||
save_state->cap.cap_nr = cap;
|
||||
save_state->cap.cap_extended = extended;
|
||||
save_state->cap.size = size;
|
||||
pci_add_saved_cap(dev, save_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size)
|
||||
{
|
||||
return _pci_add_cap_save_buffer(dev, cap, false, size);
|
||||
}
|
||||
|
||||
int pci_add_ext_cap_save_buffer(struct pci_dev *dev, u16 cap, unsigned int size)
|
||||
{
|
||||
return _pci_add_cap_save_buffer(dev, cap, true, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_allocate_cap_save_buffers - allocate buffers for saving capabilities
|
||||
* @dev: the PCI device
|
||||
|
@ -2065,6 +2122,8 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
|
|||
if (error)
|
||||
dev_err(&dev->dev,
|
||||
"unable to preallocate PCI-X save buffer\n");
|
||||
|
||||
pci_allocate_vc_save_buffers(dev);
|
||||
}
|
||||
|
||||
void pci_free_cap_save_buffers(struct pci_dev *dev)
|
||||
|
@ -2110,242 +2169,6 @@ void pci_configure_ari(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_enable_ido - enable ID-based Ordering on a device
|
||||
* @dev: the PCI device
|
||||
* @type: which types of IDO to enable
|
||||
*
|
||||
* Enable ID-based ordering on @dev. @type can contain the bits
|
||||
* %PCI_EXP_IDO_REQUEST and/or %PCI_EXP_IDO_COMPLETION to indicate
|
||||
* which types of transactions are allowed to be re-ordered.
|
||||
*/
|
||||
void pci_enable_ido(struct pci_dev *dev, unsigned long type)
|
||||
{
|
||||
u16 ctrl = 0;
|
||||
|
||||
if (type & PCI_EXP_IDO_REQUEST)
|
||||
ctrl |= PCI_EXP_DEVCTL2_IDO_REQ_EN;
|
||||
if (type & PCI_EXP_IDO_COMPLETION)
|
||||
ctrl |= PCI_EXP_DEVCTL2_IDO_CMP_EN;
|
||||
if (ctrl)
|
||||
pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, ctrl);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_enable_ido);
|
||||
|
||||
/**
|
||||
* pci_disable_ido - disable ID-based ordering on a device
|
||||
* @dev: the PCI device
|
||||
* @type: which types of IDO to disable
|
||||
*/
|
||||
void pci_disable_ido(struct pci_dev *dev, unsigned long type)
|
||||
{
|
||||
u16 ctrl = 0;
|
||||
|
||||
if (type & PCI_EXP_IDO_REQUEST)
|
||||
ctrl |= PCI_EXP_DEVCTL2_IDO_REQ_EN;
|
||||
if (type & PCI_EXP_IDO_COMPLETION)
|
||||
ctrl |= PCI_EXP_DEVCTL2_IDO_CMP_EN;
|
||||
if (ctrl)
|
||||
pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, ctrl);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_disable_ido);
|
||||
|
||||
/**
|
||||
* pci_enable_obff - enable optimized buffer flush/fill
|
||||
* @dev: PCI device
|
||||
* @type: type of signaling to use
|
||||
*
|
||||
* Try to enable @type OBFF signaling on @dev. It will try using WAKE#
|
||||
* signaling if possible, falling back to message signaling only if
|
||||
* WAKE# isn't supported. @type should indicate whether the PCIe link
|
||||
* be brought out of L0s or L1 to send the message. It should be either
|
||||
* %PCI_EXP_OBFF_SIGNAL_ALWAYS or %PCI_OBFF_SIGNAL_L0.
|
||||
*
|
||||
* If your device can benefit from receiving all messages, even at the
|
||||
* power cost of bringing the link back up from a low power state, use
|
||||
* %PCI_EXP_OBFF_SIGNAL_ALWAYS. Otherwise, use %PCI_OBFF_SIGNAL_L0 (the
|
||||
* preferred type).
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, appropriate error number on failure.
|
||||
*/
|
||||
int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
|
||||
{
|
||||
u32 cap;
|
||||
u16 ctrl;
|
||||
int ret;
|
||||
|
||||
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
|
||||
if (!(cap & PCI_EXP_DEVCAP2_OBFF_MASK))
|
||||
return -ENOTSUPP; /* no OBFF support at all */
|
||||
|
||||
/* Make sure the topology supports OBFF as well */
|
||||
if (dev->bus->self) {
|
||||
ret = pci_enable_obff(dev->bus->self, type);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &ctrl);
|
||||
if (cap & PCI_EXP_DEVCAP2_OBFF_WAKE)
|
||||
ctrl |= PCI_EXP_DEVCTL2_OBFF_WAKE_EN;
|
||||
else {
|
||||
switch (type) {
|
||||
case PCI_EXP_OBFF_SIGNAL_L0:
|
||||
if (!(ctrl & PCI_EXP_DEVCTL2_OBFF_WAKE_EN))
|
||||
ctrl |= PCI_EXP_DEVCTL2_OBFF_MSGA_EN;
|
||||
break;
|
||||
case PCI_EXP_OBFF_SIGNAL_ALWAYS:
|
||||
ctrl &= ~PCI_EXP_DEVCTL2_OBFF_WAKE_EN;
|
||||
ctrl |= PCI_EXP_DEVCTL2_OBFF_MSGB_EN;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "bad OBFF signal type\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, ctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_enable_obff);
|
||||
|
||||
/**
|
||||
* pci_disable_obff - disable optimized buffer flush/fill
|
||||
* @dev: PCI device
|
||||
*
|
||||
* Disable OBFF on @dev.
|
||||
*/
|
||||
void pci_disable_obff(struct pci_dev *dev)
|
||||
{
|
||||
pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2,
|
||||
PCI_EXP_DEVCTL2_OBFF_WAKE_EN);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_disable_obff);
|
||||
|
||||
/**
|
||||
* pci_ltr_supported - check whether a device supports LTR
|
||||
* @dev: PCI device
|
||||
*
|
||||
* RETURNS:
|
||||
* True if @dev supports latency tolerance reporting, false otherwise.
|
||||
*/
|
||||
static bool pci_ltr_supported(struct pci_dev *dev)
|
||||
{
|
||||
u32 cap;
|
||||
|
||||
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
|
||||
|
||||
return cap & PCI_EXP_DEVCAP2_LTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_enable_ltr - enable latency tolerance reporting
|
||||
* @dev: PCI device
|
||||
*
|
||||
* Enable LTR on @dev if possible, which means enabling it first on
|
||||
* upstream ports.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, errno on failure.
|
||||
*/
|
||||
int pci_enable_ltr(struct pci_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Only primary function can enable/disable LTR */
|
||||
if (PCI_FUNC(dev->devfn) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!pci_ltr_supported(dev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* Enable upstream ports first */
|
||||
if (dev->bus->self) {
|
||||
ret = pci_enable_ltr(dev->bus->self);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
|
||||
PCI_EXP_DEVCTL2_LTR_EN);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_enable_ltr);
|
||||
|
||||
/**
|
||||
* pci_disable_ltr - disable latency tolerance reporting
|
||||
* @dev: PCI device
|
||||
*/
|
||||
void pci_disable_ltr(struct pci_dev *dev)
|
||||
{
|
||||
/* Only primary function can enable/disable LTR */
|
||||
if (PCI_FUNC(dev->devfn) != 0)
|
||||
return;
|
||||
|
||||
if (!pci_ltr_supported(dev))
|
||||
return;
|
||||
|
||||
pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2,
|
||||
PCI_EXP_DEVCTL2_LTR_EN);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_disable_ltr);
|
||||
|
||||
static int __pci_ltr_scale(int *val)
|
||||
{
|
||||
int scale = 0;
|
||||
|
||||
while (*val > 1023) {
|
||||
*val = (*val + 31) / 32;
|
||||
scale++;
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_set_ltr - set LTR latency values
|
||||
* @dev: PCI device
|
||||
* @snoop_lat_ns: snoop latency in nanoseconds
|
||||
* @nosnoop_lat_ns: nosnoop latency in nanoseconds
|
||||
*
|
||||
* Figure out the scale and set the LTR values accordingly.
|
||||
*/
|
||||
int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns)
|
||||
{
|
||||
int pos, ret, snoop_scale, nosnoop_scale;
|
||||
u16 val;
|
||||
|
||||
if (!pci_ltr_supported(dev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
snoop_scale = __pci_ltr_scale(&snoop_lat_ns);
|
||||
nosnoop_scale = __pci_ltr_scale(&nosnoop_lat_ns);
|
||||
|
||||
if (snoop_lat_ns > PCI_LTR_VALUE_MASK ||
|
||||
nosnoop_lat_ns > PCI_LTR_VALUE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
if ((snoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)) ||
|
||||
(nosnoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)))
|
||||
return -EINVAL;
|
||||
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
|
||||
if (!pos)
|
||||
return -ENOTSUPP;
|
||||
|
||||
val = (snoop_scale << PCI_LTR_SCALE_SHIFT) | snoop_lat_ns;
|
||||
ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_SNOOP_LAT, val);
|
||||
if (ret != 4)
|
||||
return -EIO;
|
||||
|
||||
val = (nosnoop_scale << PCI_LTR_SCALE_SHIFT) | nosnoop_lat_ns;
|
||||
ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_NOSNOOP_LAT, val);
|
||||
if (ret != 4)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_set_ltr);
|
||||
|
||||
static int pci_acs_enable;
|
||||
|
||||
/**
|
||||
|
@ -3138,7 +2961,7 @@ bool pci_check_and_mask_intx(struct pci_dev *dev)
|
|||
EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
|
||||
|
||||
/**
|
||||
* pci_check_and_mask_intx - unmask INTx of no interrupt is pending
|
||||
* pci_check_and_unmask_intx - unmask INTx if no interrupt is pending
|
||||
* @dev: the PCI device to operate on
|
||||
*
|
||||
* Check if the device dev has its INTx line asserted, unmask it if not
|
||||
|
@ -3204,20 +3027,10 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);
|
|||
*/
|
||||
int pci_wait_for_pending_transaction(struct pci_dev *dev)
|
||||
{
|
||||
int i;
|
||||
u16 status;
|
||||
if (!pci_is_pcie(dev))
|
||||
return 1;
|
||||
|
||||
/* Wait for Transaction Pending bit clean */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (i)
|
||||
msleep((1 << (i - 1)) * 100);
|
||||
|
||||
pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status);
|
||||
if (!(status & PCI_EXP_DEVSTA_TRPND))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return pci_wait_for_pending(dev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_TRPND);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_wait_for_pending_transaction);
|
||||
|
||||
|
@ -3244,10 +3057,8 @@ static int pcie_flr(struct pci_dev *dev, int probe)
|
|||
|
||||
static int pci_af_flr(struct pci_dev *dev, int probe)
|
||||
{
|
||||
int i;
|
||||
int pos;
|
||||
u8 cap;
|
||||
u8 status;
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_AF);
|
||||
if (!pos)
|
||||
|
@ -3261,14 +3072,8 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
|
|||
return 0;
|
||||
|
||||
/* Wait for Transaction Pending bit clean */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (i)
|
||||
msleep((1 << (i - 1)) * 100);
|
||||
|
||||
pci_read_config_byte(dev, pos + PCI_AF_STATUS, &status);
|
||||
if (!(status & PCI_AF_STATUS_TP))
|
||||
goto clear;
|
||||
}
|
||||
if (pci_wait_for_pending(dev, PCI_AF_STATUS, PCI_AF_STATUS_TP))
|
||||
goto clear;
|
||||
|
||||
dev_err(&dev->dev, "transaction is not cleared; "
|
||||
"proceeding with reset anyway\n");
|
||||
|
@ -3445,6 +3250,18 @@ static void pci_dev_lock(struct pci_dev *dev)
|
|||
device_lock(&dev->dev);
|
||||
}
|
||||
|
||||
/* Return 1 on successful lock, 0 on contention */
|
||||
static int pci_dev_trylock(struct pci_dev *dev)
|
||||
{
|
||||
if (pci_cfg_access_trylock(dev)) {
|
||||
if (device_trylock(&dev->dev))
|
||||
return 1;
|
||||
pci_cfg_access_unlock(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_dev_unlock(struct pci_dev *dev)
|
||||
{
|
||||
device_unlock(&dev->dev);
|
||||
|
@ -3588,6 +3405,34 @@ int pci_reset_function(struct pci_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pci_reset_function);
|
||||
|
||||
/**
|
||||
* pci_try_reset_function - quiesce and reset a PCI device function
|
||||
* @dev: PCI device to reset
|
||||
*
|
||||
* Same as above, except return -EAGAIN if unable to lock device.
|
||||
*/
|
||||
int pci_try_reset_function(struct pci_dev *dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pci_dev_reset(dev, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pci_dev_save_and_disable(dev);
|
||||
|
||||
if (pci_dev_trylock(dev)) {
|
||||
rc = __pci_dev_reset(dev, 0);
|
||||
pci_dev_unlock(dev);
|
||||
} else
|
||||
rc = -EAGAIN;
|
||||
|
||||
pci_dev_restore(dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_try_reset_function);
|
||||
|
||||
/* Lock devices from the top of the tree down */
|
||||
static void pci_bus_lock(struct pci_bus *bus)
|
||||
{
|
||||
|
@ -3612,6 +3457,32 @@ static void pci_bus_unlock(struct pci_bus *bus)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return 1 on successful lock, 0 on contention */
|
||||
static int pci_bus_trylock(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (!pci_dev_trylock(dev))
|
||||
goto unlock;
|
||||
if (dev->subordinate) {
|
||||
if (!pci_bus_trylock(dev->subordinate)) {
|
||||
pci_dev_unlock(dev);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
unlock:
|
||||
list_for_each_entry_continue_reverse(dev, &bus->devices, bus_list) {
|
||||
if (dev->subordinate)
|
||||
pci_bus_unlock(dev->subordinate);
|
||||
pci_dev_unlock(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Lock devices from the top of the tree down */
|
||||
static void pci_slot_lock(struct pci_slot *slot)
|
||||
{
|
||||
|
@ -3640,6 +3511,37 @@ static void pci_slot_unlock(struct pci_slot *slot)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return 1 on successful lock, 0 on contention */
|
||||
static int pci_slot_trylock(struct pci_slot *slot)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &slot->bus->devices, bus_list) {
|
||||
if (!dev->slot || dev->slot != slot)
|
||||
continue;
|
||||
if (!pci_dev_trylock(dev))
|
||||
goto unlock;
|
||||
if (dev->subordinate) {
|
||||
if (!pci_bus_trylock(dev->subordinate)) {
|
||||
pci_dev_unlock(dev);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
unlock:
|
||||
list_for_each_entry_continue_reverse(dev,
|
||||
&slot->bus->devices, bus_list) {
|
||||
if (!dev->slot || dev->slot != slot)
|
||||
continue;
|
||||
if (dev->subordinate)
|
||||
pci_bus_unlock(dev->subordinate);
|
||||
pci_dev_unlock(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Save and disable devices from the top of the tree down */
|
||||
static void pci_bus_save_and_disable(struct pci_bus *bus)
|
||||
{
|
||||
|
@ -3763,6 +3665,35 @@ int pci_reset_slot(struct pci_slot *slot)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pci_reset_slot);
|
||||
|
||||
/**
|
||||
* pci_try_reset_slot - Try to reset a PCI slot
|
||||
* @slot: PCI slot to reset
|
||||
*
|
||||
* Same as above except return -EAGAIN if the slot cannot be locked
|
||||
*/
|
||||
int pci_try_reset_slot(struct pci_slot *slot)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pci_slot_reset(slot, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pci_slot_save_and_disable(slot);
|
||||
|
||||
if (pci_slot_trylock(slot)) {
|
||||
might_sleep();
|
||||
rc = pci_reset_hotplug_slot(slot->hotplug, 0);
|
||||
pci_slot_unlock(slot);
|
||||
} else
|
||||
rc = -EAGAIN;
|
||||
|
||||
pci_slot_restore(slot);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_try_reset_slot);
|
||||
|
||||
static int pci_bus_reset(struct pci_bus *bus, int probe)
|
||||
{
|
||||
if (!bus->self)
|
||||
|
@ -3821,6 +3752,35 @@ int pci_reset_bus(struct pci_bus *bus)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pci_reset_bus);
|
||||
|
||||
/**
|
||||
* pci_try_reset_bus - Try to reset a PCI bus
|
||||
* @bus: top level PCI bus to reset
|
||||
*
|
||||
* Same as above except return -EAGAIN if the bus cannot be locked
|
||||
*/
|
||||
int pci_try_reset_bus(struct pci_bus *bus)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pci_bus_reset(bus, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pci_bus_save_and_disable(bus);
|
||||
|
||||
if (pci_bus_trylock(bus)) {
|
||||
might_sleep();
|
||||
pci_reset_bridge_secondary_bus(bus->self);
|
||||
pci_bus_unlock(bus);
|
||||
} else
|
||||
rc = -EAGAIN;
|
||||
|
||||
pci_bus_restore(bus);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_try_reset_bus);
|
||||
|
||||
/**
|
||||
* pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
|
||||
* @dev: PCI device to query
|
||||
|
@ -4450,7 +4410,6 @@ EXPORT_SYMBOL(pci_restore_state);
|
|||
EXPORT_SYMBOL(pci_pme_capable);
|
||||
EXPORT_SYMBOL(pci_pme_active);
|
||||
EXPORT_SYMBOL(pci_wake_from_d3);
|
||||
EXPORT_SYMBOL(pci_target_state);
|
||||
EXPORT_SYMBOL(pci_prepare_to_sleep);
|
||||
EXPORT_SYMBOL(pci_back_from_sleep);
|
||||
EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue