162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PCI Bus Services, see include/linux/pci.h for further explanation. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter, 662306a36Sopenharmony_ci * David Mosberger-Tang 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright 1997 -- 2000 Martin Mares <mj@ucw.cz> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/acpi.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/delay.h> 1462306a36Sopenharmony_ci#include <linux/dmi.h> 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/msi.h> 1762306a36Sopenharmony_ci#include <linux/of.h> 1862306a36Sopenharmony_ci#include <linux/pci.h> 1962306a36Sopenharmony_ci#include <linux/pm.h> 2062306a36Sopenharmony_ci#include <linux/slab.h> 2162306a36Sopenharmony_ci#include <linux/module.h> 2262306a36Sopenharmony_ci#include <linux/spinlock.h> 2362306a36Sopenharmony_ci#include <linux/string.h> 2462306a36Sopenharmony_ci#include <linux/log2.h> 2562306a36Sopenharmony_ci#include <linux/logic_pio.h> 2662306a36Sopenharmony_ci#include <linux/pm_wakeup.h> 2762306a36Sopenharmony_ci#include <linux/interrupt.h> 2862306a36Sopenharmony_ci#include <linux/device.h> 2962306a36Sopenharmony_ci#include <linux/pm_runtime.h> 3062306a36Sopenharmony_ci#include <linux/pci_hotplug.h> 3162306a36Sopenharmony_ci#include <linux/vmalloc.h> 3262306a36Sopenharmony_ci#include <asm/dma.h> 3362306a36Sopenharmony_ci#include <linux/aer.h> 3462306a36Sopenharmony_ci#include <linux/bitfield.h> 3562306a36Sopenharmony_ci#include "pci.h" 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciDEFINE_MUTEX(pci_slot_mutex); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciconst char *pci_power_names[] = { 4062306a36Sopenharmony_ci "error", "D0", "D1", "D2", "D3hot", "D3cold", "unknown", 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_power_names); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#ifdef CONFIG_X86_32 4562306a36Sopenharmony_ciint isa_dma_bridge_buggy; 4662306a36Sopenharmony_ciEXPORT_SYMBOL(isa_dma_bridge_buggy); 4762306a36Sopenharmony_ci#endif 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ciint pci_pci_problems; 5062306a36Sopenharmony_ciEXPORT_SYMBOL(pci_pci_problems); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciunsigned int pci_pm_d3hot_delay; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic void pci_pme_list_scan(struct work_struct *work); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic LIST_HEAD(pci_pme_list); 5762306a36Sopenharmony_cistatic DEFINE_MUTEX(pci_pme_list_mutex); 5862306a36Sopenharmony_cistatic DECLARE_DELAYED_WORK(pci_pme_work, pci_pme_list_scan); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistruct pci_pme_device { 6162306a36Sopenharmony_ci struct list_head list; 6262306a36Sopenharmony_ci struct pci_dev *dev; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define PME_TIMEOUT 1000 /* How long between PME checks */ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* 6862306a36Sopenharmony_ci * Following exit from Conventional Reset, devices must be ready within 1 sec 6962306a36Sopenharmony_ci * (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional 7062306a36Sopenharmony_ci * Reset (PCIe r6.0 sec 5.8). 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_ci#define PCI_RESET_WAIT 1000 /* msec */ 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* 7562306a36Sopenharmony_ci * Devices may extend the 1 sec period through Request Retry Status 7662306a36Sopenharmony_ci * completions (PCIe r6.0 sec 2.3.1). The spec does not provide an upper 7762306a36Sopenharmony_ci * limit, but 60 sec ought to be enough for any device to become 7862306a36Sopenharmony_ci * responsive. 7962306a36Sopenharmony_ci */ 8062306a36Sopenharmony_ci#define PCIE_RESET_READY_POLL_MS 60000 /* msec */ 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic void pci_dev_d3_sleep(struct pci_dev *dev) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci unsigned int delay_ms = max(dev->d3hot_delay, pci_pm_d3hot_delay); 8562306a36Sopenharmony_ci unsigned int upper; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci if (delay_ms) { 8862306a36Sopenharmony_ci /* Use a 20% upper bound, 1ms minimum */ 8962306a36Sopenharmony_ci upper = max(DIV_ROUND_CLOSEST(delay_ms, 5), 1U); 9062306a36Sopenharmony_ci usleep_range(delay_ms * USEC_PER_MSEC, 9162306a36Sopenharmony_ci (delay_ms + upper) * USEC_PER_MSEC); 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cibool pci_reset_supported(struct pci_dev *dev) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci return dev->reset_methods[0] != 0; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci#ifdef CONFIG_PCI_DOMAINS 10162306a36Sopenharmony_ciint pci_domains_supported = 1; 10262306a36Sopenharmony_ci#endif 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define DEFAULT_CARDBUS_IO_SIZE (256) 10562306a36Sopenharmony_ci#define DEFAULT_CARDBUS_MEM_SIZE (64*1024*1024) 10662306a36Sopenharmony_ci/* pci=cbmemsize=nnM,cbiosize=nn can override this */ 10762306a36Sopenharmony_ciunsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE; 10862306a36Sopenharmony_ciunsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci#define DEFAULT_HOTPLUG_IO_SIZE (256) 11162306a36Sopenharmony_ci#define DEFAULT_HOTPLUG_MMIO_SIZE (2*1024*1024) 11262306a36Sopenharmony_ci#define DEFAULT_HOTPLUG_MMIO_PREF_SIZE (2*1024*1024) 11362306a36Sopenharmony_ci/* hpiosize=nn can override this */ 11462306a36Sopenharmony_ciunsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE; 11562306a36Sopenharmony_ci/* 11662306a36Sopenharmony_ci * pci=hpmmiosize=nnM overrides non-prefetchable MMIO size, 11762306a36Sopenharmony_ci * pci=hpmmioprefsize=nnM overrides prefetchable MMIO size; 11862306a36Sopenharmony_ci * pci=hpmemsize=nnM overrides both 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ciunsigned long pci_hotplug_mmio_size = DEFAULT_HOTPLUG_MMIO_SIZE; 12162306a36Sopenharmony_ciunsigned long pci_hotplug_mmio_pref_size = DEFAULT_HOTPLUG_MMIO_PREF_SIZE; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#define DEFAULT_HOTPLUG_BUS_SIZE 1 12462306a36Sopenharmony_ciunsigned long pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/* PCIe MPS/MRRS strategy; can be overridden by kernel command-line param */ 12862306a36Sopenharmony_ci#ifdef CONFIG_PCIE_BUS_TUNE_OFF 12962306a36Sopenharmony_cienum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF; 13062306a36Sopenharmony_ci#elif defined CONFIG_PCIE_BUS_SAFE 13162306a36Sopenharmony_cienum pcie_bus_config_types pcie_bus_config = PCIE_BUS_SAFE; 13262306a36Sopenharmony_ci#elif defined CONFIG_PCIE_BUS_PERFORMANCE 13362306a36Sopenharmony_cienum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE; 13462306a36Sopenharmony_ci#elif defined CONFIG_PCIE_BUS_PEER2PEER 13562306a36Sopenharmony_cienum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PEER2PEER; 13662306a36Sopenharmony_ci#else 13762306a36Sopenharmony_cienum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT; 13862306a36Sopenharmony_ci#endif 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/* 14162306a36Sopenharmony_ci * The default CLS is used if arch didn't set CLS explicitly and not 14262306a36Sopenharmony_ci * all pci devices agree on the same value. Arch can override either 14362306a36Sopenharmony_ci * the dfl or actual value as it sees fit. Don't forget this is 14462306a36Sopenharmony_ci * measured in 32-bit words, not bytes. 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_ciu8 pci_dfl_cache_line_size = L1_CACHE_BYTES >> 2; 14762306a36Sopenharmony_ciu8 pci_cache_line_size; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* 15062306a36Sopenharmony_ci * If we set up a device for bus mastering, we need to check the latency 15162306a36Sopenharmony_ci * timer as certain BIOSes forget to set it properly. 15262306a36Sopenharmony_ci */ 15362306a36Sopenharmony_ciunsigned int pcibios_max_latency = 255; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/* If set, the PCIe ARI capability will not be used. */ 15662306a36Sopenharmony_cistatic bool pcie_ari_disabled; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* If set, the PCIe ATS capability will not be used. */ 15962306a36Sopenharmony_cistatic bool pcie_ats_disabled; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci/* If set, the PCI config space of each device is printed during boot. */ 16262306a36Sopenharmony_cibool pci_early_dump; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cibool pci_ats_disabled(void) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci return pcie_ats_disabled; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_ats_disabled); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci/* Disable bridge_d3 for all PCIe ports */ 17162306a36Sopenharmony_cistatic bool pci_bridge_d3_disable; 17262306a36Sopenharmony_ci/* Force bridge_d3 for all PCIe ports */ 17362306a36Sopenharmony_cistatic bool pci_bridge_d3_force; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic int __init pcie_port_pm_setup(char *str) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci if (!strcmp(str, "off")) 17862306a36Sopenharmony_ci pci_bridge_d3_disable = true; 17962306a36Sopenharmony_ci else if (!strcmp(str, "force")) 18062306a36Sopenharmony_ci pci_bridge_d3_force = true; 18162306a36Sopenharmony_ci return 1; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci__setup("pcie_port_pm=", pcie_port_pm_setup); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/** 18662306a36Sopenharmony_ci * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children 18762306a36Sopenharmony_ci * @bus: pointer to PCI bus structure to search 18862306a36Sopenharmony_ci * 18962306a36Sopenharmony_ci * Given a PCI bus, returns the highest PCI bus number present in the set 19062306a36Sopenharmony_ci * including the given PCI bus and its list of child PCI buses. 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_ciunsigned char pci_bus_max_busnr(struct pci_bus *bus) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci struct pci_bus *tmp; 19562306a36Sopenharmony_ci unsigned char max, n; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci max = bus->busn_res.end; 19862306a36Sopenharmony_ci list_for_each_entry(tmp, &bus->children, node) { 19962306a36Sopenharmony_ci n = pci_bus_max_busnr(tmp); 20062306a36Sopenharmony_ci if (n > max) 20162306a36Sopenharmony_ci max = n; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci return max; 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_bus_max_busnr); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/** 20862306a36Sopenharmony_ci * pci_status_get_and_clear_errors - return and clear error bits in PCI_STATUS 20962306a36Sopenharmony_ci * @pdev: the PCI device 21062306a36Sopenharmony_ci * 21162306a36Sopenharmony_ci * Returns error bits set in PCI_STATUS and clears them. 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_ciint pci_status_get_and_clear_errors(struct pci_dev *pdev) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci u16 status; 21662306a36Sopenharmony_ci int ret; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci ret = pci_read_config_word(pdev, PCI_STATUS, &status); 21962306a36Sopenharmony_ci if (ret != PCIBIOS_SUCCESSFUL) 22062306a36Sopenharmony_ci return -EIO; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci status &= PCI_STATUS_ERROR_BITS; 22362306a36Sopenharmony_ci if (status) 22462306a36Sopenharmony_ci pci_write_config_word(pdev, PCI_STATUS, status); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return status; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_status_get_and_clear_errors); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci#ifdef CONFIG_HAS_IOMEM 23162306a36Sopenharmony_cistatic void __iomem *__pci_ioremap_resource(struct pci_dev *pdev, int bar, 23262306a36Sopenharmony_ci bool write_combine) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci struct resource *res = &pdev->resource[bar]; 23562306a36Sopenharmony_ci resource_size_t start = res->start; 23662306a36Sopenharmony_ci resource_size_t size = resource_size(res); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* 23962306a36Sopenharmony_ci * Make sure the BAR is actually a memory resource, not an IO resource 24062306a36Sopenharmony_ci */ 24162306a36Sopenharmony_ci if (res->flags & IORESOURCE_UNSET || !(res->flags & IORESOURCE_MEM)) { 24262306a36Sopenharmony_ci pci_err(pdev, "can't ioremap BAR %d: %pR\n", bar, res); 24362306a36Sopenharmony_ci return NULL; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci if (write_combine) 24762306a36Sopenharmony_ci return ioremap_wc(start, size); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return ioremap(start, size); 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_civoid __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci return __pci_ioremap_resource(pdev, bar, false); 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_ioremap_bar); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_civoid __iomem *pci_ioremap_wc_bar(struct pci_dev *pdev, int bar) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci return __pci_ioremap_resource(pdev, bar, true); 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_ioremap_wc_bar); 26362306a36Sopenharmony_ci#endif 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci/** 26662306a36Sopenharmony_ci * pci_dev_str_match_path - test if a path string matches a device 26762306a36Sopenharmony_ci * @dev: the PCI device to test 26862306a36Sopenharmony_ci * @path: string to match the device against 26962306a36Sopenharmony_ci * @endptr: pointer to the string after the match 27062306a36Sopenharmony_ci * 27162306a36Sopenharmony_ci * Test if a string (typically from a kernel parameter) formatted as a 27262306a36Sopenharmony_ci * path of device/function addresses matches a PCI device. The string must 27362306a36Sopenharmony_ci * be of the form: 27462306a36Sopenharmony_ci * 27562306a36Sopenharmony_ci * [<domain>:]<bus>:<device>.<func>[/<device>.<func>]* 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * A path for a device can be obtained using 'lspci -t'. Using a path 27862306a36Sopenharmony_ci * is more robust against bus renumbering than using only a single bus, 27962306a36Sopenharmony_ci * device and function address. 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci * Returns 1 if the string matches the device, 0 if it does not and 28262306a36Sopenharmony_ci * a negative error code if it fails to parse the string. 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_cistatic int pci_dev_str_match_path(struct pci_dev *dev, const char *path, 28562306a36Sopenharmony_ci const char **endptr) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci int ret; 28862306a36Sopenharmony_ci unsigned int seg, bus, slot, func; 28962306a36Sopenharmony_ci char *wpath, *p; 29062306a36Sopenharmony_ci char end; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci *endptr = strchrnul(path, ';'); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci wpath = kmemdup_nul(path, *endptr - path, GFP_ATOMIC); 29562306a36Sopenharmony_ci if (!wpath) 29662306a36Sopenharmony_ci return -ENOMEM; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci while (1) { 29962306a36Sopenharmony_ci p = strrchr(wpath, '/'); 30062306a36Sopenharmony_ci if (!p) 30162306a36Sopenharmony_ci break; 30262306a36Sopenharmony_ci ret = sscanf(p, "/%x.%x%c", &slot, &func, &end); 30362306a36Sopenharmony_ci if (ret != 2) { 30462306a36Sopenharmony_ci ret = -EINVAL; 30562306a36Sopenharmony_ci goto free_and_exit; 30662306a36Sopenharmony_ci } 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (dev->devfn != PCI_DEVFN(slot, func)) { 30962306a36Sopenharmony_ci ret = 0; 31062306a36Sopenharmony_ci goto free_and_exit; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* 31462306a36Sopenharmony_ci * Note: we don't need to get a reference to the upstream 31562306a36Sopenharmony_ci * bridge because we hold a reference to the top level 31662306a36Sopenharmony_ci * device which should hold a reference to the bridge, 31762306a36Sopenharmony_ci * and so on. 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ci dev = pci_upstream_bridge(dev); 32062306a36Sopenharmony_ci if (!dev) { 32162306a36Sopenharmony_ci ret = 0; 32262306a36Sopenharmony_ci goto free_and_exit; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci *p = 0; 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci ret = sscanf(wpath, "%x:%x:%x.%x%c", &seg, &bus, &slot, 32962306a36Sopenharmony_ci &func, &end); 33062306a36Sopenharmony_ci if (ret != 4) { 33162306a36Sopenharmony_ci seg = 0; 33262306a36Sopenharmony_ci ret = sscanf(wpath, "%x:%x.%x%c", &bus, &slot, &func, &end); 33362306a36Sopenharmony_ci if (ret != 3) { 33462306a36Sopenharmony_ci ret = -EINVAL; 33562306a36Sopenharmony_ci goto free_and_exit; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci ret = (seg == pci_domain_nr(dev->bus) && 34062306a36Sopenharmony_ci bus == dev->bus->number && 34162306a36Sopenharmony_ci dev->devfn == PCI_DEVFN(slot, func)); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cifree_and_exit: 34462306a36Sopenharmony_ci kfree(wpath); 34562306a36Sopenharmony_ci return ret; 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci/** 34962306a36Sopenharmony_ci * pci_dev_str_match - test if a string matches a device 35062306a36Sopenharmony_ci * @dev: the PCI device to test 35162306a36Sopenharmony_ci * @p: string to match the device against 35262306a36Sopenharmony_ci * @endptr: pointer to the string after the match 35362306a36Sopenharmony_ci * 35462306a36Sopenharmony_ci * Test if a string (typically from a kernel parameter) matches a specified 35562306a36Sopenharmony_ci * PCI device. The string may be of one of the following formats: 35662306a36Sopenharmony_ci * 35762306a36Sopenharmony_ci * [<domain>:]<bus>:<device>.<func>[/<device>.<func>]* 35862306a36Sopenharmony_ci * pci:<vendor>:<device>[:<subvendor>:<subdevice>] 35962306a36Sopenharmony_ci * 36062306a36Sopenharmony_ci * The first format specifies a PCI bus/device/function address which 36162306a36Sopenharmony_ci * may change if new hardware is inserted, if motherboard firmware changes, 36262306a36Sopenharmony_ci * or due to changes caused in kernel parameters. If the domain is 36362306a36Sopenharmony_ci * left unspecified, it is taken to be 0. In order to be robust against 36462306a36Sopenharmony_ci * bus renumbering issues, a path of PCI device/function numbers may be used 36562306a36Sopenharmony_ci * to address the specific device. The path for a device can be determined 36662306a36Sopenharmony_ci * through the use of 'lspci -t'. 36762306a36Sopenharmony_ci * 36862306a36Sopenharmony_ci * The second format matches devices using IDs in the configuration 36962306a36Sopenharmony_ci * space which may match multiple devices in the system. A value of 0 37062306a36Sopenharmony_ci * for any field will match all devices. (Note: this differs from 37162306a36Sopenharmony_ci * in-kernel code that uses PCI_ANY_ID which is ~0; this is for 37262306a36Sopenharmony_ci * legacy reasons and convenience so users don't have to specify 37362306a36Sopenharmony_ci * FFFFFFFFs on the command line.) 37462306a36Sopenharmony_ci * 37562306a36Sopenharmony_ci * Returns 1 if the string matches the device, 0 if it does not and 37662306a36Sopenharmony_ci * a negative error code if the string cannot be parsed. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_cistatic int pci_dev_str_match(struct pci_dev *dev, const char *p, 37962306a36Sopenharmony_ci const char **endptr) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci int ret; 38262306a36Sopenharmony_ci int count; 38362306a36Sopenharmony_ci unsigned short vendor, device, subsystem_vendor, subsystem_device; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci if (strncmp(p, "pci:", 4) == 0) { 38662306a36Sopenharmony_ci /* PCI vendor/device (subvendor/subdevice) IDs are specified */ 38762306a36Sopenharmony_ci p += 4; 38862306a36Sopenharmony_ci ret = sscanf(p, "%hx:%hx:%hx:%hx%n", &vendor, &device, 38962306a36Sopenharmony_ci &subsystem_vendor, &subsystem_device, &count); 39062306a36Sopenharmony_ci if (ret != 4) { 39162306a36Sopenharmony_ci ret = sscanf(p, "%hx:%hx%n", &vendor, &device, &count); 39262306a36Sopenharmony_ci if (ret != 2) 39362306a36Sopenharmony_ci return -EINVAL; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci subsystem_vendor = 0; 39662306a36Sopenharmony_ci subsystem_device = 0; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci p += count; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci if ((!vendor || vendor == dev->vendor) && 40262306a36Sopenharmony_ci (!device || device == dev->device) && 40362306a36Sopenharmony_ci (!subsystem_vendor || 40462306a36Sopenharmony_ci subsystem_vendor == dev->subsystem_vendor) && 40562306a36Sopenharmony_ci (!subsystem_device || 40662306a36Sopenharmony_ci subsystem_device == dev->subsystem_device)) 40762306a36Sopenharmony_ci goto found; 40862306a36Sopenharmony_ci } else { 40962306a36Sopenharmony_ci /* 41062306a36Sopenharmony_ci * PCI Bus, Device, Function IDs are specified 41162306a36Sopenharmony_ci * (optionally, may include a path of devfns following it) 41262306a36Sopenharmony_ci */ 41362306a36Sopenharmony_ci ret = pci_dev_str_match_path(dev, p, &p); 41462306a36Sopenharmony_ci if (ret < 0) 41562306a36Sopenharmony_ci return ret; 41662306a36Sopenharmony_ci else if (ret) 41762306a36Sopenharmony_ci goto found; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci *endptr = p; 42162306a36Sopenharmony_ci return 0; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cifound: 42462306a36Sopenharmony_ci *endptr = p; 42562306a36Sopenharmony_ci return 1; 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic u8 __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn, 42962306a36Sopenharmony_ci u8 pos, int cap, int *ttl) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci u8 id; 43262306a36Sopenharmony_ci u16 ent; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci pci_bus_read_config_byte(bus, devfn, pos, &pos); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci while ((*ttl)--) { 43762306a36Sopenharmony_ci if (pos < 0x40) 43862306a36Sopenharmony_ci break; 43962306a36Sopenharmony_ci pos &= ~3; 44062306a36Sopenharmony_ci pci_bus_read_config_word(bus, devfn, pos, &ent); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci id = ent & 0xff; 44362306a36Sopenharmony_ci if (id == 0xff) 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci if (id == cap) 44662306a36Sopenharmony_ci return pos; 44762306a36Sopenharmony_ci pos = (ent >> 8); 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci return 0; 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic u8 __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, 45362306a36Sopenharmony_ci u8 pos, int cap) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci int ttl = PCI_FIND_CAP_TTL; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl); 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ciu8 pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci return __pci_find_next_cap(dev->bus, dev->devfn, 46362306a36Sopenharmony_ci pos + PCI_CAP_LIST_NEXT, cap); 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_find_next_capability); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic u8 __pci_bus_find_cap_start(struct pci_bus *bus, 46862306a36Sopenharmony_ci unsigned int devfn, u8 hdr_type) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci u16 status; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); 47362306a36Sopenharmony_ci if (!(status & PCI_STATUS_CAP_LIST)) 47462306a36Sopenharmony_ci return 0; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci switch (hdr_type) { 47762306a36Sopenharmony_ci case PCI_HEADER_TYPE_NORMAL: 47862306a36Sopenharmony_ci case PCI_HEADER_TYPE_BRIDGE: 47962306a36Sopenharmony_ci return PCI_CAPABILITY_LIST; 48062306a36Sopenharmony_ci case PCI_HEADER_TYPE_CARDBUS: 48162306a36Sopenharmony_ci return PCI_CB_CAPABILITY_LIST; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci return 0; 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci/** 48862306a36Sopenharmony_ci * pci_find_capability - query for devices' capabilities 48962306a36Sopenharmony_ci * @dev: PCI device to query 49062306a36Sopenharmony_ci * @cap: capability code 49162306a36Sopenharmony_ci * 49262306a36Sopenharmony_ci * Tell if a device supports a given PCI capability. 49362306a36Sopenharmony_ci * Returns the address of the requested capability structure within the 49462306a36Sopenharmony_ci * device's PCI configuration space or 0 in case the device does not 49562306a36Sopenharmony_ci * support it. Possible values for @cap include: 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * %PCI_CAP_ID_PM Power Management 49862306a36Sopenharmony_ci * %PCI_CAP_ID_AGP Accelerated Graphics Port 49962306a36Sopenharmony_ci * %PCI_CAP_ID_VPD Vital Product Data 50062306a36Sopenharmony_ci * %PCI_CAP_ID_SLOTID Slot Identification 50162306a36Sopenharmony_ci * %PCI_CAP_ID_MSI Message Signalled Interrupts 50262306a36Sopenharmony_ci * %PCI_CAP_ID_CHSWP CompactPCI HotSwap 50362306a36Sopenharmony_ci * %PCI_CAP_ID_PCIX PCI-X 50462306a36Sopenharmony_ci * %PCI_CAP_ID_EXP PCI Express 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_ciu8 pci_find_capability(struct pci_dev *dev, int cap) 50762306a36Sopenharmony_ci{ 50862306a36Sopenharmony_ci u8 pos; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type); 51162306a36Sopenharmony_ci if (pos) 51262306a36Sopenharmony_ci pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return pos; 51562306a36Sopenharmony_ci} 51662306a36Sopenharmony_ciEXPORT_SYMBOL(pci_find_capability); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci/** 51962306a36Sopenharmony_ci * pci_bus_find_capability - query for devices' capabilities 52062306a36Sopenharmony_ci * @bus: the PCI bus to query 52162306a36Sopenharmony_ci * @devfn: PCI device to query 52262306a36Sopenharmony_ci * @cap: capability code 52362306a36Sopenharmony_ci * 52462306a36Sopenharmony_ci * Like pci_find_capability() but works for PCI devices that do not have a 52562306a36Sopenharmony_ci * pci_dev structure set up yet. 52662306a36Sopenharmony_ci * 52762306a36Sopenharmony_ci * Returns the address of the requested capability structure within the 52862306a36Sopenharmony_ci * device's PCI configuration space or 0 in case the device does not 52962306a36Sopenharmony_ci * support it. 53062306a36Sopenharmony_ci */ 53162306a36Sopenharmony_ciu8 pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci u8 hdr_type, pos; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci pos = __pci_bus_find_cap_start(bus, devfn, hdr_type & 0x7f); 53862306a36Sopenharmony_ci if (pos) 53962306a36Sopenharmony_ci pos = __pci_find_next_cap(bus, devfn, pos, cap); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci return pos; 54262306a36Sopenharmony_ci} 54362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_find_capability); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci/** 54662306a36Sopenharmony_ci * pci_find_next_ext_capability - Find an extended capability 54762306a36Sopenharmony_ci * @dev: PCI device to query 54862306a36Sopenharmony_ci * @start: address at which to start looking (0 to start at beginning of list) 54962306a36Sopenharmony_ci * @cap: capability code 55062306a36Sopenharmony_ci * 55162306a36Sopenharmony_ci * Returns the address of the next matching extended capability structure 55262306a36Sopenharmony_ci * within the device's PCI configuration space or 0 if the device does 55362306a36Sopenharmony_ci * not support it. Some capabilities can occur several times, e.g., the 55462306a36Sopenharmony_ci * vendor-specific capability, and this provides a way to find them all. 55562306a36Sopenharmony_ci */ 55662306a36Sopenharmony_ciu16 pci_find_next_ext_capability(struct pci_dev *dev, u16 start, int cap) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci u32 header; 55962306a36Sopenharmony_ci int ttl; 56062306a36Sopenharmony_ci u16 pos = PCI_CFG_SPACE_SIZE; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci /* minimum 8 bytes per capability */ 56362306a36Sopenharmony_ci ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (dev->cfg_size <= PCI_CFG_SPACE_SIZE) 56662306a36Sopenharmony_ci return 0; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci if (start) 56962306a36Sopenharmony_ci pos = start; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL) 57262306a36Sopenharmony_ci return 0; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* 57562306a36Sopenharmony_ci * If we have no capabilities, this is indicated by cap ID, 57662306a36Sopenharmony_ci * cap version and next pointer all being 0. 57762306a36Sopenharmony_ci */ 57862306a36Sopenharmony_ci if (header == 0) 57962306a36Sopenharmony_ci return 0; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci while (ttl-- > 0) { 58262306a36Sopenharmony_ci if (PCI_EXT_CAP_ID(header) == cap && pos != start) 58362306a36Sopenharmony_ci return pos; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci pos = PCI_EXT_CAP_NEXT(header); 58662306a36Sopenharmony_ci if (pos < PCI_CFG_SPACE_SIZE) 58762306a36Sopenharmony_ci break; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL) 59062306a36Sopenharmony_ci break; 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci return 0; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_find_next_ext_capability); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci/** 59862306a36Sopenharmony_ci * pci_find_ext_capability - Find an extended capability 59962306a36Sopenharmony_ci * @dev: PCI device to query 60062306a36Sopenharmony_ci * @cap: capability code 60162306a36Sopenharmony_ci * 60262306a36Sopenharmony_ci * Returns the address of the requested extended capability structure 60362306a36Sopenharmony_ci * within the device's PCI configuration space or 0 if the device does 60462306a36Sopenharmony_ci * not support it. Possible values for @cap include: 60562306a36Sopenharmony_ci * 60662306a36Sopenharmony_ci * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting 60762306a36Sopenharmony_ci * %PCI_EXT_CAP_ID_VC Virtual Channel 60862306a36Sopenharmony_ci * %PCI_EXT_CAP_ID_DSN Device Serial Number 60962306a36Sopenharmony_ci * %PCI_EXT_CAP_ID_PWR Power Budgeting 61062306a36Sopenharmony_ci */ 61162306a36Sopenharmony_ciu16 pci_find_ext_capability(struct pci_dev *dev, int cap) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci return pci_find_next_ext_capability(dev, 0, cap); 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_find_ext_capability); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci/** 61862306a36Sopenharmony_ci * pci_get_dsn - Read and return the 8-byte Device Serial Number 61962306a36Sopenharmony_ci * @dev: PCI device to query 62062306a36Sopenharmony_ci * 62162306a36Sopenharmony_ci * Looks up the PCI_EXT_CAP_ID_DSN and reads the 8 bytes of the Device Serial 62262306a36Sopenharmony_ci * Number. 62362306a36Sopenharmony_ci * 62462306a36Sopenharmony_ci * Returns the DSN, or zero if the capability does not exist. 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_ciu64 pci_get_dsn(struct pci_dev *dev) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci u32 dword; 62962306a36Sopenharmony_ci u64 dsn; 63062306a36Sopenharmony_ci int pos; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DSN); 63362306a36Sopenharmony_ci if (!pos) 63462306a36Sopenharmony_ci return 0; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* 63762306a36Sopenharmony_ci * The Device Serial Number is two dwords offset 4 bytes from the 63862306a36Sopenharmony_ci * capability position. The specification says that the first dword is 63962306a36Sopenharmony_ci * the lower half, and the second dword is the upper half. 64062306a36Sopenharmony_ci */ 64162306a36Sopenharmony_ci pos += 4; 64262306a36Sopenharmony_ci pci_read_config_dword(dev, pos, &dword); 64362306a36Sopenharmony_ci dsn = (u64)dword; 64462306a36Sopenharmony_ci pci_read_config_dword(dev, pos + 4, &dword); 64562306a36Sopenharmony_ci dsn |= ((u64)dword) << 32; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci return dsn; 64862306a36Sopenharmony_ci} 64962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_get_dsn); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic u8 __pci_find_next_ht_cap(struct pci_dev *dev, u8 pos, int ht_cap) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci int rc, ttl = PCI_FIND_CAP_TTL; 65462306a36Sopenharmony_ci u8 cap, mask; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (ht_cap == HT_CAPTYPE_SLAVE || ht_cap == HT_CAPTYPE_HOST) 65762306a36Sopenharmony_ci mask = HT_3BIT_CAP_MASK; 65862306a36Sopenharmony_ci else 65962306a36Sopenharmony_ci mask = HT_5BIT_CAP_MASK; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos, 66262306a36Sopenharmony_ci PCI_CAP_ID_HT, &ttl); 66362306a36Sopenharmony_ci while (pos) { 66462306a36Sopenharmony_ci rc = pci_read_config_byte(dev, pos + 3, &cap); 66562306a36Sopenharmony_ci if (rc != PCIBIOS_SUCCESSFUL) 66662306a36Sopenharmony_ci return 0; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if ((cap & mask) == ht_cap) 66962306a36Sopenharmony_ci return pos; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, 67262306a36Sopenharmony_ci pos + PCI_CAP_LIST_NEXT, 67362306a36Sopenharmony_ci PCI_CAP_ID_HT, &ttl); 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci return 0; 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci/** 68062306a36Sopenharmony_ci * pci_find_next_ht_capability - query a device's HyperTransport capabilities 68162306a36Sopenharmony_ci * @dev: PCI device to query 68262306a36Sopenharmony_ci * @pos: Position from which to continue searching 68362306a36Sopenharmony_ci * @ht_cap: HyperTransport capability code 68462306a36Sopenharmony_ci * 68562306a36Sopenharmony_ci * To be used in conjunction with pci_find_ht_capability() to search for 68662306a36Sopenharmony_ci * all capabilities matching @ht_cap. @pos should always be a value returned 68762306a36Sopenharmony_ci * from pci_find_ht_capability(). 68862306a36Sopenharmony_ci * 68962306a36Sopenharmony_ci * NB. To be 100% safe against broken PCI devices, the caller should take 69062306a36Sopenharmony_ci * steps to avoid an infinite loop. 69162306a36Sopenharmony_ci */ 69262306a36Sopenharmony_ciu8 pci_find_next_ht_capability(struct pci_dev *dev, u8 pos, int ht_cap) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci return __pci_find_next_ht_cap(dev, pos + PCI_CAP_LIST_NEXT, ht_cap); 69562306a36Sopenharmony_ci} 69662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_find_next_ht_capability); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci/** 69962306a36Sopenharmony_ci * pci_find_ht_capability - query a device's HyperTransport capabilities 70062306a36Sopenharmony_ci * @dev: PCI device to query 70162306a36Sopenharmony_ci * @ht_cap: HyperTransport capability code 70262306a36Sopenharmony_ci * 70362306a36Sopenharmony_ci * Tell if a device supports a given HyperTransport capability. 70462306a36Sopenharmony_ci * Returns an address within the device's PCI configuration space 70562306a36Sopenharmony_ci * or 0 in case the device does not support the request capability. 70662306a36Sopenharmony_ci * The address points to the PCI capability, of type PCI_CAP_ID_HT, 70762306a36Sopenharmony_ci * which has a HyperTransport capability matching @ht_cap. 70862306a36Sopenharmony_ci */ 70962306a36Sopenharmony_ciu8 pci_find_ht_capability(struct pci_dev *dev, int ht_cap) 71062306a36Sopenharmony_ci{ 71162306a36Sopenharmony_ci u8 pos; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type); 71462306a36Sopenharmony_ci if (pos) 71562306a36Sopenharmony_ci pos = __pci_find_next_ht_cap(dev, pos, ht_cap); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci return pos; 71862306a36Sopenharmony_ci} 71962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_find_ht_capability); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci/** 72262306a36Sopenharmony_ci * pci_find_vsec_capability - Find a vendor-specific extended capability 72362306a36Sopenharmony_ci * @dev: PCI device to query 72462306a36Sopenharmony_ci * @vendor: Vendor ID for which capability is defined 72562306a36Sopenharmony_ci * @cap: Vendor-specific capability ID 72662306a36Sopenharmony_ci * 72762306a36Sopenharmony_ci * If @dev has Vendor ID @vendor, search for a VSEC capability with 72862306a36Sopenharmony_ci * VSEC ID @cap. If found, return the capability offset in 72962306a36Sopenharmony_ci * config space; otherwise return 0. 73062306a36Sopenharmony_ci */ 73162306a36Sopenharmony_ciu16 pci_find_vsec_capability(struct pci_dev *dev, u16 vendor, int cap) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci u16 vsec = 0; 73462306a36Sopenharmony_ci u32 header; 73562306a36Sopenharmony_ci int ret; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci if (vendor != dev->vendor) 73862306a36Sopenharmony_ci return 0; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci while ((vsec = pci_find_next_ext_capability(dev, vsec, 74162306a36Sopenharmony_ci PCI_EXT_CAP_ID_VNDR))) { 74262306a36Sopenharmony_ci ret = pci_read_config_dword(dev, vsec + PCI_VNDR_HEADER, &header); 74362306a36Sopenharmony_ci if (ret != PCIBIOS_SUCCESSFUL) 74462306a36Sopenharmony_ci continue; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci if (PCI_VNDR_HEADER_ID(header) == cap) 74762306a36Sopenharmony_ci return vsec; 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci return 0; 75162306a36Sopenharmony_ci} 75262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_find_vsec_capability); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci/** 75562306a36Sopenharmony_ci * pci_find_dvsec_capability - Find DVSEC for vendor 75662306a36Sopenharmony_ci * @dev: PCI device to query 75762306a36Sopenharmony_ci * @vendor: Vendor ID to match for the DVSEC 75862306a36Sopenharmony_ci * @dvsec: Designated Vendor-specific capability ID 75962306a36Sopenharmony_ci * 76062306a36Sopenharmony_ci * If DVSEC has Vendor ID @vendor and DVSEC ID @dvsec return the capability 76162306a36Sopenharmony_ci * offset in config space; otherwise return 0. 76262306a36Sopenharmony_ci */ 76362306a36Sopenharmony_ciu16 pci_find_dvsec_capability(struct pci_dev *dev, u16 vendor, u16 dvsec) 76462306a36Sopenharmony_ci{ 76562306a36Sopenharmony_ci int pos; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DVSEC); 76862306a36Sopenharmony_ci if (!pos) 76962306a36Sopenharmony_ci return 0; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci while (pos) { 77262306a36Sopenharmony_ci u16 v, id; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci pci_read_config_word(dev, pos + PCI_DVSEC_HEADER1, &v); 77562306a36Sopenharmony_ci pci_read_config_word(dev, pos + PCI_DVSEC_HEADER2, &id); 77662306a36Sopenharmony_ci if (vendor == v && dvsec == id) 77762306a36Sopenharmony_ci return pos; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci pos = pci_find_next_ext_capability(dev, pos, PCI_EXT_CAP_ID_DVSEC); 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci return 0; 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_find_dvsec_capability); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci/** 78762306a36Sopenharmony_ci * pci_find_parent_resource - return resource region of parent bus of given 78862306a36Sopenharmony_ci * region 78962306a36Sopenharmony_ci * @dev: PCI device structure contains resources to be searched 79062306a36Sopenharmony_ci * @res: child resource record for which parent is sought 79162306a36Sopenharmony_ci * 79262306a36Sopenharmony_ci * For given resource region of given device, return the resource region of 79362306a36Sopenharmony_ci * parent bus the given region is contained in. 79462306a36Sopenharmony_ci */ 79562306a36Sopenharmony_cistruct resource *pci_find_parent_resource(const struct pci_dev *dev, 79662306a36Sopenharmony_ci struct resource *res) 79762306a36Sopenharmony_ci{ 79862306a36Sopenharmony_ci const struct pci_bus *bus = dev->bus; 79962306a36Sopenharmony_ci struct resource *r; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci pci_bus_for_each_resource(bus, r) { 80262306a36Sopenharmony_ci if (!r) 80362306a36Sopenharmony_ci continue; 80462306a36Sopenharmony_ci if (resource_contains(r, res)) { 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci /* 80762306a36Sopenharmony_ci * If the window is prefetchable but the BAR is 80862306a36Sopenharmony_ci * not, the allocator made a mistake. 80962306a36Sopenharmony_ci */ 81062306a36Sopenharmony_ci if (r->flags & IORESOURCE_PREFETCH && 81162306a36Sopenharmony_ci !(res->flags & IORESOURCE_PREFETCH)) 81262306a36Sopenharmony_ci return NULL; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci /* 81562306a36Sopenharmony_ci * If we're below a transparent bridge, there may 81662306a36Sopenharmony_ci * be both a positively-decoded aperture and a 81762306a36Sopenharmony_ci * subtractively-decoded region that contain the BAR. 81862306a36Sopenharmony_ci * We want the positively-decoded one, so this depends 81962306a36Sopenharmony_ci * on pci_bus_for_each_resource() giving us those 82062306a36Sopenharmony_ci * first. 82162306a36Sopenharmony_ci */ 82262306a36Sopenharmony_ci return r; 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci } 82562306a36Sopenharmony_ci return NULL; 82662306a36Sopenharmony_ci} 82762306a36Sopenharmony_ciEXPORT_SYMBOL(pci_find_parent_resource); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci/** 83062306a36Sopenharmony_ci * pci_find_resource - Return matching PCI device resource 83162306a36Sopenharmony_ci * @dev: PCI device to query 83262306a36Sopenharmony_ci * @res: Resource to look for 83362306a36Sopenharmony_ci * 83462306a36Sopenharmony_ci * Goes over standard PCI resources (BARs) and checks if the given resource 83562306a36Sopenharmony_ci * is partially or fully contained in any of them. In that case the 83662306a36Sopenharmony_ci * matching resource is returned, %NULL otherwise. 83762306a36Sopenharmony_ci */ 83862306a36Sopenharmony_cistruct resource *pci_find_resource(struct pci_dev *dev, struct resource *res) 83962306a36Sopenharmony_ci{ 84062306a36Sopenharmony_ci int i; 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci for (i = 0; i < PCI_STD_NUM_BARS; i++) { 84362306a36Sopenharmony_ci struct resource *r = &dev->resource[i]; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci if (r->start && resource_contains(r, res)) 84662306a36Sopenharmony_ci return r; 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci return NULL; 85062306a36Sopenharmony_ci} 85162306a36Sopenharmony_ciEXPORT_SYMBOL(pci_find_resource); 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci/** 85462306a36Sopenharmony_ci * pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos 85562306a36Sopenharmony_ci * @dev: the PCI device to operate on 85662306a36Sopenharmony_ci * @pos: config space offset of status word 85762306a36Sopenharmony_ci * @mask: mask of bit(s) to care about in status word 85862306a36Sopenharmony_ci * 85962306a36Sopenharmony_ci * Return 1 when mask bit(s) in status word clear, 0 otherwise. 86062306a36Sopenharmony_ci */ 86162306a36Sopenharmony_ciint pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci int i; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /* Wait for Transaction Pending bit clean */ 86662306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 86762306a36Sopenharmony_ci u16 status; 86862306a36Sopenharmony_ci if (i) 86962306a36Sopenharmony_ci msleep((1 << (i - 1)) * 100); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci pci_read_config_word(dev, pos, &status); 87262306a36Sopenharmony_ci if (!(status & mask)) 87362306a36Sopenharmony_ci return 1; 87462306a36Sopenharmony_ci } 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci return 0; 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic int pci_acs_enable; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci/** 88262306a36Sopenharmony_ci * pci_request_acs - ask for ACS to be enabled if supported 88362306a36Sopenharmony_ci */ 88462306a36Sopenharmony_civoid pci_request_acs(void) 88562306a36Sopenharmony_ci{ 88662306a36Sopenharmony_ci pci_acs_enable = 1; 88762306a36Sopenharmony_ci} 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_cistatic const char *disable_acs_redir_param; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci/** 89262306a36Sopenharmony_ci * pci_disable_acs_redir - disable ACS redirect capabilities 89362306a36Sopenharmony_ci * @dev: the PCI device 89462306a36Sopenharmony_ci * 89562306a36Sopenharmony_ci * For only devices specified in the disable_acs_redir parameter. 89662306a36Sopenharmony_ci */ 89762306a36Sopenharmony_cistatic void pci_disable_acs_redir(struct pci_dev *dev) 89862306a36Sopenharmony_ci{ 89962306a36Sopenharmony_ci int ret = 0; 90062306a36Sopenharmony_ci const char *p; 90162306a36Sopenharmony_ci int pos; 90262306a36Sopenharmony_ci u16 ctrl; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci if (!disable_acs_redir_param) 90562306a36Sopenharmony_ci return; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci p = disable_acs_redir_param; 90862306a36Sopenharmony_ci while (*p) { 90962306a36Sopenharmony_ci ret = pci_dev_str_match(dev, p, &p); 91062306a36Sopenharmony_ci if (ret < 0) { 91162306a36Sopenharmony_ci pr_info_once("PCI: Can't parse disable_acs_redir parameter: %s\n", 91262306a36Sopenharmony_ci disable_acs_redir_param); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci break; 91562306a36Sopenharmony_ci } else if (ret == 1) { 91662306a36Sopenharmony_ci /* Found a match */ 91762306a36Sopenharmony_ci break; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci if (*p != ';' && *p != ',') { 92162306a36Sopenharmony_ci /* End of param or invalid format */ 92262306a36Sopenharmony_ci break; 92362306a36Sopenharmony_ci } 92462306a36Sopenharmony_ci p++; 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci if (ret != 1) 92862306a36Sopenharmony_ci return; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci if (!pci_dev_specific_disable_acs_redir(dev)) 93162306a36Sopenharmony_ci return; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci pos = dev->acs_cap; 93462306a36Sopenharmony_ci if (!pos) { 93562306a36Sopenharmony_ci pci_warn(dev, "cannot disable ACS redirect for this hardware as it does not have ACS capabilities\n"); 93662306a36Sopenharmony_ci return; 93762306a36Sopenharmony_ci } 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci /* P2P Request & Completion Redirect */ 94262306a36Sopenharmony_ci ctrl &= ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC); 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci pci_info(dev, "disabled ACS redirect\n"); 94762306a36Sopenharmony_ci} 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci/** 95062306a36Sopenharmony_ci * pci_std_enable_acs - enable ACS on devices using standard ACS capabilities 95162306a36Sopenharmony_ci * @dev: the PCI device 95262306a36Sopenharmony_ci */ 95362306a36Sopenharmony_cistatic void pci_std_enable_acs(struct pci_dev *dev) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci int pos; 95662306a36Sopenharmony_ci u16 cap; 95762306a36Sopenharmony_ci u16 ctrl; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci pos = dev->acs_cap; 96062306a36Sopenharmony_ci if (!pos) 96162306a36Sopenharmony_ci return; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap); 96462306a36Sopenharmony_ci pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci /* Source Validation */ 96762306a36Sopenharmony_ci ctrl |= (cap & PCI_ACS_SV); 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci /* P2P Request Redirect */ 97062306a36Sopenharmony_ci ctrl |= (cap & PCI_ACS_RR); 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci /* P2P Completion Redirect */ 97362306a36Sopenharmony_ci ctrl |= (cap & PCI_ACS_CR); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci /* Upstream Forwarding */ 97662306a36Sopenharmony_ci ctrl |= (cap & PCI_ACS_UF); 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci /* Enable Translation Blocking for external devices and noats */ 97962306a36Sopenharmony_ci if (pci_ats_disabled() || dev->external_facing || dev->untrusted) 98062306a36Sopenharmony_ci ctrl |= (cap & PCI_ACS_TB); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); 98362306a36Sopenharmony_ci} 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci/** 98662306a36Sopenharmony_ci * pci_enable_acs - enable ACS if hardware support it 98762306a36Sopenharmony_ci * @dev: the PCI device 98862306a36Sopenharmony_ci */ 98962306a36Sopenharmony_cistatic void pci_enable_acs(struct pci_dev *dev) 99062306a36Sopenharmony_ci{ 99162306a36Sopenharmony_ci if (!pci_acs_enable) 99262306a36Sopenharmony_ci goto disable_acs_redir; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci if (!pci_dev_specific_enable_acs(dev)) 99562306a36Sopenharmony_ci goto disable_acs_redir; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci pci_std_enable_acs(dev); 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_cidisable_acs_redir: 100062306a36Sopenharmony_ci /* 100162306a36Sopenharmony_ci * Note: pci_disable_acs_redir() must be called even if ACS was not 100262306a36Sopenharmony_ci * enabled by the kernel because it may have been enabled by 100362306a36Sopenharmony_ci * platform firmware. So if we are told to disable it, we should 100462306a36Sopenharmony_ci * always disable it after setting the kernel's default 100562306a36Sopenharmony_ci * preferences. 100662306a36Sopenharmony_ci */ 100762306a36Sopenharmony_ci pci_disable_acs_redir(dev); 100862306a36Sopenharmony_ci} 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci/** 101162306a36Sopenharmony_ci * pci_restore_bars - restore a device's BAR values (e.g. after wake-up) 101262306a36Sopenharmony_ci * @dev: PCI device to have its BARs restored 101362306a36Sopenharmony_ci * 101462306a36Sopenharmony_ci * Restore the BAR values for a given device, so as to make it 101562306a36Sopenharmony_ci * accessible by its driver. 101662306a36Sopenharmony_ci */ 101762306a36Sopenharmony_cistatic void pci_restore_bars(struct pci_dev *dev) 101862306a36Sopenharmony_ci{ 101962306a36Sopenharmony_ci int i; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) 102262306a36Sopenharmony_ci pci_update_resource(dev, i); 102362306a36Sopenharmony_ci} 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_cistatic inline bool platform_pci_power_manageable(struct pci_dev *dev) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci if (pci_use_mid_pm()) 102862306a36Sopenharmony_ci return true; 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci return acpi_pci_power_manageable(dev); 103162306a36Sopenharmony_ci} 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_cistatic inline int platform_pci_set_power_state(struct pci_dev *dev, 103462306a36Sopenharmony_ci pci_power_t t) 103562306a36Sopenharmony_ci{ 103662306a36Sopenharmony_ci if (pci_use_mid_pm()) 103762306a36Sopenharmony_ci return mid_pci_set_power_state(dev, t); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci return acpi_pci_set_power_state(dev, t); 104062306a36Sopenharmony_ci} 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_cistatic inline pci_power_t platform_pci_get_power_state(struct pci_dev *dev) 104362306a36Sopenharmony_ci{ 104462306a36Sopenharmony_ci if (pci_use_mid_pm()) 104562306a36Sopenharmony_ci return mid_pci_get_power_state(dev); 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci return acpi_pci_get_power_state(dev); 104862306a36Sopenharmony_ci} 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_cistatic inline void platform_pci_refresh_power_state(struct pci_dev *dev) 105162306a36Sopenharmony_ci{ 105262306a36Sopenharmony_ci if (!pci_use_mid_pm()) 105362306a36Sopenharmony_ci acpi_pci_refresh_power_state(dev); 105462306a36Sopenharmony_ci} 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_cistatic inline pci_power_t platform_pci_choose_state(struct pci_dev *dev) 105762306a36Sopenharmony_ci{ 105862306a36Sopenharmony_ci if (pci_use_mid_pm()) 105962306a36Sopenharmony_ci return PCI_POWER_ERROR; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci return acpi_pci_choose_state(dev); 106262306a36Sopenharmony_ci} 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_cistatic inline int platform_pci_set_wakeup(struct pci_dev *dev, bool enable) 106562306a36Sopenharmony_ci{ 106662306a36Sopenharmony_ci if (pci_use_mid_pm()) 106762306a36Sopenharmony_ci return PCI_POWER_ERROR; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci return acpi_pci_wakeup(dev, enable); 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cistatic inline bool platform_pci_need_resume(struct pci_dev *dev) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci if (pci_use_mid_pm()) 107562306a36Sopenharmony_ci return false; 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci return acpi_pci_need_resume(dev); 107862306a36Sopenharmony_ci} 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_cistatic inline bool platform_pci_bridge_d3(struct pci_dev *dev) 108162306a36Sopenharmony_ci{ 108262306a36Sopenharmony_ci if (pci_use_mid_pm()) 108362306a36Sopenharmony_ci return false; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci return acpi_pci_bridge_d3(dev); 108662306a36Sopenharmony_ci} 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci/** 108962306a36Sopenharmony_ci * pci_update_current_state - Read power state of given device and cache it 109062306a36Sopenharmony_ci * @dev: PCI device to handle. 109162306a36Sopenharmony_ci * @state: State to cache in case the device doesn't have the PM capability 109262306a36Sopenharmony_ci * 109362306a36Sopenharmony_ci * The power state is read from the PMCSR register, which however is 109462306a36Sopenharmony_ci * inaccessible in D3cold. The platform firmware is therefore queried first 109562306a36Sopenharmony_ci * to detect accessibility of the register. In case the platform firmware 109662306a36Sopenharmony_ci * reports an incorrect state or the device isn't power manageable by the 109762306a36Sopenharmony_ci * platform at all, we try to detect D3cold by testing accessibility of the 109862306a36Sopenharmony_ci * vendor ID in config space. 109962306a36Sopenharmony_ci */ 110062306a36Sopenharmony_civoid pci_update_current_state(struct pci_dev *dev, pci_power_t state) 110162306a36Sopenharmony_ci{ 110262306a36Sopenharmony_ci if (platform_pci_get_power_state(dev) == PCI_D3cold) { 110362306a36Sopenharmony_ci dev->current_state = PCI_D3cold; 110462306a36Sopenharmony_ci } else if (dev->pm_cap) { 110562306a36Sopenharmony_ci u16 pmcsr; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 110862306a36Sopenharmony_ci if (PCI_POSSIBLE_ERROR(pmcsr)) { 110962306a36Sopenharmony_ci dev->current_state = PCI_D3cold; 111062306a36Sopenharmony_ci return; 111162306a36Sopenharmony_ci } 111262306a36Sopenharmony_ci dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK; 111362306a36Sopenharmony_ci } else { 111462306a36Sopenharmony_ci dev->current_state = state; 111562306a36Sopenharmony_ci } 111662306a36Sopenharmony_ci} 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci/** 111962306a36Sopenharmony_ci * pci_refresh_power_state - Refresh the given device's power state data 112062306a36Sopenharmony_ci * @dev: Target PCI device. 112162306a36Sopenharmony_ci * 112262306a36Sopenharmony_ci * Ask the platform to refresh the devices power state information and invoke 112362306a36Sopenharmony_ci * pci_update_current_state() to update its current PCI power state. 112462306a36Sopenharmony_ci */ 112562306a36Sopenharmony_civoid pci_refresh_power_state(struct pci_dev *dev) 112662306a36Sopenharmony_ci{ 112762306a36Sopenharmony_ci platform_pci_refresh_power_state(dev); 112862306a36Sopenharmony_ci pci_update_current_state(dev, dev->current_state); 112962306a36Sopenharmony_ci} 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci/** 113262306a36Sopenharmony_ci * pci_platform_power_transition - Use platform to change device power state 113362306a36Sopenharmony_ci * @dev: PCI device to handle. 113462306a36Sopenharmony_ci * @state: State to put the device into. 113562306a36Sopenharmony_ci */ 113662306a36Sopenharmony_ciint pci_platform_power_transition(struct pci_dev *dev, pci_power_t state) 113762306a36Sopenharmony_ci{ 113862306a36Sopenharmony_ci int error; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci error = platform_pci_set_power_state(dev, state); 114162306a36Sopenharmony_ci if (!error) 114262306a36Sopenharmony_ci pci_update_current_state(dev, state); 114362306a36Sopenharmony_ci else if (!dev->pm_cap) /* Fall back to PCI_D0 */ 114462306a36Sopenharmony_ci dev->current_state = PCI_D0; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci return error; 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_platform_power_transition); 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_cistatic int pci_resume_one(struct pci_dev *pci_dev, void *ign) 115162306a36Sopenharmony_ci{ 115262306a36Sopenharmony_ci pm_request_resume(&pci_dev->dev); 115362306a36Sopenharmony_ci return 0; 115462306a36Sopenharmony_ci} 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci/** 115762306a36Sopenharmony_ci * pci_resume_bus - Walk given bus and runtime resume devices on it 115862306a36Sopenharmony_ci * @bus: Top bus of the subtree to walk. 115962306a36Sopenharmony_ci */ 116062306a36Sopenharmony_civoid pci_resume_bus(struct pci_bus *bus) 116162306a36Sopenharmony_ci{ 116262306a36Sopenharmony_ci if (bus) 116362306a36Sopenharmony_ci pci_walk_bus(bus, pci_resume_one, NULL); 116462306a36Sopenharmony_ci} 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_cistatic int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout) 116762306a36Sopenharmony_ci{ 116862306a36Sopenharmony_ci int delay = 1; 116962306a36Sopenharmony_ci bool retrain = false; 117062306a36Sopenharmony_ci struct pci_dev *bridge; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci if (pci_is_pcie(dev)) { 117362306a36Sopenharmony_ci bridge = pci_upstream_bridge(dev); 117462306a36Sopenharmony_ci if (bridge) 117562306a36Sopenharmony_ci retrain = true; 117662306a36Sopenharmony_ci } 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci /* 117962306a36Sopenharmony_ci * After reset, the device should not silently discard config 118062306a36Sopenharmony_ci * requests, but it may still indicate that it needs more time by 118162306a36Sopenharmony_ci * responding to them with CRS completions. The Root Port will 118262306a36Sopenharmony_ci * generally synthesize ~0 (PCI_ERROR_RESPONSE) data to complete 118362306a36Sopenharmony_ci * the read (except when CRS SV is enabled and the read was for the 118462306a36Sopenharmony_ci * Vendor ID; in that case it synthesizes 0x0001 data). 118562306a36Sopenharmony_ci * 118662306a36Sopenharmony_ci * Wait for the device to return a non-CRS completion. Read the 118762306a36Sopenharmony_ci * Command register instead of Vendor ID so we don't have to 118862306a36Sopenharmony_ci * contend with the CRS SV value. 118962306a36Sopenharmony_ci */ 119062306a36Sopenharmony_ci for (;;) { 119162306a36Sopenharmony_ci u32 id; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci pci_read_config_dword(dev, PCI_COMMAND, &id); 119462306a36Sopenharmony_ci if (!PCI_POSSIBLE_ERROR(id)) 119562306a36Sopenharmony_ci break; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci if (delay > timeout) { 119862306a36Sopenharmony_ci pci_warn(dev, "not ready %dms after %s; giving up\n", 119962306a36Sopenharmony_ci delay - 1, reset_type); 120062306a36Sopenharmony_ci return -ENOTTY; 120162306a36Sopenharmony_ci } 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci if (delay > PCI_RESET_WAIT) { 120462306a36Sopenharmony_ci if (retrain) { 120562306a36Sopenharmony_ci retrain = false; 120662306a36Sopenharmony_ci if (pcie_failed_link_retrain(bridge)) { 120762306a36Sopenharmony_ci delay = 1; 120862306a36Sopenharmony_ci continue; 120962306a36Sopenharmony_ci } 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci pci_info(dev, "not ready %dms after %s; waiting\n", 121262306a36Sopenharmony_ci delay - 1, reset_type); 121362306a36Sopenharmony_ci } 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci msleep(delay); 121662306a36Sopenharmony_ci delay *= 2; 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci if (delay > PCI_RESET_WAIT) 122062306a36Sopenharmony_ci pci_info(dev, "ready %dms after %s\n", delay - 1, 122162306a36Sopenharmony_ci reset_type); 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci return 0; 122462306a36Sopenharmony_ci} 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci/** 122762306a36Sopenharmony_ci * pci_power_up - Put the given device into D0 122862306a36Sopenharmony_ci * @dev: PCI device to power up 122962306a36Sopenharmony_ci * 123062306a36Sopenharmony_ci * On success, return 0 or 1, depending on whether or not it is necessary to 123162306a36Sopenharmony_ci * restore the device's BARs subsequently (1 is returned in that case). 123262306a36Sopenharmony_ci * 123362306a36Sopenharmony_ci * On failure, return a negative error code. Always return failure if @dev 123462306a36Sopenharmony_ci * lacks a Power Management Capability, even if the platform was able to 123562306a36Sopenharmony_ci * put the device in D0 via non-PCI means. 123662306a36Sopenharmony_ci */ 123762306a36Sopenharmony_ciint pci_power_up(struct pci_dev *dev) 123862306a36Sopenharmony_ci{ 123962306a36Sopenharmony_ci bool need_restore; 124062306a36Sopenharmony_ci pci_power_t state; 124162306a36Sopenharmony_ci u16 pmcsr; 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci platform_pci_set_power_state(dev, PCI_D0); 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci if (!dev->pm_cap) { 124662306a36Sopenharmony_ci state = platform_pci_get_power_state(dev); 124762306a36Sopenharmony_ci if (state == PCI_UNKNOWN) 124862306a36Sopenharmony_ci dev->current_state = PCI_D0; 124962306a36Sopenharmony_ci else 125062306a36Sopenharmony_ci dev->current_state = state; 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci return -EIO; 125362306a36Sopenharmony_ci } 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 125662306a36Sopenharmony_ci if (PCI_POSSIBLE_ERROR(pmcsr)) { 125762306a36Sopenharmony_ci pci_err(dev, "Unable to change power state from %s to D0, device inaccessible\n", 125862306a36Sopenharmony_ci pci_power_name(dev->current_state)); 125962306a36Sopenharmony_ci dev->current_state = PCI_D3cold; 126062306a36Sopenharmony_ci return -EIO; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci state = pmcsr & PCI_PM_CTRL_STATE_MASK; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci need_restore = (state == PCI_D3hot || dev->current_state >= PCI_D3hot) && 126662306a36Sopenharmony_ci !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci if (state == PCI_D0) 126962306a36Sopenharmony_ci goto end; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci /* 127262306a36Sopenharmony_ci * Force the entire word to 0. This doesn't affect PME_Status, disables 127362306a36Sopenharmony_ci * PME_En, and sets PowerState to 0. 127462306a36Sopenharmony_ci */ 127562306a36Sopenharmony_ci pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, 0); 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci /* Mandatory transition delays; see PCI PM 1.2. */ 127862306a36Sopenharmony_ci if (state == PCI_D3hot) 127962306a36Sopenharmony_ci pci_dev_d3_sleep(dev); 128062306a36Sopenharmony_ci else if (state == PCI_D2) 128162306a36Sopenharmony_ci udelay(PCI_PM_D2_DELAY); 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ciend: 128462306a36Sopenharmony_ci dev->current_state = PCI_D0; 128562306a36Sopenharmony_ci if (need_restore) 128662306a36Sopenharmony_ci return 1; 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci return 0; 128962306a36Sopenharmony_ci} 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci/** 129262306a36Sopenharmony_ci * pci_set_full_power_state - Put a PCI device into D0 and update its state 129362306a36Sopenharmony_ci * @dev: PCI device to power up 129462306a36Sopenharmony_ci * 129562306a36Sopenharmony_ci * Call pci_power_up() to put @dev into D0, read from its PCI_PM_CTRL register 129662306a36Sopenharmony_ci * to confirm the state change, restore its BARs if they might be lost and 129762306a36Sopenharmony_ci * reconfigure ASPM in accordance with the new power state. 129862306a36Sopenharmony_ci * 129962306a36Sopenharmony_ci * If pci_restore_state() is going to be called right after a power state change 130062306a36Sopenharmony_ci * to D0, it is more efficient to use pci_power_up() directly instead of this 130162306a36Sopenharmony_ci * function. 130262306a36Sopenharmony_ci */ 130362306a36Sopenharmony_cistatic int pci_set_full_power_state(struct pci_dev *dev) 130462306a36Sopenharmony_ci{ 130562306a36Sopenharmony_ci u16 pmcsr; 130662306a36Sopenharmony_ci int ret; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci ret = pci_power_up(dev); 130962306a36Sopenharmony_ci if (ret < 0) { 131062306a36Sopenharmony_ci if (dev->current_state == PCI_D0) 131162306a36Sopenharmony_ci return 0; 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci return ret; 131462306a36Sopenharmony_ci } 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 131762306a36Sopenharmony_ci dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK; 131862306a36Sopenharmony_ci if (dev->current_state != PCI_D0) { 131962306a36Sopenharmony_ci pci_info_ratelimited(dev, "Refused to change power state from %s to D0\n", 132062306a36Sopenharmony_ci pci_power_name(dev->current_state)); 132162306a36Sopenharmony_ci } else if (ret > 0) { 132262306a36Sopenharmony_ci /* 132362306a36Sopenharmony_ci * According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT 132462306a36Sopenharmony_ci * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning 132562306a36Sopenharmony_ci * from D3hot to D0 _may_ perform an internal reset, thereby 132662306a36Sopenharmony_ci * going to "D0 Uninitialized" rather than "D0 Initialized". 132762306a36Sopenharmony_ci * For example, at least some versions of the 3c905B and the 132862306a36Sopenharmony_ci * 3c556B exhibit this behaviour. 132962306a36Sopenharmony_ci * 133062306a36Sopenharmony_ci * At least some laptop BIOSen (e.g. the Thinkpad T21) leave 133162306a36Sopenharmony_ci * devices in a D3hot state at boot. Consequently, we need to 133262306a36Sopenharmony_ci * restore at least the BARs so that the device will be 133362306a36Sopenharmony_ci * accessible to its driver. 133462306a36Sopenharmony_ci */ 133562306a36Sopenharmony_ci pci_restore_bars(dev); 133662306a36Sopenharmony_ci } 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci if (dev->bus->self) 133962306a36Sopenharmony_ci pcie_aspm_pm_state_change(dev->bus->self); 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci return 0; 134262306a36Sopenharmony_ci} 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci/** 134562306a36Sopenharmony_ci * __pci_dev_set_current_state - Set current state of a PCI device 134662306a36Sopenharmony_ci * @dev: Device to handle 134762306a36Sopenharmony_ci * @data: pointer to state to be set 134862306a36Sopenharmony_ci */ 134962306a36Sopenharmony_cistatic int __pci_dev_set_current_state(struct pci_dev *dev, void *data) 135062306a36Sopenharmony_ci{ 135162306a36Sopenharmony_ci pci_power_t state = *(pci_power_t *)data; 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci dev->current_state = state; 135462306a36Sopenharmony_ci return 0; 135562306a36Sopenharmony_ci} 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci/** 135862306a36Sopenharmony_ci * pci_bus_set_current_state - Walk given bus and set current state of devices 135962306a36Sopenharmony_ci * @bus: Top bus of the subtree to walk. 136062306a36Sopenharmony_ci * @state: state to be set 136162306a36Sopenharmony_ci */ 136262306a36Sopenharmony_civoid pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state) 136362306a36Sopenharmony_ci{ 136462306a36Sopenharmony_ci if (bus) 136562306a36Sopenharmony_ci pci_walk_bus(bus, __pci_dev_set_current_state, &state); 136662306a36Sopenharmony_ci} 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci/** 136962306a36Sopenharmony_ci * pci_set_low_power_state - Put a PCI device into a low-power state. 137062306a36Sopenharmony_ci * @dev: PCI device to handle. 137162306a36Sopenharmony_ci * @state: PCI power state (D1, D2, D3hot) to put the device into. 137262306a36Sopenharmony_ci * 137362306a36Sopenharmony_ci * Use the device's PCI_PM_CTRL register to put it into a low-power state. 137462306a36Sopenharmony_ci * 137562306a36Sopenharmony_ci * RETURN VALUE: 137662306a36Sopenharmony_ci * -EINVAL if the requested state is invalid. 137762306a36Sopenharmony_ci * -EIO if device does not support PCI PM or its PM capabilities register has a 137862306a36Sopenharmony_ci * wrong version, or device doesn't support the requested state. 137962306a36Sopenharmony_ci * 0 if device already is in the requested state. 138062306a36Sopenharmony_ci * 0 if device's power state has been successfully changed. 138162306a36Sopenharmony_ci */ 138262306a36Sopenharmony_cistatic int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) 138362306a36Sopenharmony_ci{ 138462306a36Sopenharmony_ci u16 pmcsr; 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci if (!dev->pm_cap) 138762306a36Sopenharmony_ci return -EIO; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci /* 139062306a36Sopenharmony_ci * Validate transition: We can enter D0 from any state, but if 139162306a36Sopenharmony_ci * we're already in a low-power state, we can only go deeper. E.g., 139262306a36Sopenharmony_ci * we can go from D1 to D3, but we can't go directly from D3 to D1; 139362306a36Sopenharmony_ci * we'd have to go from D3 to D0, then to D1. 139462306a36Sopenharmony_ci */ 139562306a36Sopenharmony_ci if (dev->current_state <= PCI_D3cold && dev->current_state > state) { 139662306a36Sopenharmony_ci pci_dbg(dev, "Invalid power transition (from %s to %s)\n", 139762306a36Sopenharmony_ci pci_power_name(dev->current_state), 139862306a36Sopenharmony_ci pci_power_name(state)); 139962306a36Sopenharmony_ci return -EINVAL; 140062306a36Sopenharmony_ci } 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci /* Check if this device supports the desired state */ 140362306a36Sopenharmony_ci if ((state == PCI_D1 && !dev->d1_support) 140462306a36Sopenharmony_ci || (state == PCI_D2 && !dev->d2_support)) 140562306a36Sopenharmony_ci return -EIO; 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 140862306a36Sopenharmony_ci if (PCI_POSSIBLE_ERROR(pmcsr)) { 140962306a36Sopenharmony_ci pci_err(dev, "Unable to change power state from %s to %s, device inaccessible\n", 141062306a36Sopenharmony_ci pci_power_name(dev->current_state), 141162306a36Sopenharmony_ci pci_power_name(state)); 141262306a36Sopenharmony_ci dev->current_state = PCI_D3cold; 141362306a36Sopenharmony_ci return -EIO; 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci pmcsr &= ~PCI_PM_CTRL_STATE_MASK; 141762306a36Sopenharmony_ci pmcsr |= state; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci /* Enter specified state */ 142062306a36Sopenharmony_ci pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci /* Mandatory power management transition delays; see PCI PM 1.2. */ 142362306a36Sopenharmony_ci if (state == PCI_D3hot) 142462306a36Sopenharmony_ci pci_dev_d3_sleep(dev); 142562306a36Sopenharmony_ci else if (state == PCI_D2) 142662306a36Sopenharmony_ci udelay(PCI_PM_D2_DELAY); 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 142962306a36Sopenharmony_ci dev->current_state = pmcsr & PCI_PM_CTRL_STATE_MASK; 143062306a36Sopenharmony_ci if (dev->current_state != state) 143162306a36Sopenharmony_ci pci_info_ratelimited(dev, "Refused to change power state from %s to %s\n", 143262306a36Sopenharmony_ci pci_power_name(dev->current_state), 143362306a36Sopenharmony_ci pci_power_name(state)); 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci if (dev->bus->self) 143662306a36Sopenharmony_ci pcie_aspm_pm_state_change(dev->bus->self); 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci return 0; 143962306a36Sopenharmony_ci} 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci/** 144262306a36Sopenharmony_ci * pci_set_power_state - Set the power state of a PCI device 144362306a36Sopenharmony_ci * @dev: PCI device to handle. 144462306a36Sopenharmony_ci * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. 144562306a36Sopenharmony_ci * 144662306a36Sopenharmony_ci * Transition a device to a new power state, using the platform firmware and/or 144762306a36Sopenharmony_ci * the device's PCI PM registers. 144862306a36Sopenharmony_ci * 144962306a36Sopenharmony_ci * RETURN VALUE: 145062306a36Sopenharmony_ci * -EINVAL if the requested state is invalid. 145162306a36Sopenharmony_ci * -EIO if device does not support PCI PM or its PM capabilities register has a 145262306a36Sopenharmony_ci * wrong version, or device doesn't support the requested state. 145362306a36Sopenharmony_ci * 0 if the transition is to D1 or D2 but D1 and D2 are not supported. 145462306a36Sopenharmony_ci * 0 if device already is in the requested state. 145562306a36Sopenharmony_ci * 0 if the transition is to D3 but D3 is not supported. 145662306a36Sopenharmony_ci * 0 if device's power state has been successfully changed. 145762306a36Sopenharmony_ci */ 145862306a36Sopenharmony_ciint pci_set_power_state(struct pci_dev *dev, pci_power_t state) 145962306a36Sopenharmony_ci{ 146062306a36Sopenharmony_ci int error; 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci /* Bound the state we're entering */ 146362306a36Sopenharmony_ci if (state > PCI_D3cold) 146462306a36Sopenharmony_ci state = PCI_D3cold; 146562306a36Sopenharmony_ci else if (state < PCI_D0) 146662306a36Sopenharmony_ci state = PCI_D0; 146762306a36Sopenharmony_ci else if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev)) 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci /* 147062306a36Sopenharmony_ci * If the device or the parent bridge do not support PCI 147162306a36Sopenharmony_ci * PM, ignore the request if we're doing anything other 147262306a36Sopenharmony_ci * than putting it into D0 (which would only happen on 147362306a36Sopenharmony_ci * boot). 147462306a36Sopenharmony_ci */ 147562306a36Sopenharmony_ci return 0; 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci /* Check if we're already there */ 147862306a36Sopenharmony_ci if (dev->current_state == state) 147962306a36Sopenharmony_ci return 0; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci if (state == PCI_D0) 148262306a36Sopenharmony_ci return pci_set_full_power_state(dev); 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci /* 148562306a36Sopenharmony_ci * This device is quirked not to be put into D3, so don't put it in 148662306a36Sopenharmony_ci * D3 148762306a36Sopenharmony_ci */ 148862306a36Sopenharmony_ci if (state >= PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) 148962306a36Sopenharmony_ci return 0; 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci if (state == PCI_D3cold) { 149262306a36Sopenharmony_ci /* 149362306a36Sopenharmony_ci * To put the device in D3cold, put it into D3hot in the native 149462306a36Sopenharmony_ci * way, then put it into D3cold using platform ops. 149562306a36Sopenharmony_ci */ 149662306a36Sopenharmony_ci error = pci_set_low_power_state(dev, PCI_D3hot); 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci if (pci_platform_power_transition(dev, PCI_D3cold)) 149962306a36Sopenharmony_ci return error; 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci /* Powering off a bridge may power off the whole hierarchy */ 150262306a36Sopenharmony_ci if (dev->current_state == PCI_D3cold) 150362306a36Sopenharmony_ci pci_bus_set_current_state(dev->subordinate, PCI_D3cold); 150462306a36Sopenharmony_ci } else { 150562306a36Sopenharmony_ci error = pci_set_low_power_state(dev, state); 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci if (pci_platform_power_transition(dev, state)) 150862306a36Sopenharmony_ci return error; 150962306a36Sopenharmony_ci } 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci return 0; 151262306a36Sopenharmony_ci} 151362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_set_power_state); 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci#define PCI_EXP_SAVE_REGS 7 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_cistatic struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev, 151862306a36Sopenharmony_ci u16 cap, bool extended) 151962306a36Sopenharmony_ci{ 152062306a36Sopenharmony_ci struct pci_cap_saved_state *tmp; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) { 152362306a36Sopenharmony_ci if (tmp->cap.cap_extended == extended && tmp->cap.cap_nr == cap) 152462306a36Sopenharmony_ci return tmp; 152562306a36Sopenharmony_ci } 152662306a36Sopenharmony_ci return NULL; 152762306a36Sopenharmony_ci} 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_cistruct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap) 153062306a36Sopenharmony_ci{ 153162306a36Sopenharmony_ci return _pci_find_saved_cap(dev, cap, false); 153262306a36Sopenharmony_ci} 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_cistruct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, u16 cap) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci return _pci_find_saved_cap(dev, cap, true); 153762306a36Sopenharmony_ci} 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_cistatic int pci_save_pcie_state(struct pci_dev *dev) 154062306a36Sopenharmony_ci{ 154162306a36Sopenharmony_ci int i = 0; 154262306a36Sopenharmony_ci struct pci_cap_saved_state *save_state; 154362306a36Sopenharmony_ci u16 *cap; 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ci if (!pci_is_pcie(dev)) 154662306a36Sopenharmony_ci return 0; 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); 154962306a36Sopenharmony_ci if (!save_state) { 155062306a36Sopenharmony_ci pci_err(dev, "buffer not found in %s\n", __func__); 155162306a36Sopenharmony_ci return -ENOMEM; 155262306a36Sopenharmony_ci } 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci cap = (u16 *)&save_state->cap.data[0]; 155562306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &cap[i++]); 155662306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &cap[i++]); 155762306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_SLTCTL, &cap[i++]); 155862306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_RTCTL, &cap[i++]); 155962306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &cap[i++]); 156062306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &cap[i++]); 156162306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_SLTCTL2, &cap[i++]); 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci return 0; 156462306a36Sopenharmony_ci} 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_civoid pci_bridge_reconfigure_ltr(struct pci_dev *dev) 156762306a36Sopenharmony_ci{ 156862306a36Sopenharmony_ci#ifdef CONFIG_PCIEASPM 156962306a36Sopenharmony_ci struct pci_dev *bridge; 157062306a36Sopenharmony_ci u32 ctl; 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci bridge = pci_upstream_bridge(dev); 157362306a36Sopenharmony_ci if (bridge && bridge->ltr_path) { 157462306a36Sopenharmony_ci pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, &ctl); 157562306a36Sopenharmony_ci if (!(ctl & PCI_EXP_DEVCTL2_LTR_EN)) { 157662306a36Sopenharmony_ci pci_dbg(bridge, "re-enabling LTR\n"); 157762306a36Sopenharmony_ci pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, 157862306a36Sopenharmony_ci PCI_EXP_DEVCTL2_LTR_EN); 157962306a36Sopenharmony_ci } 158062306a36Sopenharmony_ci } 158162306a36Sopenharmony_ci#endif 158262306a36Sopenharmony_ci} 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_cistatic void pci_restore_pcie_state(struct pci_dev *dev) 158562306a36Sopenharmony_ci{ 158662306a36Sopenharmony_ci int i = 0; 158762306a36Sopenharmony_ci struct pci_cap_saved_state *save_state; 158862306a36Sopenharmony_ci u16 *cap; 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); 159162306a36Sopenharmony_ci if (!save_state) 159262306a36Sopenharmony_ci return; 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci /* 159562306a36Sopenharmony_ci * Downstream ports reset the LTR enable bit when link goes down. 159662306a36Sopenharmony_ci * Check and re-configure the bit here before restoring device. 159762306a36Sopenharmony_ci * PCIe r5.0, sec 7.5.3.16. 159862306a36Sopenharmony_ci */ 159962306a36Sopenharmony_ci pci_bridge_reconfigure_ltr(dev); 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci cap = (u16 *)&save_state->cap.data[0]; 160262306a36Sopenharmony_ci pcie_capability_write_word(dev, PCI_EXP_DEVCTL, cap[i++]); 160362306a36Sopenharmony_ci pcie_capability_write_word(dev, PCI_EXP_LNKCTL, cap[i++]); 160462306a36Sopenharmony_ci pcie_capability_write_word(dev, PCI_EXP_SLTCTL, cap[i++]); 160562306a36Sopenharmony_ci pcie_capability_write_word(dev, PCI_EXP_RTCTL, cap[i++]); 160662306a36Sopenharmony_ci pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, cap[i++]); 160762306a36Sopenharmony_ci pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, cap[i++]); 160862306a36Sopenharmony_ci pcie_capability_write_word(dev, PCI_EXP_SLTCTL2, cap[i++]); 160962306a36Sopenharmony_ci} 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_cistatic int pci_save_pcix_state(struct pci_dev *dev) 161262306a36Sopenharmony_ci{ 161362306a36Sopenharmony_ci int pos; 161462306a36Sopenharmony_ci struct pci_cap_saved_state *save_state; 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); 161762306a36Sopenharmony_ci if (!pos) 161862306a36Sopenharmony_ci return 0; 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); 162162306a36Sopenharmony_ci if (!save_state) { 162262306a36Sopenharmony_ci pci_err(dev, "buffer not found in %s\n", __func__); 162362306a36Sopenharmony_ci return -ENOMEM; 162462306a36Sopenharmony_ci } 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci pci_read_config_word(dev, pos + PCI_X_CMD, 162762306a36Sopenharmony_ci (u16 *)save_state->cap.data); 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci return 0; 163062306a36Sopenharmony_ci} 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_cistatic void pci_restore_pcix_state(struct pci_dev *dev) 163362306a36Sopenharmony_ci{ 163462306a36Sopenharmony_ci int i = 0, pos; 163562306a36Sopenharmony_ci struct pci_cap_saved_state *save_state; 163662306a36Sopenharmony_ci u16 *cap; 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); 163962306a36Sopenharmony_ci pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); 164062306a36Sopenharmony_ci if (!save_state || !pos) 164162306a36Sopenharmony_ci return; 164262306a36Sopenharmony_ci cap = (u16 *)&save_state->cap.data[0]; 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]); 164562306a36Sopenharmony_ci} 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_cistatic void pci_save_ltr_state(struct pci_dev *dev) 164862306a36Sopenharmony_ci{ 164962306a36Sopenharmony_ci int ltr; 165062306a36Sopenharmony_ci struct pci_cap_saved_state *save_state; 165162306a36Sopenharmony_ci u32 *cap; 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci if (!pci_is_pcie(dev)) 165462306a36Sopenharmony_ci return; 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR); 165762306a36Sopenharmony_ci if (!ltr) 165862306a36Sopenharmony_ci return; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); 166162306a36Sopenharmony_ci if (!save_state) { 166262306a36Sopenharmony_ci pci_err(dev, "no suspend buffer for LTR; ASPM issues possible after resume\n"); 166362306a36Sopenharmony_ci return; 166462306a36Sopenharmony_ci } 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci /* Some broken devices only support dword access to LTR */ 166762306a36Sopenharmony_ci cap = &save_state->cap.data[0]; 166862306a36Sopenharmony_ci pci_read_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap); 166962306a36Sopenharmony_ci} 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_cistatic void pci_restore_ltr_state(struct pci_dev *dev) 167262306a36Sopenharmony_ci{ 167362306a36Sopenharmony_ci struct pci_cap_saved_state *save_state; 167462306a36Sopenharmony_ci int ltr; 167562306a36Sopenharmony_ci u32 *cap; 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR); 167862306a36Sopenharmony_ci ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR); 167962306a36Sopenharmony_ci if (!save_state || !ltr) 168062306a36Sopenharmony_ci return; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci /* Some broken devices only support dword access to LTR */ 168362306a36Sopenharmony_ci cap = &save_state->cap.data[0]; 168462306a36Sopenharmony_ci pci_write_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap); 168562306a36Sopenharmony_ci} 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci/** 168862306a36Sopenharmony_ci * pci_save_state - save the PCI configuration space of a device before 168962306a36Sopenharmony_ci * suspending 169062306a36Sopenharmony_ci * @dev: PCI device that we're dealing with 169162306a36Sopenharmony_ci */ 169262306a36Sopenharmony_ciint pci_save_state(struct pci_dev *dev) 169362306a36Sopenharmony_ci{ 169462306a36Sopenharmony_ci int i; 169562306a36Sopenharmony_ci /* XXX: 100% dword access ok here? */ 169662306a36Sopenharmony_ci for (i = 0; i < 16; i++) { 169762306a36Sopenharmony_ci pci_read_config_dword(dev, i * 4, &dev->saved_config_space[i]); 169862306a36Sopenharmony_ci pci_dbg(dev, "save config %#04x: %#010x\n", 169962306a36Sopenharmony_ci i * 4, dev->saved_config_space[i]); 170062306a36Sopenharmony_ci } 170162306a36Sopenharmony_ci dev->state_saved = true; 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci i = pci_save_pcie_state(dev); 170462306a36Sopenharmony_ci if (i != 0) 170562306a36Sopenharmony_ci return i; 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci i = pci_save_pcix_state(dev); 170862306a36Sopenharmony_ci if (i != 0) 170962306a36Sopenharmony_ci return i; 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci pci_save_ltr_state(dev); 171262306a36Sopenharmony_ci pci_save_dpc_state(dev); 171362306a36Sopenharmony_ci pci_save_aer_state(dev); 171462306a36Sopenharmony_ci pci_save_ptm_state(dev); 171562306a36Sopenharmony_ci return pci_save_vc_state(dev); 171662306a36Sopenharmony_ci} 171762306a36Sopenharmony_ciEXPORT_SYMBOL(pci_save_state); 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_cistatic void pci_restore_config_dword(struct pci_dev *pdev, int offset, 172062306a36Sopenharmony_ci u32 saved_val, int retry, bool force) 172162306a36Sopenharmony_ci{ 172262306a36Sopenharmony_ci u32 val; 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci pci_read_config_dword(pdev, offset, &val); 172562306a36Sopenharmony_ci if (!force && val == saved_val) 172662306a36Sopenharmony_ci return; 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci for (;;) { 172962306a36Sopenharmony_ci pci_dbg(pdev, "restore config %#04x: %#010x -> %#010x\n", 173062306a36Sopenharmony_ci offset, val, saved_val); 173162306a36Sopenharmony_ci pci_write_config_dword(pdev, offset, saved_val); 173262306a36Sopenharmony_ci if (retry-- <= 0) 173362306a36Sopenharmony_ci return; 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci pci_read_config_dword(pdev, offset, &val); 173662306a36Sopenharmony_ci if (val == saved_val) 173762306a36Sopenharmony_ci return; 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci mdelay(1); 174062306a36Sopenharmony_ci } 174162306a36Sopenharmony_ci} 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_cistatic void pci_restore_config_space_range(struct pci_dev *pdev, 174462306a36Sopenharmony_ci int start, int end, int retry, 174562306a36Sopenharmony_ci bool force) 174662306a36Sopenharmony_ci{ 174762306a36Sopenharmony_ci int index; 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci for (index = end; index >= start; index--) 175062306a36Sopenharmony_ci pci_restore_config_dword(pdev, 4 * index, 175162306a36Sopenharmony_ci pdev->saved_config_space[index], 175262306a36Sopenharmony_ci retry, force); 175362306a36Sopenharmony_ci} 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_cistatic void pci_restore_config_space(struct pci_dev *pdev) 175662306a36Sopenharmony_ci{ 175762306a36Sopenharmony_ci if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) { 175862306a36Sopenharmony_ci pci_restore_config_space_range(pdev, 10, 15, 0, false); 175962306a36Sopenharmony_ci /* Restore BARs before the command register. */ 176062306a36Sopenharmony_ci pci_restore_config_space_range(pdev, 4, 9, 10, false); 176162306a36Sopenharmony_ci pci_restore_config_space_range(pdev, 0, 3, 0, false); 176262306a36Sopenharmony_ci } else if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 176362306a36Sopenharmony_ci pci_restore_config_space_range(pdev, 12, 15, 0, false); 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci /* 176662306a36Sopenharmony_ci * Force rewriting of prefetch registers to avoid S3 resume 176762306a36Sopenharmony_ci * issues on Intel PCI bridges that occur when these 176862306a36Sopenharmony_ci * registers are not explicitly written. 176962306a36Sopenharmony_ci */ 177062306a36Sopenharmony_ci pci_restore_config_space_range(pdev, 9, 11, 0, true); 177162306a36Sopenharmony_ci pci_restore_config_space_range(pdev, 0, 8, 0, false); 177262306a36Sopenharmony_ci } else { 177362306a36Sopenharmony_ci pci_restore_config_space_range(pdev, 0, 15, 0, false); 177462306a36Sopenharmony_ci } 177562306a36Sopenharmony_ci} 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_cistatic void pci_restore_rebar_state(struct pci_dev *pdev) 177862306a36Sopenharmony_ci{ 177962306a36Sopenharmony_ci unsigned int pos, nbars, i; 178062306a36Sopenharmony_ci u32 ctrl; 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_ci pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); 178362306a36Sopenharmony_ci if (!pos) 178462306a36Sopenharmony_ci return; 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); 178762306a36Sopenharmony_ci nbars = (ctrl & PCI_REBAR_CTRL_NBAR_MASK) >> 178862306a36Sopenharmony_ci PCI_REBAR_CTRL_NBAR_SHIFT; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci for (i = 0; i < nbars; i++, pos += 8) { 179162306a36Sopenharmony_ci struct resource *res; 179262306a36Sopenharmony_ci int bar_idx, size; 179362306a36Sopenharmony_ci 179462306a36Sopenharmony_ci pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); 179562306a36Sopenharmony_ci bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; 179662306a36Sopenharmony_ci res = pdev->resource + bar_idx; 179762306a36Sopenharmony_ci size = pci_rebar_bytes_to_size(resource_size(res)); 179862306a36Sopenharmony_ci ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; 179962306a36Sopenharmony_ci ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT; 180062306a36Sopenharmony_ci pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); 180162306a36Sopenharmony_ci } 180262306a36Sopenharmony_ci} 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci/** 180562306a36Sopenharmony_ci * pci_restore_state - Restore the saved state of a PCI device 180662306a36Sopenharmony_ci * @dev: PCI device that we're dealing with 180762306a36Sopenharmony_ci */ 180862306a36Sopenharmony_civoid pci_restore_state(struct pci_dev *dev) 180962306a36Sopenharmony_ci{ 181062306a36Sopenharmony_ci if (!dev->state_saved) 181162306a36Sopenharmony_ci return; 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci /* 181462306a36Sopenharmony_ci * Restore max latencies (in the LTR capability) before enabling 181562306a36Sopenharmony_ci * LTR itself (in the PCIe capability). 181662306a36Sopenharmony_ci */ 181762306a36Sopenharmony_ci pci_restore_ltr_state(dev); 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci pci_restore_pcie_state(dev); 182062306a36Sopenharmony_ci pci_restore_pasid_state(dev); 182162306a36Sopenharmony_ci pci_restore_pri_state(dev); 182262306a36Sopenharmony_ci pci_restore_ats_state(dev); 182362306a36Sopenharmony_ci pci_restore_vc_state(dev); 182462306a36Sopenharmony_ci pci_restore_rebar_state(dev); 182562306a36Sopenharmony_ci pci_restore_dpc_state(dev); 182662306a36Sopenharmony_ci pci_restore_ptm_state(dev); 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_ci pci_aer_clear_status(dev); 182962306a36Sopenharmony_ci pci_restore_aer_state(dev); 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci pci_restore_config_space(dev); 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci pci_restore_pcix_state(dev); 183462306a36Sopenharmony_ci pci_restore_msi_state(dev); 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci /* Restore ACS and IOV configuration state */ 183762306a36Sopenharmony_ci pci_enable_acs(dev); 183862306a36Sopenharmony_ci pci_restore_iov_state(dev); 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ci dev->state_saved = false; 184162306a36Sopenharmony_ci} 184262306a36Sopenharmony_ciEXPORT_SYMBOL(pci_restore_state); 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_cistruct pci_saved_state { 184562306a36Sopenharmony_ci u32 config_space[16]; 184662306a36Sopenharmony_ci struct pci_cap_saved_data cap[]; 184762306a36Sopenharmony_ci}; 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci/** 185062306a36Sopenharmony_ci * pci_store_saved_state - Allocate and return an opaque struct containing 185162306a36Sopenharmony_ci * the device saved state. 185262306a36Sopenharmony_ci * @dev: PCI device that we're dealing with 185362306a36Sopenharmony_ci * 185462306a36Sopenharmony_ci * Return NULL if no state or error. 185562306a36Sopenharmony_ci */ 185662306a36Sopenharmony_cistruct pci_saved_state *pci_store_saved_state(struct pci_dev *dev) 185762306a36Sopenharmony_ci{ 185862306a36Sopenharmony_ci struct pci_saved_state *state; 185962306a36Sopenharmony_ci struct pci_cap_saved_state *tmp; 186062306a36Sopenharmony_ci struct pci_cap_saved_data *cap; 186162306a36Sopenharmony_ci size_t size; 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci if (!dev->state_saved) 186462306a36Sopenharmony_ci return NULL; 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_ci size = sizeof(*state) + sizeof(struct pci_cap_saved_data); 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci hlist_for_each_entry(tmp, &dev->saved_cap_space, next) 186962306a36Sopenharmony_ci size += sizeof(struct pci_cap_saved_data) + tmp->cap.size; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci state = kzalloc(size, GFP_KERNEL); 187262306a36Sopenharmony_ci if (!state) 187362306a36Sopenharmony_ci return NULL; 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci memcpy(state->config_space, dev->saved_config_space, 187662306a36Sopenharmony_ci sizeof(state->config_space)); 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci cap = state->cap; 187962306a36Sopenharmony_ci hlist_for_each_entry(tmp, &dev->saved_cap_space, next) { 188062306a36Sopenharmony_ci size_t len = sizeof(struct pci_cap_saved_data) + tmp->cap.size; 188162306a36Sopenharmony_ci memcpy(cap, &tmp->cap, len); 188262306a36Sopenharmony_ci cap = (struct pci_cap_saved_data *)((u8 *)cap + len); 188362306a36Sopenharmony_ci } 188462306a36Sopenharmony_ci /* Empty cap_save terminates list */ 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci return state; 188762306a36Sopenharmony_ci} 188862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_store_saved_state); 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci/** 189162306a36Sopenharmony_ci * pci_load_saved_state - Reload the provided save state into struct pci_dev. 189262306a36Sopenharmony_ci * @dev: PCI device that we're dealing with 189362306a36Sopenharmony_ci * @state: Saved state returned from pci_store_saved_state() 189462306a36Sopenharmony_ci */ 189562306a36Sopenharmony_ciint pci_load_saved_state(struct pci_dev *dev, 189662306a36Sopenharmony_ci struct pci_saved_state *state) 189762306a36Sopenharmony_ci{ 189862306a36Sopenharmony_ci struct pci_cap_saved_data *cap; 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci dev->state_saved = false; 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci if (!state) 190362306a36Sopenharmony_ci return 0; 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci memcpy(dev->saved_config_space, state->config_space, 190662306a36Sopenharmony_ci sizeof(state->config_space)); 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci cap = state->cap; 190962306a36Sopenharmony_ci while (cap->size) { 191062306a36Sopenharmony_ci struct pci_cap_saved_state *tmp; 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci tmp = _pci_find_saved_cap(dev, cap->cap_nr, cap->cap_extended); 191362306a36Sopenharmony_ci if (!tmp || tmp->cap.size != cap->size) 191462306a36Sopenharmony_ci return -EINVAL; 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci memcpy(tmp->cap.data, cap->data, tmp->cap.size); 191762306a36Sopenharmony_ci cap = (struct pci_cap_saved_data *)((u8 *)cap + 191862306a36Sopenharmony_ci sizeof(struct pci_cap_saved_data) + cap->size); 191962306a36Sopenharmony_ci } 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci dev->state_saved = true; 192262306a36Sopenharmony_ci return 0; 192362306a36Sopenharmony_ci} 192462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_load_saved_state); 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci/** 192762306a36Sopenharmony_ci * pci_load_and_free_saved_state - Reload the save state pointed to by state, 192862306a36Sopenharmony_ci * and free the memory allocated for it. 192962306a36Sopenharmony_ci * @dev: PCI device that we're dealing with 193062306a36Sopenharmony_ci * @state: Pointer to saved state returned from pci_store_saved_state() 193162306a36Sopenharmony_ci */ 193262306a36Sopenharmony_ciint pci_load_and_free_saved_state(struct pci_dev *dev, 193362306a36Sopenharmony_ci struct pci_saved_state **state) 193462306a36Sopenharmony_ci{ 193562306a36Sopenharmony_ci int ret = pci_load_saved_state(dev, *state); 193662306a36Sopenharmony_ci kfree(*state); 193762306a36Sopenharmony_ci *state = NULL; 193862306a36Sopenharmony_ci return ret; 193962306a36Sopenharmony_ci} 194062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_load_and_free_saved_state); 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ciint __weak pcibios_enable_device(struct pci_dev *dev, int bars) 194362306a36Sopenharmony_ci{ 194462306a36Sopenharmony_ci return pci_enable_resources(dev, bars); 194562306a36Sopenharmony_ci} 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_cistatic int do_pci_enable_device(struct pci_dev *dev, int bars) 194862306a36Sopenharmony_ci{ 194962306a36Sopenharmony_ci int err; 195062306a36Sopenharmony_ci struct pci_dev *bridge; 195162306a36Sopenharmony_ci u16 cmd; 195262306a36Sopenharmony_ci u8 pin; 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_ci err = pci_set_power_state(dev, PCI_D0); 195562306a36Sopenharmony_ci if (err < 0 && err != -EIO) 195662306a36Sopenharmony_ci return err; 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci bridge = pci_upstream_bridge(dev); 195962306a36Sopenharmony_ci if (bridge) 196062306a36Sopenharmony_ci pcie_aspm_powersave_config_link(bridge); 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci err = pcibios_enable_device(dev, bars); 196362306a36Sopenharmony_ci if (err < 0) 196462306a36Sopenharmony_ci return err; 196562306a36Sopenharmony_ci pci_fixup_device(pci_fixup_enable, dev); 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci if (dev->msi_enabled || dev->msix_enabled) 196862306a36Sopenharmony_ci return 0; 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); 197162306a36Sopenharmony_ci if (pin) { 197262306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &cmd); 197362306a36Sopenharmony_ci if (cmd & PCI_COMMAND_INTX_DISABLE) 197462306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, 197562306a36Sopenharmony_ci cmd & ~PCI_COMMAND_INTX_DISABLE); 197662306a36Sopenharmony_ci } 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci return 0; 197962306a36Sopenharmony_ci} 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci/** 198262306a36Sopenharmony_ci * pci_reenable_device - Resume abandoned device 198362306a36Sopenharmony_ci * @dev: PCI device to be resumed 198462306a36Sopenharmony_ci * 198562306a36Sopenharmony_ci * NOTE: This function is a backend of pci_default_resume() and is not supposed 198662306a36Sopenharmony_ci * to be called by normal code, write proper resume handler and use it instead. 198762306a36Sopenharmony_ci */ 198862306a36Sopenharmony_ciint pci_reenable_device(struct pci_dev *dev) 198962306a36Sopenharmony_ci{ 199062306a36Sopenharmony_ci if (pci_is_enabled(dev)) 199162306a36Sopenharmony_ci return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1); 199262306a36Sopenharmony_ci return 0; 199362306a36Sopenharmony_ci} 199462306a36Sopenharmony_ciEXPORT_SYMBOL(pci_reenable_device); 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_cistatic void pci_enable_bridge(struct pci_dev *dev) 199762306a36Sopenharmony_ci{ 199862306a36Sopenharmony_ci struct pci_dev *bridge; 199962306a36Sopenharmony_ci int retval; 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_ci bridge = pci_upstream_bridge(dev); 200262306a36Sopenharmony_ci if (bridge) 200362306a36Sopenharmony_ci pci_enable_bridge(bridge); 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci if (pci_is_enabled(dev)) { 200662306a36Sopenharmony_ci if (!dev->is_busmaster) 200762306a36Sopenharmony_ci pci_set_master(dev); 200862306a36Sopenharmony_ci return; 200962306a36Sopenharmony_ci } 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_ci retval = pci_enable_device(dev); 201262306a36Sopenharmony_ci if (retval) 201362306a36Sopenharmony_ci pci_err(dev, "Error enabling bridge (%d), continuing\n", 201462306a36Sopenharmony_ci retval); 201562306a36Sopenharmony_ci pci_set_master(dev); 201662306a36Sopenharmony_ci} 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_cistatic int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) 201962306a36Sopenharmony_ci{ 202062306a36Sopenharmony_ci struct pci_dev *bridge; 202162306a36Sopenharmony_ci int err; 202262306a36Sopenharmony_ci int i, bars = 0; 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci /* 202562306a36Sopenharmony_ci * Power state could be unknown at this point, either due to a fresh 202662306a36Sopenharmony_ci * boot or a device removal call. So get the current power state 202762306a36Sopenharmony_ci * so that things like MSI message writing will behave as expected 202862306a36Sopenharmony_ci * (e.g. if the device really is in D0 at enable time). 202962306a36Sopenharmony_ci */ 203062306a36Sopenharmony_ci pci_update_current_state(dev, dev->current_state); 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci if (atomic_inc_return(&dev->enable_cnt) > 1) 203362306a36Sopenharmony_ci return 0; /* already enabled */ 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci bridge = pci_upstream_bridge(dev); 203662306a36Sopenharmony_ci if (bridge) 203762306a36Sopenharmony_ci pci_enable_bridge(bridge); 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_ci /* only skip sriov related */ 204062306a36Sopenharmony_ci for (i = 0; i <= PCI_ROM_RESOURCE; i++) 204162306a36Sopenharmony_ci if (dev->resource[i].flags & flags) 204262306a36Sopenharmony_ci bars |= (1 << i); 204362306a36Sopenharmony_ci for (i = PCI_BRIDGE_RESOURCES; i < DEVICE_COUNT_RESOURCE; i++) 204462306a36Sopenharmony_ci if (dev->resource[i].flags & flags) 204562306a36Sopenharmony_ci bars |= (1 << i); 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci err = do_pci_enable_device(dev, bars); 204862306a36Sopenharmony_ci if (err < 0) 204962306a36Sopenharmony_ci atomic_dec(&dev->enable_cnt); 205062306a36Sopenharmony_ci return err; 205162306a36Sopenharmony_ci} 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci/** 205462306a36Sopenharmony_ci * pci_enable_device_io - Initialize a device for use with IO space 205562306a36Sopenharmony_ci * @dev: PCI device to be initialized 205662306a36Sopenharmony_ci * 205762306a36Sopenharmony_ci * Initialize device before it's used by a driver. Ask low-level code 205862306a36Sopenharmony_ci * to enable I/O resources. Wake up the device if it was suspended. 205962306a36Sopenharmony_ci * Beware, this function can fail. 206062306a36Sopenharmony_ci */ 206162306a36Sopenharmony_ciint pci_enable_device_io(struct pci_dev *dev) 206262306a36Sopenharmony_ci{ 206362306a36Sopenharmony_ci return pci_enable_device_flags(dev, IORESOURCE_IO); 206462306a36Sopenharmony_ci} 206562306a36Sopenharmony_ciEXPORT_SYMBOL(pci_enable_device_io); 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci/** 206862306a36Sopenharmony_ci * pci_enable_device_mem - Initialize a device for use with Memory space 206962306a36Sopenharmony_ci * @dev: PCI device to be initialized 207062306a36Sopenharmony_ci * 207162306a36Sopenharmony_ci * Initialize device before it's used by a driver. Ask low-level code 207262306a36Sopenharmony_ci * to enable Memory resources. Wake up the device if it was suspended. 207362306a36Sopenharmony_ci * Beware, this function can fail. 207462306a36Sopenharmony_ci */ 207562306a36Sopenharmony_ciint pci_enable_device_mem(struct pci_dev *dev) 207662306a36Sopenharmony_ci{ 207762306a36Sopenharmony_ci return pci_enable_device_flags(dev, IORESOURCE_MEM); 207862306a36Sopenharmony_ci} 207962306a36Sopenharmony_ciEXPORT_SYMBOL(pci_enable_device_mem); 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci/** 208262306a36Sopenharmony_ci * pci_enable_device - Initialize device before it's used by a driver. 208362306a36Sopenharmony_ci * @dev: PCI device to be initialized 208462306a36Sopenharmony_ci * 208562306a36Sopenharmony_ci * Initialize device before it's used by a driver. Ask low-level code 208662306a36Sopenharmony_ci * to enable I/O and memory. Wake up the device if it was suspended. 208762306a36Sopenharmony_ci * Beware, this function can fail. 208862306a36Sopenharmony_ci * 208962306a36Sopenharmony_ci * Note we don't actually enable the device many times if we call 209062306a36Sopenharmony_ci * this function repeatedly (we just increment the count). 209162306a36Sopenharmony_ci */ 209262306a36Sopenharmony_ciint pci_enable_device(struct pci_dev *dev) 209362306a36Sopenharmony_ci{ 209462306a36Sopenharmony_ci return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO); 209562306a36Sopenharmony_ci} 209662306a36Sopenharmony_ciEXPORT_SYMBOL(pci_enable_device); 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci/* 209962306a36Sopenharmony_ci * Managed PCI resources. This manages device on/off, INTx/MSI/MSI-X 210062306a36Sopenharmony_ci * on/off and BAR regions. pci_dev itself records MSI/MSI-X status, so 210162306a36Sopenharmony_ci * there's no need to track it separately. pci_devres is initialized 210262306a36Sopenharmony_ci * when a device is enabled using managed PCI device enable interface. 210362306a36Sopenharmony_ci */ 210462306a36Sopenharmony_cistruct pci_devres { 210562306a36Sopenharmony_ci unsigned int enabled:1; 210662306a36Sopenharmony_ci unsigned int pinned:1; 210762306a36Sopenharmony_ci unsigned int orig_intx:1; 210862306a36Sopenharmony_ci unsigned int restore_intx:1; 210962306a36Sopenharmony_ci unsigned int mwi:1; 211062306a36Sopenharmony_ci u32 region_mask; 211162306a36Sopenharmony_ci}; 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_cistatic void pcim_release(struct device *gendev, void *res) 211462306a36Sopenharmony_ci{ 211562306a36Sopenharmony_ci struct pci_dev *dev = to_pci_dev(gendev); 211662306a36Sopenharmony_ci struct pci_devres *this = res; 211762306a36Sopenharmony_ci int i; 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) 212062306a36Sopenharmony_ci if (this->region_mask & (1 << i)) 212162306a36Sopenharmony_ci pci_release_region(dev, i); 212262306a36Sopenharmony_ci 212362306a36Sopenharmony_ci if (this->mwi) 212462306a36Sopenharmony_ci pci_clear_mwi(dev); 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci if (this->restore_intx) 212762306a36Sopenharmony_ci pci_intx(dev, this->orig_intx); 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci if (this->enabled && !this->pinned) 213062306a36Sopenharmony_ci pci_disable_device(dev); 213162306a36Sopenharmony_ci} 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_cistatic struct pci_devres *get_pci_dr(struct pci_dev *pdev) 213462306a36Sopenharmony_ci{ 213562306a36Sopenharmony_ci struct pci_devres *dr, *new_dr; 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_ci dr = devres_find(&pdev->dev, pcim_release, NULL, NULL); 213862306a36Sopenharmony_ci if (dr) 213962306a36Sopenharmony_ci return dr; 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ci new_dr = devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL); 214262306a36Sopenharmony_ci if (!new_dr) 214362306a36Sopenharmony_ci return NULL; 214462306a36Sopenharmony_ci return devres_get(&pdev->dev, new_dr, NULL, NULL); 214562306a36Sopenharmony_ci} 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_cistatic struct pci_devres *find_pci_dr(struct pci_dev *pdev) 214862306a36Sopenharmony_ci{ 214962306a36Sopenharmony_ci if (pci_is_managed(pdev)) 215062306a36Sopenharmony_ci return devres_find(&pdev->dev, pcim_release, NULL, NULL); 215162306a36Sopenharmony_ci return NULL; 215262306a36Sopenharmony_ci} 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci/** 215562306a36Sopenharmony_ci * pcim_enable_device - Managed pci_enable_device() 215662306a36Sopenharmony_ci * @pdev: PCI device to be initialized 215762306a36Sopenharmony_ci * 215862306a36Sopenharmony_ci * Managed pci_enable_device(). 215962306a36Sopenharmony_ci */ 216062306a36Sopenharmony_ciint pcim_enable_device(struct pci_dev *pdev) 216162306a36Sopenharmony_ci{ 216262306a36Sopenharmony_ci struct pci_devres *dr; 216362306a36Sopenharmony_ci int rc; 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_ci dr = get_pci_dr(pdev); 216662306a36Sopenharmony_ci if (unlikely(!dr)) 216762306a36Sopenharmony_ci return -ENOMEM; 216862306a36Sopenharmony_ci if (dr->enabled) 216962306a36Sopenharmony_ci return 0; 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci rc = pci_enable_device(pdev); 217262306a36Sopenharmony_ci if (!rc) { 217362306a36Sopenharmony_ci pdev->is_managed = 1; 217462306a36Sopenharmony_ci dr->enabled = 1; 217562306a36Sopenharmony_ci } 217662306a36Sopenharmony_ci return rc; 217762306a36Sopenharmony_ci} 217862306a36Sopenharmony_ciEXPORT_SYMBOL(pcim_enable_device); 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_ci/** 218162306a36Sopenharmony_ci * pcim_pin_device - Pin managed PCI device 218262306a36Sopenharmony_ci * @pdev: PCI device to pin 218362306a36Sopenharmony_ci * 218462306a36Sopenharmony_ci * Pin managed PCI device @pdev. Pinned device won't be disabled on 218562306a36Sopenharmony_ci * driver detach. @pdev must have been enabled with 218662306a36Sopenharmony_ci * pcim_enable_device(). 218762306a36Sopenharmony_ci */ 218862306a36Sopenharmony_civoid pcim_pin_device(struct pci_dev *pdev) 218962306a36Sopenharmony_ci{ 219062306a36Sopenharmony_ci struct pci_devres *dr; 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci dr = find_pci_dr(pdev); 219362306a36Sopenharmony_ci WARN_ON(!dr || !dr->enabled); 219462306a36Sopenharmony_ci if (dr) 219562306a36Sopenharmony_ci dr->pinned = 1; 219662306a36Sopenharmony_ci} 219762306a36Sopenharmony_ciEXPORT_SYMBOL(pcim_pin_device); 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci/* 220062306a36Sopenharmony_ci * pcibios_device_add - provide arch specific hooks when adding device dev 220162306a36Sopenharmony_ci * @dev: the PCI device being added 220262306a36Sopenharmony_ci * 220362306a36Sopenharmony_ci * Permits the platform to provide architecture specific functionality when 220462306a36Sopenharmony_ci * devices are added. This is the default implementation. Architecture 220562306a36Sopenharmony_ci * implementations can override this. 220662306a36Sopenharmony_ci */ 220762306a36Sopenharmony_ciint __weak pcibios_device_add(struct pci_dev *dev) 220862306a36Sopenharmony_ci{ 220962306a36Sopenharmony_ci return 0; 221062306a36Sopenharmony_ci} 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_ci/** 221362306a36Sopenharmony_ci * pcibios_release_device - provide arch specific hooks when releasing 221462306a36Sopenharmony_ci * device dev 221562306a36Sopenharmony_ci * @dev: the PCI device being released 221662306a36Sopenharmony_ci * 221762306a36Sopenharmony_ci * Permits the platform to provide architecture specific functionality when 221862306a36Sopenharmony_ci * devices are released. This is the default implementation. Architecture 221962306a36Sopenharmony_ci * implementations can override this. 222062306a36Sopenharmony_ci */ 222162306a36Sopenharmony_civoid __weak pcibios_release_device(struct pci_dev *dev) {} 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_ci/** 222462306a36Sopenharmony_ci * pcibios_disable_device - disable arch specific PCI resources for device dev 222562306a36Sopenharmony_ci * @dev: the PCI device to disable 222662306a36Sopenharmony_ci * 222762306a36Sopenharmony_ci * Disables architecture specific PCI resources for the device. This 222862306a36Sopenharmony_ci * is the default implementation. Architecture implementations can 222962306a36Sopenharmony_ci * override this. 223062306a36Sopenharmony_ci */ 223162306a36Sopenharmony_civoid __weak pcibios_disable_device(struct pci_dev *dev) {} 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci/** 223462306a36Sopenharmony_ci * pcibios_penalize_isa_irq - penalize an ISA IRQ 223562306a36Sopenharmony_ci * @irq: ISA IRQ to penalize 223662306a36Sopenharmony_ci * @active: IRQ active or not 223762306a36Sopenharmony_ci * 223862306a36Sopenharmony_ci * Permits the platform to provide architecture-specific functionality when 223962306a36Sopenharmony_ci * penalizing ISA IRQs. This is the default implementation. Architecture 224062306a36Sopenharmony_ci * implementations can override this. 224162306a36Sopenharmony_ci */ 224262306a36Sopenharmony_civoid __weak pcibios_penalize_isa_irq(int irq, int active) {} 224362306a36Sopenharmony_ci 224462306a36Sopenharmony_cistatic void do_pci_disable_device(struct pci_dev *dev) 224562306a36Sopenharmony_ci{ 224662306a36Sopenharmony_ci u16 pci_command; 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &pci_command); 224962306a36Sopenharmony_ci if (pci_command & PCI_COMMAND_MASTER) { 225062306a36Sopenharmony_ci pci_command &= ~PCI_COMMAND_MASTER; 225162306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, pci_command); 225262306a36Sopenharmony_ci } 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci pcibios_disable_device(dev); 225562306a36Sopenharmony_ci} 225662306a36Sopenharmony_ci 225762306a36Sopenharmony_ci/** 225862306a36Sopenharmony_ci * pci_disable_enabled_device - Disable device without updating enable_cnt 225962306a36Sopenharmony_ci * @dev: PCI device to disable 226062306a36Sopenharmony_ci * 226162306a36Sopenharmony_ci * NOTE: This function is a backend of PCI power management routines and is 226262306a36Sopenharmony_ci * not supposed to be called drivers. 226362306a36Sopenharmony_ci */ 226462306a36Sopenharmony_civoid pci_disable_enabled_device(struct pci_dev *dev) 226562306a36Sopenharmony_ci{ 226662306a36Sopenharmony_ci if (pci_is_enabled(dev)) 226762306a36Sopenharmony_ci do_pci_disable_device(dev); 226862306a36Sopenharmony_ci} 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci/** 227162306a36Sopenharmony_ci * pci_disable_device - Disable PCI device after use 227262306a36Sopenharmony_ci * @dev: PCI device to be disabled 227362306a36Sopenharmony_ci * 227462306a36Sopenharmony_ci * Signal to the system that the PCI device is not in use by the system 227562306a36Sopenharmony_ci * anymore. This only involves disabling PCI bus-mastering, if active. 227662306a36Sopenharmony_ci * 227762306a36Sopenharmony_ci * Note we don't actually disable the device until all callers of 227862306a36Sopenharmony_ci * pci_enable_device() have called pci_disable_device(). 227962306a36Sopenharmony_ci */ 228062306a36Sopenharmony_civoid pci_disable_device(struct pci_dev *dev) 228162306a36Sopenharmony_ci{ 228262306a36Sopenharmony_ci struct pci_devres *dr; 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ci dr = find_pci_dr(dev); 228562306a36Sopenharmony_ci if (dr) 228662306a36Sopenharmony_ci dr->enabled = 0; 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0, 228962306a36Sopenharmony_ci "disabling already-disabled device"); 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci if (atomic_dec_return(&dev->enable_cnt) != 0) 229262306a36Sopenharmony_ci return; 229362306a36Sopenharmony_ci 229462306a36Sopenharmony_ci do_pci_disable_device(dev); 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci dev->is_busmaster = 0; 229762306a36Sopenharmony_ci} 229862306a36Sopenharmony_ciEXPORT_SYMBOL(pci_disable_device); 229962306a36Sopenharmony_ci 230062306a36Sopenharmony_ci/** 230162306a36Sopenharmony_ci * pcibios_set_pcie_reset_state - set reset state for device dev 230262306a36Sopenharmony_ci * @dev: the PCIe device reset 230362306a36Sopenharmony_ci * @state: Reset state to enter into 230462306a36Sopenharmony_ci * 230562306a36Sopenharmony_ci * Set the PCIe reset state for the device. This is the default 230662306a36Sopenharmony_ci * implementation. Architecture implementations can override this. 230762306a36Sopenharmony_ci */ 230862306a36Sopenharmony_ciint __weak pcibios_set_pcie_reset_state(struct pci_dev *dev, 230962306a36Sopenharmony_ci enum pcie_reset_state state) 231062306a36Sopenharmony_ci{ 231162306a36Sopenharmony_ci return -EINVAL; 231262306a36Sopenharmony_ci} 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci/** 231562306a36Sopenharmony_ci * pci_set_pcie_reset_state - set reset state for device dev 231662306a36Sopenharmony_ci * @dev: the PCIe device reset 231762306a36Sopenharmony_ci * @state: Reset state to enter into 231862306a36Sopenharmony_ci * 231962306a36Sopenharmony_ci * Sets the PCI reset state for the device. 232062306a36Sopenharmony_ci */ 232162306a36Sopenharmony_ciint pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) 232262306a36Sopenharmony_ci{ 232362306a36Sopenharmony_ci return pcibios_set_pcie_reset_state(dev, state); 232462306a36Sopenharmony_ci} 232562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_set_pcie_reset_state); 232662306a36Sopenharmony_ci 232762306a36Sopenharmony_ci#ifdef CONFIG_PCIEAER 232862306a36Sopenharmony_civoid pcie_clear_device_status(struct pci_dev *dev) 232962306a36Sopenharmony_ci{ 233062306a36Sopenharmony_ci u16 sta; 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &sta); 233362306a36Sopenharmony_ci pcie_capability_write_word(dev, PCI_EXP_DEVSTA, sta); 233462306a36Sopenharmony_ci} 233562306a36Sopenharmony_ci#endif 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci/** 233862306a36Sopenharmony_ci * pcie_clear_root_pme_status - Clear root port PME interrupt status. 233962306a36Sopenharmony_ci * @dev: PCIe root port or event collector. 234062306a36Sopenharmony_ci */ 234162306a36Sopenharmony_civoid pcie_clear_root_pme_status(struct pci_dev *dev) 234262306a36Sopenharmony_ci{ 234362306a36Sopenharmony_ci pcie_capability_set_dword(dev, PCI_EXP_RTSTA, PCI_EXP_RTSTA_PME); 234462306a36Sopenharmony_ci} 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci/** 234762306a36Sopenharmony_ci * pci_check_pme_status - Check if given device has generated PME. 234862306a36Sopenharmony_ci * @dev: Device to check. 234962306a36Sopenharmony_ci * 235062306a36Sopenharmony_ci * Check the PME status of the device and if set, clear it and clear PME enable 235162306a36Sopenharmony_ci * (if set). Return 'true' if PME status and PME enable were both set or 235262306a36Sopenharmony_ci * 'false' otherwise. 235362306a36Sopenharmony_ci */ 235462306a36Sopenharmony_cibool pci_check_pme_status(struct pci_dev *dev) 235562306a36Sopenharmony_ci{ 235662306a36Sopenharmony_ci int pmcsr_pos; 235762306a36Sopenharmony_ci u16 pmcsr; 235862306a36Sopenharmony_ci bool ret = false; 235962306a36Sopenharmony_ci 236062306a36Sopenharmony_ci if (!dev->pm_cap) 236162306a36Sopenharmony_ci return false; 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci pmcsr_pos = dev->pm_cap + PCI_PM_CTRL; 236462306a36Sopenharmony_ci pci_read_config_word(dev, pmcsr_pos, &pmcsr); 236562306a36Sopenharmony_ci if (!(pmcsr & PCI_PM_CTRL_PME_STATUS)) 236662306a36Sopenharmony_ci return false; 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci /* Clear PME status. */ 236962306a36Sopenharmony_ci pmcsr |= PCI_PM_CTRL_PME_STATUS; 237062306a36Sopenharmony_ci if (pmcsr & PCI_PM_CTRL_PME_ENABLE) { 237162306a36Sopenharmony_ci /* Disable PME to avoid interrupt flood. */ 237262306a36Sopenharmony_ci pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; 237362306a36Sopenharmony_ci ret = true; 237462306a36Sopenharmony_ci } 237562306a36Sopenharmony_ci 237662306a36Sopenharmony_ci pci_write_config_word(dev, pmcsr_pos, pmcsr); 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci return ret; 237962306a36Sopenharmony_ci} 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci/** 238262306a36Sopenharmony_ci * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. 238362306a36Sopenharmony_ci * @dev: Device to handle. 238462306a36Sopenharmony_ci * @pme_poll_reset: Whether or not to reset the device's pme_poll flag. 238562306a36Sopenharmony_ci * 238662306a36Sopenharmony_ci * Check if @dev has generated PME and queue a resume request for it in that 238762306a36Sopenharmony_ci * case. 238862306a36Sopenharmony_ci */ 238962306a36Sopenharmony_cistatic int pci_pme_wakeup(struct pci_dev *dev, void *pme_poll_reset) 239062306a36Sopenharmony_ci{ 239162306a36Sopenharmony_ci if (pme_poll_reset && dev->pme_poll) 239262306a36Sopenharmony_ci dev->pme_poll = false; 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci if (pci_check_pme_status(dev)) { 239562306a36Sopenharmony_ci pci_wakeup_event(dev); 239662306a36Sopenharmony_ci pm_request_resume(&dev->dev); 239762306a36Sopenharmony_ci } 239862306a36Sopenharmony_ci return 0; 239962306a36Sopenharmony_ci} 240062306a36Sopenharmony_ci 240162306a36Sopenharmony_ci/** 240262306a36Sopenharmony_ci * pci_pme_wakeup_bus - Walk given bus and wake up devices on it, if necessary. 240362306a36Sopenharmony_ci * @bus: Top bus of the subtree to walk. 240462306a36Sopenharmony_ci */ 240562306a36Sopenharmony_civoid pci_pme_wakeup_bus(struct pci_bus *bus) 240662306a36Sopenharmony_ci{ 240762306a36Sopenharmony_ci if (bus) 240862306a36Sopenharmony_ci pci_walk_bus(bus, pci_pme_wakeup, (void *)true); 240962306a36Sopenharmony_ci} 241062306a36Sopenharmony_ci 241162306a36Sopenharmony_ci 241262306a36Sopenharmony_ci/** 241362306a36Sopenharmony_ci * pci_pme_capable - check the capability of PCI device to generate PME# 241462306a36Sopenharmony_ci * @dev: PCI device to handle. 241562306a36Sopenharmony_ci * @state: PCI state from which device will issue PME#. 241662306a36Sopenharmony_ci */ 241762306a36Sopenharmony_cibool pci_pme_capable(struct pci_dev *dev, pci_power_t state) 241862306a36Sopenharmony_ci{ 241962306a36Sopenharmony_ci if (!dev->pm_cap) 242062306a36Sopenharmony_ci return false; 242162306a36Sopenharmony_ci 242262306a36Sopenharmony_ci return !!(dev->pme_support & (1 << state)); 242362306a36Sopenharmony_ci} 242462306a36Sopenharmony_ciEXPORT_SYMBOL(pci_pme_capable); 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_cistatic void pci_pme_list_scan(struct work_struct *work) 242762306a36Sopenharmony_ci{ 242862306a36Sopenharmony_ci struct pci_pme_device *pme_dev, *n; 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_ci mutex_lock(&pci_pme_list_mutex); 243162306a36Sopenharmony_ci list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) { 243262306a36Sopenharmony_ci struct pci_dev *pdev = pme_dev->dev; 243362306a36Sopenharmony_ci 243462306a36Sopenharmony_ci if (pdev->pme_poll) { 243562306a36Sopenharmony_ci struct pci_dev *bridge = pdev->bus->self; 243662306a36Sopenharmony_ci struct device *dev = &pdev->dev; 243762306a36Sopenharmony_ci struct device *bdev = bridge ? &bridge->dev : NULL; 243862306a36Sopenharmony_ci int bref = 0; 243962306a36Sopenharmony_ci 244062306a36Sopenharmony_ci /* 244162306a36Sopenharmony_ci * If we have a bridge, it should be in an active/D0 244262306a36Sopenharmony_ci * state or the configuration space of subordinate 244362306a36Sopenharmony_ci * devices may not be accessible or stable over the 244462306a36Sopenharmony_ci * course of the call. 244562306a36Sopenharmony_ci */ 244662306a36Sopenharmony_ci if (bdev) { 244762306a36Sopenharmony_ci bref = pm_runtime_get_if_active(bdev, true); 244862306a36Sopenharmony_ci if (!bref) 244962306a36Sopenharmony_ci continue; 245062306a36Sopenharmony_ci 245162306a36Sopenharmony_ci if (bridge->current_state != PCI_D0) 245262306a36Sopenharmony_ci goto put_bridge; 245362306a36Sopenharmony_ci } 245462306a36Sopenharmony_ci 245562306a36Sopenharmony_ci /* 245662306a36Sopenharmony_ci * The device itself should be suspended but config 245762306a36Sopenharmony_ci * space must be accessible, therefore it cannot be in 245862306a36Sopenharmony_ci * D3cold. 245962306a36Sopenharmony_ci */ 246062306a36Sopenharmony_ci if (pm_runtime_suspended(dev) && 246162306a36Sopenharmony_ci pdev->current_state != PCI_D3cold) 246262306a36Sopenharmony_ci pci_pme_wakeup(pdev, NULL); 246362306a36Sopenharmony_ci 246462306a36Sopenharmony_ciput_bridge: 246562306a36Sopenharmony_ci if (bref > 0) 246662306a36Sopenharmony_ci pm_runtime_put(bdev); 246762306a36Sopenharmony_ci } else { 246862306a36Sopenharmony_ci list_del(&pme_dev->list); 246962306a36Sopenharmony_ci kfree(pme_dev); 247062306a36Sopenharmony_ci } 247162306a36Sopenharmony_ci } 247262306a36Sopenharmony_ci if (!list_empty(&pci_pme_list)) 247362306a36Sopenharmony_ci queue_delayed_work(system_freezable_wq, &pci_pme_work, 247462306a36Sopenharmony_ci msecs_to_jiffies(PME_TIMEOUT)); 247562306a36Sopenharmony_ci mutex_unlock(&pci_pme_list_mutex); 247662306a36Sopenharmony_ci} 247762306a36Sopenharmony_ci 247862306a36Sopenharmony_cistatic void __pci_pme_active(struct pci_dev *dev, bool enable) 247962306a36Sopenharmony_ci{ 248062306a36Sopenharmony_ci u16 pmcsr; 248162306a36Sopenharmony_ci 248262306a36Sopenharmony_ci if (!dev->pme_support) 248362306a36Sopenharmony_ci return; 248462306a36Sopenharmony_ci 248562306a36Sopenharmony_ci pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 248662306a36Sopenharmony_ci /* Clear PME_Status by writing 1 to it and enable PME# */ 248762306a36Sopenharmony_ci pmcsr |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE; 248862306a36Sopenharmony_ci if (!enable) 248962306a36Sopenharmony_ci pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; 249062306a36Sopenharmony_ci 249162306a36Sopenharmony_ci pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); 249262306a36Sopenharmony_ci} 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ci/** 249562306a36Sopenharmony_ci * pci_pme_restore - Restore PME configuration after config space restore. 249662306a36Sopenharmony_ci * @dev: PCI device to update. 249762306a36Sopenharmony_ci */ 249862306a36Sopenharmony_civoid pci_pme_restore(struct pci_dev *dev) 249962306a36Sopenharmony_ci{ 250062306a36Sopenharmony_ci u16 pmcsr; 250162306a36Sopenharmony_ci 250262306a36Sopenharmony_ci if (!dev->pme_support) 250362306a36Sopenharmony_ci return; 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); 250662306a36Sopenharmony_ci if (dev->wakeup_prepared) { 250762306a36Sopenharmony_ci pmcsr |= PCI_PM_CTRL_PME_ENABLE; 250862306a36Sopenharmony_ci pmcsr &= ~PCI_PM_CTRL_PME_STATUS; 250962306a36Sopenharmony_ci } else { 251062306a36Sopenharmony_ci pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; 251162306a36Sopenharmony_ci pmcsr |= PCI_PM_CTRL_PME_STATUS; 251262306a36Sopenharmony_ci } 251362306a36Sopenharmony_ci pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); 251462306a36Sopenharmony_ci} 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci/** 251762306a36Sopenharmony_ci * pci_pme_active - enable or disable PCI device's PME# function 251862306a36Sopenharmony_ci * @dev: PCI device to handle. 251962306a36Sopenharmony_ci * @enable: 'true' to enable PME# generation; 'false' to disable it. 252062306a36Sopenharmony_ci * 252162306a36Sopenharmony_ci * The caller must verify that the device is capable of generating PME# before 252262306a36Sopenharmony_ci * calling this function with @enable equal to 'true'. 252362306a36Sopenharmony_ci */ 252462306a36Sopenharmony_civoid pci_pme_active(struct pci_dev *dev, bool enable) 252562306a36Sopenharmony_ci{ 252662306a36Sopenharmony_ci __pci_pme_active(dev, enable); 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci /* 252962306a36Sopenharmony_ci * PCI (as opposed to PCIe) PME requires that the device have 253062306a36Sopenharmony_ci * its PME# line hooked up correctly. Not all hardware vendors 253162306a36Sopenharmony_ci * do this, so the PME never gets delivered and the device 253262306a36Sopenharmony_ci * remains asleep. The easiest way around this is to 253362306a36Sopenharmony_ci * periodically walk the list of suspended devices and check 253462306a36Sopenharmony_ci * whether any have their PME flag set. The assumption is that 253562306a36Sopenharmony_ci * we'll wake up often enough anyway that this won't be a huge 253662306a36Sopenharmony_ci * hit, and the power savings from the devices will still be a 253762306a36Sopenharmony_ci * win. 253862306a36Sopenharmony_ci * 253962306a36Sopenharmony_ci * Although PCIe uses in-band PME message instead of PME# line 254062306a36Sopenharmony_ci * to report PME, PME does not work for some PCIe devices in 254162306a36Sopenharmony_ci * reality. For example, there are devices that set their PME 254262306a36Sopenharmony_ci * status bits, but don't really bother to send a PME message; 254362306a36Sopenharmony_ci * there are PCI Express Root Ports that don't bother to 254462306a36Sopenharmony_ci * trigger interrupts when they receive PME messages from the 254562306a36Sopenharmony_ci * devices below. So PME poll is used for PCIe devices too. 254662306a36Sopenharmony_ci */ 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci if (dev->pme_poll) { 254962306a36Sopenharmony_ci struct pci_pme_device *pme_dev; 255062306a36Sopenharmony_ci if (enable) { 255162306a36Sopenharmony_ci pme_dev = kmalloc(sizeof(struct pci_pme_device), 255262306a36Sopenharmony_ci GFP_KERNEL); 255362306a36Sopenharmony_ci if (!pme_dev) { 255462306a36Sopenharmony_ci pci_warn(dev, "can't enable PME#\n"); 255562306a36Sopenharmony_ci return; 255662306a36Sopenharmony_ci } 255762306a36Sopenharmony_ci pme_dev->dev = dev; 255862306a36Sopenharmony_ci mutex_lock(&pci_pme_list_mutex); 255962306a36Sopenharmony_ci list_add(&pme_dev->list, &pci_pme_list); 256062306a36Sopenharmony_ci if (list_is_singular(&pci_pme_list)) 256162306a36Sopenharmony_ci queue_delayed_work(system_freezable_wq, 256262306a36Sopenharmony_ci &pci_pme_work, 256362306a36Sopenharmony_ci msecs_to_jiffies(PME_TIMEOUT)); 256462306a36Sopenharmony_ci mutex_unlock(&pci_pme_list_mutex); 256562306a36Sopenharmony_ci } else { 256662306a36Sopenharmony_ci mutex_lock(&pci_pme_list_mutex); 256762306a36Sopenharmony_ci list_for_each_entry(pme_dev, &pci_pme_list, list) { 256862306a36Sopenharmony_ci if (pme_dev->dev == dev) { 256962306a36Sopenharmony_ci list_del(&pme_dev->list); 257062306a36Sopenharmony_ci kfree(pme_dev); 257162306a36Sopenharmony_ci break; 257262306a36Sopenharmony_ci } 257362306a36Sopenharmony_ci } 257462306a36Sopenharmony_ci mutex_unlock(&pci_pme_list_mutex); 257562306a36Sopenharmony_ci } 257662306a36Sopenharmony_ci } 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_ci pci_dbg(dev, "PME# %s\n", enable ? "enabled" : "disabled"); 257962306a36Sopenharmony_ci} 258062306a36Sopenharmony_ciEXPORT_SYMBOL(pci_pme_active); 258162306a36Sopenharmony_ci 258262306a36Sopenharmony_ci/** 258362306a36Sopenharmony_ci * __pci_enable_wake - enable PCI device as wakeup event source 258462306a36Sopenharmony_ci * @dev: PCI device affected 258562306a36Sopenharmony_ci * @state: PCI state from which device will issue wakeup events 258662306a36Sopenharmony_ci * @enable: True to enable event generation; false to disable 258762306a36Sopenharmony_ci * 258862306a36Sopenharmony_ci * This enables the device as a wakeup event source, or disables it. 258962306a36Sopenharmony_ci * When such events involves platform-specific hooks, those hooks are 259062306a36Sopenharmony_ci * called automatically by this routine. 259162306a36Sopenharmony_ci * 259262306a36Sopenharmony_ci * Devices with legacy power management (no standard PCI PM capabilities) 259362306a36Sopenharmony_ci * always require such platform hooks. 259462306a36Sopenharmony_ci * 259562306a36Sopenharmony_ci * RETURN VALUE: 259662306a36Sopenharmony_ci * 0 is returned on success 259762306a36Sopenharmony_ci * -EINVAL is returned if device is not supposed to wake up the system 259862306a36Sopenharmony_ci * Error code depending on the platform is returned if both the platform and 259962306a36Sopenharmony_ci * the native mechanism fail to enable the generation of wake-up events 260062306a36Sopenharmony_ci */ 260162306a36Sopenharmony_cistatic int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) 260262306a36Sopenharmony_ci{ 260362306a36Sopenharmony_ci int ret = 0; 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci /* 260662306a36Sopenharmony_ci * Bridges that are not power-manageable directly only signal 260762306a36Sopenharmony_ci * wakeup on behalf of subordinate devices which is set up 260862306a36Sopenharmony_ci * elsewhere, so skip them. However, bridges that are 260962306a36Sopenharmony_ci * power-manageable may signal wakeup for themselves (for example, 261062306a36Sopenharmony_ci * on a hotplug event) and they need to be covered here. 261162306a36Sopenharmony_ci */ 261262306a36Sopenharmony_ci if (!pci_power_manageable(dev)) 261362306a36Sopenharmony_ci return 0; 261462306a36Sopenharmony_ci 261562306a36Sopenharmony_ci /* Don't do the same thing twice in a row for one device. */ 261662306a36Sopenharmony_ci if (!!enable == !!dev->wakeup_prepared) 261762306a36Sopenharmony_ci return 0; 261862306a36Sopenharmony_ci 261962306a36Sopenharmony_ci /* 262062306a36Sopenharmony_ci * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don 262162306a36Sopenharmony_ci * Anderson we should be doing PME# wake enable followed by ACPI wake 262262306a36Sopenharmony_ci * enable. To disable wake-up we call the platform first, for symmetry. 262362306a36Sopenharmony_ci */ 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_ci if (enable) { 262662306a36Sopenharmony_ci int error; 262762306a36Sopenharmony_ci 262862306a36Sopenharmony_ci /* 262962306a36Sopenharmony_ci * Enable PME signaling if the device can signal PME from 263062306a36Sopenharmony_ci * D3cold regardless of whether or not it can signal PME from 263162306a36Sopenharmony_ci * the current target state, because that will allow it to 263262306a36Sopenharmony_ci * signal PME when the hierarchy above it goes into D3cold and 263362306a36Sopenharmony_ci * the device itself ends up in D3cold as a result of that. 263462306a36Sopenharmony_ci */ 263562306a36Sopenharmony_ci if (pci_pme_capable(dev, state) || pci_pme_capable(dev, PCI_D3cold)) 263662306a36Sopenharmony_ci pci_pme_active(dev, true); 263762306a36Sopenharmony_ci else 263862306a36Sopenharmony_ci ret = 1; 263962306a36Sopenharmony_ci error = platform_pci_set_wakeup(dev, true); 264062306a36Sopenharmony_ci if (ret) 264162306a36Sopenharmony_ci ret = error; 264262306a36Sopenharmony_ci if (!ret) 264362306a36Sopenharmony_ci dev->wakeup_prepared = true; 264462306a36Sopenharmony_ci } else { 264562306a36Sopenharmony_ci platform_pci_set_wakeup(dev, false); 264662306a36Sopenharmony_ci pci_pme_active(dev, false); 264762306a36Sopenharmony_ci dev->wakeup_prepared = false; 264862306a36Sopenharmony_ci } 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_ci return ret; 265162306a36Sopenharmony_ci} 265262306a36Sopenharmony_ci 265362306a36Sopenharmony_ci/** 265462306a36Sopenharmony_ci * pci_enable_wake - change wakeup settings for a PCI device 265562306a36Sopenharmony_ci * @pci_dev: Target device 265662306a36Sopenharmony_ci * @state: PCI state from which device will issue wakeup events 265762306a36Sopenharmony_ci * @enable: Whether or not to enable event generation 265862306a36Sopenharmony_ci * 265962306a36Sopenharmony_ci * If @enable is set, check device_may_wakeup() for the device before calling 266062306a36Sopenharmony_ci * __pci_enable_wake() for it. 266162306a36Sopenharmony_ci */ 266262306a36Sopenharmony_ciint pci_enable_wake(struct pci_dev *pci_dev, pci_power_t state, bool enable) 266362306a36Sopenharmony_ci{ 266462306a36Sopenharmony_ci if (enable && !device_may_wakeup(&pci_dev->dev)) 266562306a36Sopenharmony_ci return -EINVAL; 266662306a36Sopenharmony_ci 266762306a36Sopenharmony_ci return __pci_enable_wake(pci_dev, state, enable); 266862306a36Sopenharmony_ci} 266962306a36Sopenharmony_ciEXPORT_SYMBOL(pci_enable_wake); 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci/** 267262306a36Sopenharmony_ci * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold 267362306a36Sopenharmony_ci * @dev: PCI device to prepare 267462306a36Sopenharmony_ci * @enable: True to enable wake-up event generation; false to disable 267562306a36Sopenharmony_ci * 267662306a36Sopenharmony_ci * Many drivers want the device to wake up the system from D3_hot or D3_cold 267762306a36Sopenharmony_ci * and this function allows them to set that up cleanly - pci_enable_wake() 267862306a36Sopenharmony_ci * should not be called twice in a row to enable wake-up due to PCI PM vs ACPI 267962306a36Sopenharmony_ci * ordering constraints. 268062306a36Sopenharmony_ci * 268162306a36Sopenharmony_ci * This function only returns error code if the device is not allowed to wake 268262306a36Sopenharmony_ci * up the system from sleep or it is not capable of generating PME# from both 268362306a36Sopenharmony_ci * D3_hot and D3_cold and the platform is unable to enable wake-up power for it. 268462306a36Sopenharmony_ci */ 268562306a36Sopenharmony_ciint pci_wake_from_d3(struct pci_dev *dev, bool enable) 268662306a36Sopenharmony_ci{ 268762306a36Sopenharmony_ci return pci_pme_capable(dev, PCI_D3cold) ? 268862306a36Sopenharmony_ci pci_enable_wake(dev, PCI_D3cold, enable) : 268962306a36Sopenharmony_ci pci_enable_wake(dev, PCI_D3hot, enable); 269062306a36Sopenharmony_ci} 269162306a36Sopenharmony_ciEXPORT_SYMBOL(pci_wake_from_d3); 269262306a36Sopenharmony_ci 269362306a36Sopenharmony_ci/** 269462306a36Sopenharmony_ci * pci_target_state - find an appropriate low power state for a given PCI dev 269562306a36Sopenharmony_ci * @dev: PCI device 269662306a36Sopenharmony_ci * @wakeup: Whether or not wakeup functionality will be enabled for the device. 269762306a36Sopenharmony_ci * 269862306a36Sopenharmony_ci * Use underlying platform code to find a supported low power state for @dev. 269962306a36Sopenharmony_ci * If the platform can't manage @dev, return the deepest state from which it 270062306a36Sopenharmony_ci * can generate wake events, based on any available PME info. 270162306a36Sopenharmony_ci */ 270262306a36Sopenharmony_cistatic pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup) 270362306a36Sopenharmony_ci{ 270462306a36Sopenharmony_ci if (platform_pci_power_manageable(dev)) { 270562306a36Sopenharmony_ci /* 270662306a36Sopenharmony_ci * Call the platform to find the target state for the device. 270762306a36Sopenharmony_ci */ 270862306a36Sopenharmony_ci pci_power_t state = platform_pci_choose_state(dev); 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci switch (state) { 271162306a36Sopenharmony_ci case PCI_POWER_ERROR: 271262306a36Sopenharmony_ci case PCI_UNKNOWN: 271362306a36Sopenharmony_ci return PCI_D3hot; 271462306a36Sopenharmony_ci 271562306a36Sopenharmony_ci case PCI_D1: 271662306a36Sopenharmony_ci case PCI_D2: 271762306a36Sopenharmony_ci if (pci_no_d1d2(dev)) 271862306a36Sopenharmony_ci return PCI_D3hot; 271962306a36Sopenharmony_ci } 272062306a36Sopenharmony_ci 272162306a36Sopenharmony_ci return state; 272262306a36Sopenharmony_ci } 272362306a36Sopenharmony_ci 272462306a36Sopenharmony_ci /* 272562306a36Sopenharmony_ci * If the device is in D3cold even though it's not power-manageable by 272662306a36Sopenharmony_ci * the platform, it may have been powered down by non-standard means. 272762306a36Sopenharmony_ci * Best to let it slumber. 272862306a36Sopenharmony_ci */ 272962306a36Sopenharmony_ci if (dev->current_state == PCI_D3cold) 273062306a36Sopenharmony_ci return PCI_D3cold; 273162306a36Sopenharmony_ci else if (!dev->pm_cap) 273262306a36Sopenharmony_ci return PCI_D0; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci if (wakeup && dev->pme_support) { 273562306a36Sopenharmony_ci pci_power_t state = PCI_D3hot; 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ci /* 273862306a36Sopenharmony_ci * Find the deepest state from which the device can generate 273962306a36Sopenharmony_ci * PME#. 274062306a36Sopenharmony_ci */ 274162306a36Sopenharmony_ci while (state && !(dev->pme_support & (1 << state))) 274262306a36Sopenharmony_ci state--; 274362306a36Sopenharmony_ci 274462306a36Sopenharmony_ci if (state) 274562306a36Sopenharmony_ci return state; 274662306a36Sopenharmony_ci else if (dev->pme_support & 1) 274762306a36Sopenharmony_ci return PCI_D0; 274862306a36Sopenharmony_ci } 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci return PCI_D3hot; 275162306a36Sopenharmony_ci} 275262306a36Sopenharmony_ci 275362306a36Sopenharmony_ci/** 275462306a36Sopenharmony_ci * pci_prepare_to_sleep - prepare PCI device for system-wide transition 275562306a36Sopenharmony_ci * into a sleep state 275662306a36Sopenharmony_ci * @dev: Device to handle. 275762306a36Sopenharmony_ci * 275862306a36Sopenharmony_ci * Choose the power state appropriate for the device depending on whether 275962306a36Sopenharmony_ci * it can wake up the system and/or is power manageable by the platform 276062306a36Sopenharmony_ci * (PCI_D3hot is the default) and put the device into that state. 276162306a36Sopenharmony_ci */ 276262306a36Sopenharmony_ciint pci_prepare_to_sleep(struct pci_dev *dev) 276362306a36Sopenharmony_ci{ 276462306a36Sopenharmony_ci bool wakeup = device_may_wakeup(&dev->dev); 276562306a36Sopenharmony_ci pci_power_t target_state = pci_target_state(dev, wakeup); 276662306a36Sopenharmony_ci int error; 276762306a36Sopenharmony_ci 276862306a36Sopenharmony_ci if (target_state == PCI_POWER_ERROR) 276962306a36Sopenharmony_ci return -EIO; 277062306a36Sopenharmony_ci 277162306a36Sopenharmony_ci pci_enable_wake(dev, target_state, wakeup); 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci error = pci_set_power_state(dev, target_state); 277462306a36Sopenharmony_ci 277562306a36Sopenharmony_ci if (error) 277662306a36Sopenharmony_ci pci_enable_wake(dev, target_state, false); 277762306a36Sopenharmony_ci 277862306a36Sopenharmony_ci return error; 277962306a36Sopenharmony_ci} 278062306a36Sopenharmony_ciEXPORT_SYMBOL(pci_prepare_to_sleep); 278162306a36Sopenharmony_ci 278262306a36Sopenharmony_ci/** 278362306a36Sopenharmony_ci * pci_back_from_sleep - turn PCI device on during system-wide transition 278462306a36Sopenharmony_ci * into working state 278562306a36Sopenharmony_ci * @dev: Device to handle. 278662306a36Sopenharmony_ci * 278762306a36Sopenharmony_ci * Disable device's system wake-up capability and put it into D0. 278862306a36Sopenharmony_ci */ 278962306a36Sopenharmony_ciint pci_back_from_sleep(struct pci_dev *dev) 279062306a36Sopenharmony_ci{ 279162306a36Sopenharmony_ci int ret = pci_set_power_state(dev, PCI_D0); 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci if (ret) 279462306a36Sopenharmony_ci return ret; 279562306a36Sopenharmony_ci 279662306a36Sopenharmony_ci pci_enable_wake(dev, PCI_D0, false); 279762306a36Sopenharmony_ci return 0; 279862306a36Sopenharmony_ci} 279962306a36Sopenharmony_ciEXPORT_SYMBOL(pci_back_from_sleep); 280062306a36Sopenharmony_ci 280162306a36Sopenharmony_ci/** 280262306a36Sopenharmony_ci * pci_finish_runtime_suspend - Carry out PCI-specific part of runtime suspend. 280362306a36Sopenharmony_ci * @dev: PCI device being suspended. 280462306a36Sopenharmony_ci * 280562306a36Sopenharmony_ci * Prepare @dev to generate wake-up events at run time and put it into a low 280662306a36Sopenharmony_ci * power state. 280762306a36Sopenharmony_ci */ 280862306a36Sopenharmony_ciint pci_finish_runtime_suspend(struct pci_dev *dev) 280962306a36Sopenharmony_ci{ 281062306a36Sopenharmony_ci pci_power_t target_state; 281162306a36Sopenharmony_ci int error; 281262306a36Sopenharmony_ci 281362306a36Sopenharmony_ci target_state = pci_target_state(dev, device_can_wakeup(&dev->dev)); 281462306a36Sopenharmony_ci if (target_state == PCI_POWER_ERROR) 281562306a36Sopenharmony_ci return -EIO; 281662306a36Sopenharmony_ci 281762306a36Sopenharmony_ci __pci_enable_wake(dev, target_state, pci_dev_run_wake(dev)); 281862306a36Sopenharmony_ci 281962306a36Sopenharmony_ci error = pci_set_power_state(dev, target_state); 282062306a36Sopenharmony_ci 282162306a36Sopenharmony_ci if (error) 282262306a36Sopenharmony_ci pci_enable_wake(dev, target_state, false); 282362306a36Sopenharmony_ci 282462306a36Sopenharmony_ci return error; 282562306a36Sopenharmony_ci} 282662306a36Sopenharmony_ci 282762306a36Sopenharmony_ci/** 282862306a36Sopenharmony_ci * pci_dev_run_wake - Check if device can generate run-time wake-up events. 282962306a36Sopenharmony_ci * @dev: Device to check. 283062306a36Sopenharmony_ci * 283162306a36Sopenharmony_ci * Return true if the device itself is capable of generating wake-up events 283262306a36Sopenharmony_ci * (through the platform or using the native PCIe PME) or if the device supports 283362306a36Sopenharmony_ci * PME and one of its upstream bridges can generate wake-up events. 283462306a36Sopenharmony_ci */ 283562306a36Sopenharmony_cibool pci_dev_run_wake(struct pci_dev *dev) 283662306a36Sopenharmony_ci{ 283762306a36Sopenharmony_ci struct pci_bus *bus = dev->bus; 283862306a36Sopenharmony_ci 283962306a36Sopenharmony_ci if (!dev->pme_support) 284062306a36Sopenharmony_ci return false; 284162306a36Sopenharmony_ci 284262306a36Sopenharmony_ci /* PME-capable in principle, but not from the target power state */ 284362306a36Sopenharmony_ci if (!pci_pme_capable(dev, pci_target_state(dev, true))) 284462306a36Sopenharmony_ci return false; 284562306a36Sopenharmony_ci 284662306a36Sopenharmony_ci if (device_can_wakeup(&dev->dev)) 284762306a36Sopenharmony_ci return true; 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_ci while (bus->parent) { 285062306a36Sopenharmony_ci struct pci_dev *bridge = bus->self; 285162306a36Sopenharmony_ci 285262306a36Sopenharmony_ci if (device_can_wakeup(&bridge->dev)) 285362306a36Sopenharmony_ci return true; 285462306a36Sopenharmony_ci 285562306a36Sopenharmony_ci bus = bus->parent; 285662306a36Sopenharmony_ci } 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci /* We have reached the root bus. */ 285962306a36Sopenharmony_ci if (bus->bridge) 286062306a36Sopenharmony_ci return device_can_wakeup(bus->bridge); 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci return false; 286362306a36Sopenharmony_ci} 286462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_dev_run_wake); 286562306a36Sopenharmony_ci 286662306a36Sopenharmony_ci/** 286762306a36Sopenharmony_ci * pci_dev_need_resume - Check if it is necessary to resume the device. 286862306a36Sopenharmony_ci * @pci_dev: Device to check. 286962306a36Sopenharmony_ci * 287062306a36Sopenharmony_ci * Return 'true' if the device is not runtime-suspended or it has to be 287162306a36Sopenharmony_ci * reconfigured due to wakeup settings difference between system and runtime 287262306a36Sopenharmony_ci * suspend, or the current power state of it is not suitable for the upcoming 287362306a36Sopenharmony_ci * (system-wide) transition. 287462306a36Sopenharmony_ci */ 287562306a36Sopenharmony_cibool pci_dev_need_resume(struct pci_dev *pci_dev) 287662306a36Sopenharmony_ci{ 287762306a36Sopenharmony_ci struct device *dev = &pci_dev->dev; 287862306a36Sopenharmony_ci pci_power_t target_state; 287962306a36Sopenharmony_ci 288062306a36Sopenharmony_ci if (!pm_runtime_suspended(dev) || platform_pci_need_resume(pci_dev)) 288162306a36Sopenharmony_ci return true; 288262306a36Sopenharmony_ci 288362306a36Sopenharmony_ci target_state = pci_target_state(pci_dev, device_may_wakeup(dev)); 288462306a36Sopenharmony_ci 288562306a36Sopenharmony_ci /* 288662306a36Sopenharmony_ci * If the earlier platform check has not triggered, D3cold is just power 288762306a36Sopenharmony_ci * removal on top of D3hot, so no need to resume the device in that 288862306a36Sopenharmony_ci * case. 288962306a36Sopenharmony_ci */ 289062306a36Sopenharmony_ci return target_state != pci_dev->current_state && 289162306a36Sopenharmony_ci target_state != PCI_D3cold && 289262306a36Sopenharmony_ci pci_dev->current_state != PCI_D3hot; 289362306a36Sopenharmony_ci} 289462306a36Sopenharmony_ci 289562306a36Sopenharmony_ci/** 289662306a36Sopenharmony_ci * pci_dev_adjust_pme - Adjust PME setting for a suspended device. 289762306a36Sopenharmony_ci * @pci_dev: Device to check. 289862306a36Sopenharmony_ci * 289962306a36Sopenharmony_ci * If the device is suspended and it is not configured for system wakeup, 290062306a36Sopenharmony_ci * disable PME for it to prevent it from waking up the system unnecessarily. 290162306a36Sopenharmony_ci * 290262306a36Sopenharmony_ci * Note that if the device's power state is D3cold and the platform check in 290362306a36Sopenharmony_ci * pci_dev_need_resume() has not triggered, the device's configuration need not 290462306a36Sopenharmony_ci * be changed. 290562306a36Sopenharmony_ci */ 290662306a36Sopenharmony_civoid pci_dev_adjust_pme(struct pci_dev *pci_dev) 290762306a36Sopenharmony_ci{ 290862306a36Sopenharmony_ci struct device *dev = &pci_dev->dev; 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_ci spin_lock_irq(&dev->power.lock); 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci if (pm_runtime_suspended(dev) && !device_may_wakeup(dev) && 291362306a36Sopenharmony_ci pci_dev->current_state < PCI_D3cold) 291462306a36Sopenharmony_ci __pci_pme_active(pci_dev, false); 291562306a36Sopenharmony_ci 291662306a36Sopenharmony_ci spin_unlock_irq(&dev->power.lock); 291762306a36Sopenharmony_ci} 291862306a36Sopenharmony_ci 291962306a36Sopenharmony_ci/** 292062306a36Sopenharmony_ci * pci_dev_complete_resume - Finalize resume from system sleep for a device. 292162306a36Sopenharmony_ci * @pci_dev: Device to handle. 292262306a36Sopenharmony_ci * 292362306a36Sopenharmony_ci * If the device is runtime suspended and wakeup-capable, enable PME for it as 292462306a36Sopenharmony_ci * it might have been disabled during the prepare phase of system suspend if 292562306a36Sopenharmony_ci * the device was not configured for system wakeup. 292662306a36Sopenharmony_ci */ 292762306a36Sopenharmony_civoid pci_dev_complete_resume(struct pci_dev *pci_dev) 292862306a36Sopenharmony_ci{ 292962306a36Sopenharmony_ci struct device *dev = &pci_dev->dev; 293062306a36Sopenharmony_ci 293162306a36Sopenharmony_ci if (!pci_dev_run_wake(pci_dev)) 293262306a36Sopenharmony_ci return; 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_ci spin_lock_irq(&dev->power.lock); 293562306a36Sopenharmony_ci 293662306a36Sopenharmony_ci if (pm_runtime_suspended(dev) && pci_dev->current_state < PCI_D3cold) 293762306a36Sopenharmony_ci __pci_pme_active(pci_dev, true); 293862306a36Sopenharmony_ci 293962306a36Sopenharmony_ci spin_unlock_irq(&dev->power.lock); 294062306a36Sopenharmony_ci} 294162306a36Sopenharmony_ci 294262306a36Sopenharmony_ci/** 294362306a36Sopenharmony_ci * pci_choose_state - Choose the power state of a PCI device. 294462306a36Sopenharmony_ci * @dev: Target PCI device. 294562306a36Sopenharmony_ci * @state: Target state for the whole system. 294662306a36Sopenharmony_ci * 294762306a36Sopenharmony_ci * Returns PCI power state suitable for @dev and @state. 294862306a36Sopenharmony_ci */ 294962306a36Sopenharmony_cipci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) 295062306a36Sopenharmony_ci{ 295162306a36Sopenharmony_ci if (state.event == PM_EVENT_ON) 295262306a36Sopenharmony_ci return PCI_D0; 295362306a36Sopenharmony_ci 295462306a36Sopenharmony_ci return pci_target_state(dev, false); 295562306a36Sopenharmony_ci} 295662306a36Sopenharmony_ciEXPORT_SYMBOL(pci_choose_state); 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_civoid pci_config_pm_runtime_get(struct pci_dev *pdev) 295962306a36Sopenharmony_ci{ 296062306a36Sopenharmony_ci struct device *dev = &pdev->dev; 296162306a36Sopenharmony_ci struct device *parent = dev->parent; 296262306a36Sopenharmony_ci 296362306a36Sopenharmony_ci if (parent) 296462306a36Sopenharmony_ci pm_runtime_get_sync(parent); 296562306a36Sopenharmony_ci pm_runtime_get_noresume(dev); 296662306a36Sopenharmony_ci /* 296762306a36Sopenharmony_ci * pdev->current_state is set to PCI_D3cold during suspending, 296862306a36Sopenharmony_ci * so wait until suspending completes 296962306a36Sopenharmony_ci */ 297062306a36Sopenharmony_ci pm_runtime_barrier(dev); 297162306a36Sopenharmony_ci /* 297262306a36Sopenharmony_ci * Only need to resume devices in D3cold, because config 297362306a36Sopenharmony_ci * registers are still accessible for devices suspended but 297462306a36Sopenharmony_ci * not in D3cold. 297562306a36Sopenharmony_ci */ 297662306a36Sopenharmony_ci if (pdev->current_state == PCI_D3cold) 297762306a36Sopenharmony_ci pm_runtime_resume(dev); 297862306a36Sopenharmony_ci} 297962306a36Sopenharmony_ci 298062306a36Sopenharmony_civoid pci_config_pm_runtime_put(struct pci_dev *pdev) 298162306a36Sopenharmony_ci{ 298262306a36Sopenharmony_ci struct device *dev = &pdev->dev; 298362306a36Sopenharmony_ci struct device *parent = dev->parent; 298462306a36Sopenharmony_ci 298562306a36Sopenharmony_ci pm_runtime_put(dev); 298662306a36Sopenharmony_ci if (parent) 298762306a36Sopenharmony_ci pm_runtime_put_sync(parent); 298862306a36Sopenharmony_ci} 298962306a36Sopenharmony_ci 299062306a36Sopenharmony_cistatic const struct dmi_system_id bridge_d3_blacklist[] = { 299162306a36Sopenharmony_ci#ifdef CONFIG_X86 299262306a36Sopenharmony_ci { 299362306a36Sopenharmony_ci /* 299462306a36Sopenharmony_ci * Gigabyte X299 root port is not marked as hotplug capable 299562306a36Sopenharmony_ci * which allows Linux to power manage it. However, this 299662306a36Sopenharmony_ci * confuses the BIOS SMI handler so don't power manage root 299762306a36Sopenharmony_ci * ports on that system. 299862306a36Sopenharmony_ci */ 299962306a36Sopenharmony_ci .ident = "X299 DESIGNARE EX-CF", 300062306a36Sopenharmony_ci .matches = { 300162306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), 300262306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "X299 DESIGNARE EX-CF"), 300362306a36Sopenharmony_ci }, 300462306a36Sopenharmony_ci }, 300562306a36Sopenharmony_ci { 300662306a36Sopenharmony_ci /* 300762306a36Sopenharmony_ci * Downstream device is not accessible after putting a root port 300862306a36Sopenharmony_ci * into D3cold and back into D0 on Elo Continental Z2 board 300962306a36Sopenharmony_ci */ 301062306a36Sopenharmony_ci .ident = "Elo Continental Z2", 301162306a36Sopenharmony_ci .matches = { 301262306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"), 301362306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_NAME, "Geminilake"), 301462306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"), 301562306a36Sopenharmony_ci }, 301662306a36Sopenharmony_ci }, 301762306a36Sopenharmony_ci#endif 301862306a36Sopenharmony_ci { } 301962306a36Sopenharmony_ci}; 302062306a36Sopenharmony_ci 302162306a36Sopenharmony_ci/** 302262306a36Sopenharmony_ci * pci_bridge_d3_possible - Is it possible to put the bridge into D3 302362306a36Sopenharmony_ci * @bridge: Bridge to check 302462306a36Sopenharmony_ci * 302562306a36Sopenharmony_ci * This function checks if it is possible to move the bridge to D3. 302662306a36Sopenharmony_ci * Currently we only allow D3 for recent enough PCIe ports and Thunderbolt. 302762306a36Sopenharmony_ci */ 302862306a36Sopenharmony_cibool pci_bridge_d3_possible(struct pci_dev *bridge) 302962306a36Sopenharmony_ci{ 303062306a36Sopenharmony_ci if (!pci_is_pcie(bridge)) 303162306a36Sopenharmony_ci return false; 303262306a36Sopenharmony_ci 303362306a36Sopenharmony_ci switch (pci_pcie_type(bridge)) { 303462306a36Sopenharmony_ci case PCI_EXP_TYPE_ROOT_PORT: 303562306a36Sopenharmony_ci case PCI_EXP_TYPE_UPSTREAM: 303662306a36Sopenharmony_ci case PCI_EXP_TYPE_DOWNSTREAM: 303762306a36Sopenharmony_ci if (pci_bridge_d3_disable) 303862306a36Sopenharmony_ci return false; 303962306a36Sopenharmony_ci 304062306a36Sopenharmony_ci /* 304162306a36Sopenharmony_ci * Hotplug ports handled by firmware in System Management Mode 304262306a36Sopenharmony_ci * may not be put into D3 by the OS (Thunderbolt on non-Macs). 304362306a36Sopenharmony_ci */ 304462306a36Sopenharmony_ci if (bridge->is_hotplug_bridge && !pciehp_is_native(bridge)) 304562306a36Sopenharmony_ci return false; 304662306a36Sopenharmony_ci 304762306a36Sopenharmony_ci if (pci_bridge_d3_force) 304862306a36Sopenharmony_ci return true; 304962306a36Sopenharmony_ci 305062306a36Sopenharmony_ci /* Even the oldest 2010 Thunderbolt controller supports D3. */ 305162306a36Sopenharmony_ci if (bridge->is_thunderbolt) 305262306a36Sopenharmony_ci return true; 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_ci /* Platform might know better if the bridge supports D3 */ 305562306a36Sopenharmony_ci if (platform_pci_bridge_d3(bridge)) 305662306a36Sopenharmony_ci return true; 305762306a36Sopenharmony_ci 305862306a36Sopenharmony_ci /* 305962306a36Sopenharmony_ci * Hotplug ports handled natively by the OS were not validated 306062306a36Sopenharmony_ci * by vendors for runtime D3 at least until 2018 because there 306162306a36Sopenharmony_ci * was no OS support. 306262306a36Sopenharmony_ci */ 306362306a36Sopenharmony_ci if (bridge->is_hotplug_bridge) 306462306a36Sopenharmony_ci return false; 306562306a36Sopenharmony_ci 306662306a36Sopenharmony_ci if (dmi_check_system(bridge_d3_blacklist)) 306762306a36Sopenharmony_ci return false; 306862306a36Sopenharmony_ci 306962306a36Sopenharmony_ci /* 307062306a36Sopenharmony_ci * It should be safe to put PCIe ports from 2015 or newer 307162306a36Sopenharmony_ci * to D3. 307262306a36Sopenharmony_ci */ 307362306a36Sopenharmony_ci if (dmi_get_bios_year() >= 2015) 307462306a36Sopenharmony_ci return true; 307562306a36Sopenharmony_ci break; 307662306a36Sopenharmony_ci } 307762306a36Sopenharmony_ci 307862306a36Sopenharmony_ci return false; 307962306a36Sopenharmony_ci} 308062306a36Sopenharmony_ci 308162306a36Sopenharmony_cistatic int pci_dev_check_d3cold(struct pci_dev *dev, void *data) 308262306a36Sopenharmony_ci{ 308362306a36Sopenharmony_ci bool *d3cold_ok = data; 308462306a36Sopenharmony_ci 308562306a36Sopenharmony_ci if (/* The device needs to be allowed to go D3cold ... */ 308662306a36Sopenharmony_ci dev->no_d3cold || !dev->d3cold_allowed || 308762306a36Sopenharmony_ci 308862306a36Sopenharmony_ci /* ... and if it is wakeup capable to do so from D3cold. */ 308962306a36Sopenharmony_ci (device_may_wakeup(&dev->dev) && 309062306a36Sopenharmony_ci !pci_pme_capable(dev, PCI_D3cold)) || 309162306a36Sopenharmony_ci 309262306a36Sopenharmony_ci /* If it is a bridge it must be allowed to go to D3. */ 309362306a36Sopenharmony_ci !pci_power_manageable(dev)) 309462306a36Sopenharmony_ci 309562306a36Sopenharmony_ci *d3cold_ok = false; 309662306a36Sopenharmony_ci 309762306a36Sopenharmony_ci return !*d3cold_ok; 309862306a36Sopenharmony_ci} 309962306a36Sopenharmony_ci 310062306a36Sopenharmony_ci/* 310162306a36Sopenharmony_ci * pci_bridge_d3_update - Update bridge D3 capabilities 310262306a36Sopenharmony_ci * @dev: PCI device which is changed 310362306a36Sopenharmony_ci * 310462306a36Sopenharmony_ci * Update upstream bridge PM capabilities accordingly depending on if the 310562306a36Sopenharmony_ci * device PM configuration was changed or the device is being removed. The 310662306a36Sopenharmony_ci * change is also propagated upstream. 310762306a36Sopenharmony_ci */ 310862306a36Sopenharmony_civoid pci_bridge_d3_update(struct pci_dev *dev) 310962306a36Sopenharmony_ci{ 311062306a36Sopenharmony_ci bool remove = !device_is_registered(&dev->dev); 311162306a36Sopenharmony_ci struct pci_dev *bridge; 311262306a36Sopenharmony_ci bool d3cold_ok = true; 311362306a36Sopenharmony_ci 311462306a36Sopenharmony_ci bridge = pci_upstream_bridge(dev); 311562306a36Sopenharmony_ci if (!bridge || !pci_bridge_d3_possible(bridge)) 311662306a36Sopenharmony_ci return; 311762306a36Sopenharmony_ci 311862306a36Sopenharmony_ci /* 311962306a36Sopenharmony_ci * If D3 is currently allowed for the bridge, removing one of its 312062306a36Sopenharmony_ci * children won't change that. 312162306a36Sopenharmony_ci */ 312262306a36Sopenharmony_ci if (remove && bridge->bridge_d3) 312362306a36Sopenharmony_ci return; 312462306a36Sopenharmony_ci 312562306a36Sopenharmony_ci /* 312662306a36Sopenharmony_ci * If D3 is currently allowed for the bridge and a child is added or 312762306a36Sopenharmony_ci * changed, disallowance of D3 can only be caused by that child, so 312862306a36Sopenharmony_ci * we only need to check that single device, not any of its siblings. 312962306a36Sopenharmony_ci * 313062306a36Sopenharmony_ci * If D3 is currently not allowed for the bridge, checking the device 313162306a36Sopenharmony_ci * first may allow us to skip checking its siblings. 313262306a36Sopenharmony_ci */ 313362306a36Sopenharmony_ci if (!remove) 313462306a36Sopenharmony_ci pci_dev_check_d3cold(dev, &d3cold_ok); 313562306a36Sopenharmony_ci 313662306a36Sopenharmony_ci /* 313762306a36Sopenharmony_ci * If D3 is currently not allowed for the bridge, this may be caused 313862306a36Sopenharmony_ci * either by the device being changed/removed or any of its siblings, 313962306a36Sopenharmony_ci * so we need to go through all children to find out if one of them 314062306a36Sopenharmony_ci * continues to block D3. 314162306a36Sopenharmony_ci */ 314262306a36Sopenharmony_ci if (d3cold_ok && !bridge->bridge_d3) 314362306a36Sopenharmony_ci pci_walk_bus(bridge->subordinate, pci_dev_check_d3cold, 314462306a36Sopenharmony_ci &d3cold_ok); 314562306a36Sopenharmony_ci 314662306a36Sopenharmony_ci if (bridge->bridge_d3 != d3cold_ok) { 314762306a36Sopenharmony_ci bridge->bridge_d3 = d3cold_ok; 314862306a36Sopenharmony_ci /* Propagate change to upstream bridges */ 314962306a36Sopenharmony_ci pci_bridge_d3_update(bridge); 315062306a36Sopenharmony_ci } 315162306a36Sopenharmony_ci} 315262306a36Sopenharmony_ci 315362306a36Sopenharmony_ci/** 315462306a36Sopenharmony_ci * pci_d3cold_enable - Enable D3cold for device 315562306a36Sopenharmony_ci * @dev: PCI device to handle 315662306a36Sopenharmony_ci * 315762306a36Sopenharmony_ci * This function can be used in drivers to enable D3cold from the device 315862306a36Sopenharmony_ci * they handle. It also updates upstream PCI bridge PM capabilities 315962306a36Sopenharmony_ci * accordingly. 316062306a36Sopenharmony_ci */ 316162306a36Sopenharmony_civoid pci_d3cold_enable(struct pci_dev *dev) 316262306a36Sopenharmony_ci{ 316362306a36Sopenharmony_ci if (dev->no_d3cold) { 316462306a36Sopenharmony_ci dev->no_d3cold = false; 316562306a36Sopenharmony_ci pci_bridge_d3_update(dev); 316662306a36Sopenharmony_ci } 316762306a36Sopenharmony_ci} 316862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_d3cold_enable); 316962306a36Sopenharmony_ci 317062306a36Sopenharmony_ci/** 317162306a36Sopenharmony_ci * pci_d3cold_disable - Disable D3cold for device 317262306a36Sopenharmony_ci * @dev: PCI device to handle 317362306a36Sopenharmony_ci * 317462306a36Sopenharmony_ci * This function can be used in drivers to disable D3cold from the device 317562306a36Sopenharmony_ci * they handle. It also updates upstream PCI bridge PM capabilities 317662306a36Sopenharmony_ci * accordingly. 317762306a36Sopenharmony_ci */ 317862306a36Sopenharmony_civoid pci_d3cold_disable(struct pci_dev *dev) 317962306a36Sopenharmony_ci{ 318062306a36Sopenharmony_ci if (!dev->no_d3cold) { 318162306a36Sopenharmony_ci dev->no_d3cold = true; 318262306a36Sopenharmony_ci pci_bridge_d3_update(dev); 318362306a36Sopenharmony_ci } 318462306a36Sopenharmony_ci} 318562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_d3cold_disable); 318662306a36Sopenharmony_ci 318762306a36Sopenharmony_ci/** 318862306a36Sopenharmony_ci * pci_pm_init - Initialize PM functions of given PCI device 318962306a36Sopenharmony_ci * @dev: PCI device to handle. 319062306a36Sopenharmony_ci */ 319162306a36Sopenharmony_civoid pci_pm_init(struct pci_dev *dev) 319262306a36Sopenharmony_ci{ 319362306a36Sopenharmony_ci int pm; 319462306a36Sopenharmony_ci u16 status; 319562306a36Sopenharmony_ci u16 pmc; 319662306a36Sopenharmony_ci 319762306a36Sopenharmony_ci pm_runtime_forbid(&dev->dev); 319862306a36Sopenharmony_ci pm_runtime_set_active(&dev->dev); 319962306a36Sopenharmony_ci pm_runtime_enable(&dev->dev); 320062306a36Sopenharmony_ci device_enable_async_suspend(&dev->dev); 320162306a36Sopenharmony_ci dev->wakeup_prepared = false; 320262306a36Sopenharmony_ci 320362306a36Sopenharmony_ci dev->pm_cap = 0; 320462306a36Sopenharmony_ci dev->pme_support = 0; 320562306a36Sopenharmony_ci 320662306a36Sopenharmony_ci /* find PCI PM capability in list */ 320762306a36Sopenharmony_ci pm = pci_find_capability(dev, PCI_CAP_ID_PM); 320862306a36Sopenharmony_ci if (!pm) 320962306a36Sopenharmony_ci return; 321062306a36Sopenharmony_ci /* Check device's ability to generate PME# */ 321162306a36Sopenharmony_ci pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc); 321262306a36Sopenharmony_ci 321362306a36Sopenharmony_ci if ((pmc & PCI_PM_CAP_VER_MASK) > 3) { 321462306a36Sopenharmony_ci pci_err(dev, "unsupported PM cap regs version (%u)\n", 321562306a36Sopenharmony_ci pmc & PCI_PM_CAP_VER_MASK); 321662306a36Sopenharmony_ci return; 321762306a36Sopenharmony_ci } 321862306a36Sopenharmony_ci 321962306a36Sopenharmony_ci dev->pm_cap = pm; 322062306a36Sopenharmony_ci dev->d3hot_delay = PCI_PM_D3HOT_WAIT; 322162306a36Sopenharmony_ci dev->d3cold_delay = PCI_PM_D3COLD_WAIT; 322262306a36Sopenharmony_ci dev->bridge_d3 = pci_bridge_d3_possible(dev); 322362306a36Sopenharmony_ci dev->d3cold_allowed = true; 322462306a36Sopenharmony_ci 322562306a36Sopenharmony_ci dev->d1_support = false; 322662306a36Sopenharmony_ci dev->d2_support = false; 322762306a36Sopenharmony_ci if (!pci_no_d1d2(dev)) { 322862306a36Sopenharmony_ci if (pmc & PCI_PM_CAP_D1) 322962306a36Sopenharmony_ci dev->d1_support = true; 323062306a36Sopenharmony_ci if (pmc & PCI_PM_CAP_D2) 323162306a36Sopenharmony_ci dev->d2_support = true; 323262306a36Sopenharmony_ci 323362306a36Sopenharmony_ci if (dev->d1_support || dev->d2_support) 323462306a36Sopenharmony_ci pci_info(dev, "supports%s%s\n", 323562306a36Sopenharmony_ci dev->d1_support ? " D1" : "", 323662306a36Sopenharmony_ci dev->d2_support ? " D2" : ""); 323762306a36Sopenharmony_ci } 323862306a36Sopenharmony_ci 323962306a36Sopenharmony_ci pmc &= PCI_PM_CAP_PME_MASK; 324062306a36Sopenharmony_ci if (pmc) { 324162306a36Sopenharmony_ci pci_info(dev, "PME# supported from%s%s%s%s%s\n", 324262306a36Sopenharmony_ci (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "", 324362306a36Sopenharmony_ci (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "", 324462306a36Sopenharmony_ci (pmc & PCI_PM_CAP_PME_D2) ? " D2" : "", 324562306a36Sopenharmony_ci (pmc & PCI_PM_CAP_PME_D3hot) ? " D3hot" : "", 324662306a36Sopenharmony_ci (pmc & PCI_PM_CAP_PME_D3cold) ? " D3cold" : ""); 324762306a36Sopenharmony_ci dev->pme_support = pmc >> PCI_PM_CAP_PME_SHIFT; 324862306a36Sopenharmony_ci dev->pme_poll = true; 324962306a36Sopenharmony_ci /* 325062306a36Sopenharmony_ci * Make device's PM flags reflect the wake-up capability, but 325162306a36Sopenharmony_ci * let the user space enable it to wake up the system as needed. 325262306a36Sopenharmony_ci */ 325362306a36Sopenharmony_ci device_set_wakeup_capable(&dev->dev, true); 325462306a36Sopenharmony_ci /* Disable the PME# generation functionality */ 325562306a36Sopenharmony_ci pci_pme_active(dev, false); 325662306a36Sopenharmony_ci } 325762306a36Sopenharmony_ci 325862306a36Sopenharmony_ci pci_read_config_word(dev, PCI_STATUS, &status); 325962306a36Sopenharmony_ci if (status & PCI_STATUS_IMM_READY) 326062306a36Sopenharmony_ci dev->imm_ready = 1; 326162306a36Sopenharmony_ci} 326262306a36Sopenharmony_ci 326362306a36Sopenharmony_cistatic unsigned long pci_ea_flags(struct pci_dev *dev, u8 prop) 326462306a36Sopenharmony_ci{ 326562306a36Sopenharmony_ci unsigned long flags = IORESOURCE_PCI_FIXED | IORESOURCE_PCI_EA_BEI; 326662306a36Sopenharmony_ci 326762306a36Sopenharmony_ci switch (prop) { 326862306a36Sopenharmony_ci case PCI_EA_P_MEM: 326962306a36Sopenharmony_ci case PCI_EA_P_VF_MEM: 327062306a36Sopenharmony_ci flags |= IORESOURCE_MEM; 327162306a36Sopenharmony_ci break; 327262306a36Sopenharmony_ci case PCI_EA_P_MEM_PREFETCH: 327362306a36Sopenharmony_ci case PCI_EA_P_VF_MEM_PREFETCH: 327462306a36Sopenharmony_ci flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; 327562306a36Sopenharmony_ci break; 327662306a36Sopenharmony_ci case PCI_EA_P_IO: 327762306a36Sopenharmony_ci flags |= IORESOURCE_IO; 327862306a36Sopenharmony_ci break; 327962306a36Sopenharmony_ci default: 328062306a36Sopenharmony_ci return 0; 328162306a36Sopenharmony_ci } 328262306a36Sopenharmony_ci 328362306a36Sopenharmony_ci return flags; 328462306a36Sopenharmony_ci} 328562306a36Sopenharmony_ci 328662306a36Sopenharmony_cistatic struct resource *pci_ea_get_resource(struct pci_dev *dev, u8 bei, 328762306a36Sopenharmony_ci u8 prop) 328862306a36Sopenharmony_ci{ 328962306a36Sopenharmony_ci if (bei <= PCI_EA_BEI_BAR5 && prop <= PCI_EA_P_IO) 329062306a36Sopenharmony_ci return &dev->resource[bei]; 329162306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 329262306a36Sopenharmony_ci else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5 && 329362306a36Sopenharmony_ci (prop == PCI_EA_P_VF_MEM || prop == PCI_EA_P_VF_MEM_PREFETCH)) 329462306a36Sopenharmony_ci return &dev->resource[PCI_IOV_RESOURCES + 329562306a36Sopenharmony_ci bei - PCI_EA_BEI_VF_BAR0]; 329662306a36Sopenharmony_ci#endif 329762306a36Sopenharmony_ci else if (bei == PCI_EA_BEI_ROM) 329862306a36Sopenharmony_ci return &dev->resource[PCI_ROM_RESOURCE]; 329962306a36Sopenharmony_ci else 330062306a36Sopenharmony_ci return NULL; 330162306a36Sopenharmony_ci} 330262306a36Sopenharmony_ci 330362306a36Sopenharmony_ci/* Read an Enhanced Allocation (EA) entry */ 330462306a36Sopenharmony_cistatic int pci_ea_read(struct pci_dev *dev, int offset) 330562306a36Sopenharmony_ci{ 330662306a36Sopenharmony_ci struct resource *res; 330762306a36Sopenharmony_ci int ent_size, ent_offset = offset; 330862306a36Sopenharmony_ci resource_size_t start, end; 330962306a36Sopenharmony_ci unsigned long flags; 331062306a36Sopenharmony_ci u32 dw0, bei, base, max_offset; 331162306a36Sopenharmony_ci u8 prop; 331262306a36Sopenharmony_ci bool support_64 = (sizeof(resource_size_t) >= 8); 331362306a36Sopenharmony_ci 331462306a36Sopenharmony_ci pci_read_config_dword(dev, ent_offset, &dw0); 331562306a36Sopenharmony_ci ent_offset += 4; 331662306a36Sopenharmony_ci 331762306a36Sopenharmony_ci /* Entry size field indicates DWORDs after 1st */ 331862306a36Sopenharmony_ci ent_size = ((dw0 & PCI_EA_ES) + 1) << 2; 331962306a36Sopenharmony_ci 332062306a36Sopenharmony_ci if (!(dw0 & PCI_EA_ENABLE)) /* Entry not enabled */ 332162306a36Sopenharmony_ci goto out; 332262306a36Sopenharmony_ci 332362306a36Sopenharmony_ci bei = (dw0 & PCI_EA_BEI) >> 4; 332462306a36Sopenharmony_ci prop = (dw0 & PCI_EA_PP) >> 8; 332562306a36Sopenharmony_ci 332662306a36Sopenharmony_ci /* 332762306a36Sopenharmony_ci * If the Property is in the reserved range, try the Secondary 332862306a36Sopenharmony_ci * Property instead. 332962306a36Sopenharmony_ci */ 333062306a36Sopenharmony_ci if (prop > PCI_EA_P_BRIDGE_IO && prop < PCI_EA_P_MEM_RESERVED) 333162306a36Sopenharmony_ci prop = (dw0 & PCI_EA_SP) >> 16; 333262306a36Sopenharmony_ci if (prop > PCI_EA_P_BRIDGE_IO) 333362306a36Sopenharmony_ci goto out; 333462306a36Sopenharmony_ci 333562306a36Sopenharmony_ci res = pci_ea_get_resource(dev, bei, prop); 333662306a36Sopenharmony_ci if (!res) { 333762306a36Sopenharmony_ci pci_err(dev, "Unsupported EA entry BEI: %u\n", bei); 333862306a36Sopenharmony_ci goto out; 333962306a36Sopenharmony_ci } 334062306a36Sopenharmony_ci 334162306a36Sopenharmony_ci flags = pci_ea_flags(dev, prop); 334262306a36Sopenharmony_ci if (!flags) { 334362306a36Sopenharmony_ci pci_err(dev, "Unsupported EA properties: %#x\n", prop); 334462306a36Sopenharmony_ci goto out; 334562306a36Sopenharmony_ci } 334662306a36Sopenharmony_ci 334762306a36Sopenharmony_ci /* Read Base */ 334862306a36Sopenharmony_ci pci_read_config_dword(dev, ent_offset, &base); 334962306a36Sopenharmony_ci start = (base & PCI_EA_FIELD_MASK); 335062306a36Sopenharmony_ci ent_offset += 4; 335162306a36Sopenharmony_ci 335262306a36Sopenharmony_ci /* Read MaxOffset */ 335362306a36Sopenharmony_ci pci_read_config_dword(dev, ent_offset, &max_offset); 335462306a36Sopenharmony_ci ent_offset += 4; 335562306a36Sopenharmony_ci 335662306a36Sopenharmony_ci /* Read Base MSBs (if 64-bit entry) */ 335762306a36Sopenharmony_ci if (base & PCI_EA_IS_64) { 335862306a36Sopenharmony_ci u32 base_upper; 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_ci pci_read_config_dword(dev, ent_offset, &base_upper); 336162306a36Sopenharmony_ci ent_offset += 4; 336262306a36Sopenharmony_ci 336362306a36Sopenharmony_ci flags |= IORESOURCE_MEM_64; 336462306a36Sopenharmony_ci 336562306a36Sopenharmony_ci /* entry starts above 32-bit boundary, can't use */ 336662306a36Sopenharmony_ci if (!support_64 && base_upper) 336762306a36Sopenharmony_ci goto out; 336862306a36Sopenharmony_ci 336962306a36Sopenharmony_ci if (support_64) 337062306a36Sopenharmony_ci start |= ((u64)base_upper << 32); 337162306a36Sopenharmony_ci } 337262306a36Sopenharmony_ci 337362306a36Sopenharmony_ci end = start + (max_offset | 0x03); 337462306a36Sopenharmony_ci 337562306a36Sopenharmony_ci /* Read MaxOffset MSBs (if 64-bit entry) */ 337662306a36Sopenharmony_ci if (max_offset & PCI_EA_IS_64) { 337762306a36Sopenharmony_ci u32 max_offset_upper; 337862306a36Sopenharmony_ci 337962306a36Sopenharmony_ci pci_read_config_dword(dev, ent_offset, &max_offset_upper); 338062306a36Sopenharmony_ci ent_offset += 4; 338162306a36Sopenharmony_ci 338262306a36Sopenharmony_ci flags |= IORESOURCE_MEM_64; 338362306a36Sopenharmony_ci 338462306a36Sopenharmony_ci /* entry too big, can't use */ 338562306a36Sopenharmony_ci if (!support_64 && max_offset_upper) 338662306a36Sopenharmony_ci goto out; 338762306a36Sopenharmony_ci 338862306a36Sopenharmony_ci if (support_64) 338962306a36Sopenharmony_ci end += ((u64)max_offset_upper << 32); 339062306a36Sopenharmony_ci } 339162306a36Sopenharmony_ci 339262306a36Sopenharmony_ci if (end < start) { 339362306a36Sopenharmony_ci pci_err(dev, "EA Entry crosses address boundary\n"); 339462306a36Sopenharmony_ci goto out; 339562306a36Sopenharmony_ci } 339662306a36Sopenharmony_ci 339762306a36Sopenharmony_ci if (ent_size != ent_offset - offset) { 339862306a36Sopenharmony_ci pci_err(dev, "EA Entry Size (%d) does not match length read (%d)\n", 339962306a36Sopenharmony_ci ent_size, ent_offset - offset); 340062306a36Sopenharmony_ci goto out; 340162306a36Sopenharmony_ci } 340262306a36Sopenharmony_ci 340362306a36Sopenharmony_ci res->name = pci_name(dev); 340462306a36Sopenharmony_ci res->start = start; 340562306a36Sopenharmony_ci res->end = end; 340662306a36Sopenharmony_ci res->flags = flags; 340762306a36Sopenharmony_ci 340862306a36Sopenharmony_ci if (bei <= PCI_EA_BEI_BAR5) 340962306a36Sopenharmony_ci pci_info(dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n", 341062306a36Sopenharmony_ci bei, res, prop); 341162306a36Sopenharmony_ci else if (bei == PCI_EA_BEI_ROM) 341262306a36Sopenharmony_ci pci_info(dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n", 341362306a36Sopenharmony_ci res, prop); 341462306a36Sopenharmony_ci else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5) 341562306a36Sopenharmony_ci pci_info(dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n", 341662306a36Sopenharmony_ci bei - PCI_EA_BEI_VF_BAR0, res, prop); 341762306a36Sopenharmony_ci else 341862306a36Sopenharmony_ci pci_info(dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n", 341962306a36Sopenharmony_ci bei, res, prop); 342062306a36Sopenharmony_ci 342162306a36Sopenharmony_ciout: 342262306a36Sopenharmony_ci return offset + ent_size; 342362306a36Sopenharmony_ci} 342462306a36Sopenharmony_ci 342562306a36Sopenharmony_ci/* Enhanced Allocation Initialization */ 342662306a36Sopenharmony_civoid pci_ea_init(struct pci_dev *dev) 342762306a36Sopenharmony_ci{ 342862306a36Sopenharmony_ci int ea; 342962306a36Sopenharmony_ci u8 num_ent; 343062306a36Sopenharmony_ci int offset; 343162306a36Sopenharmony_ci int i; 343262306a36Sopenharmony_ci 343362306a36Sopenharmony_ci /* find PCI EA capability in list */ 343462306a36Sopenharmony_ci ea = pci_find_capability(dev, PCI_CAP_ID_EA); 343562306a36Sopenharmony_ci if (!ea) 343662306a36Sopenharmony_ci return; 343762306a36Sopenharmony_ci 343862306a36Sopenharmony_ci /* determine the number of entries */ 343962306a36Sopenharmony_ci pci_bus_read_config_byte(dev->bus, dev->devfn, ea + PCI_EA_NUM_ENT, 344062306a36Sopenharmony_ci &num_ent); 344162306a36Sopenharmony_ci num_ent &= PCI_EA_NUM_ENT_MASK; 344262306a36Sopenharmony_ci 344362306a36Sopenharmony_ci offset = ea + PCI_EA_FIRST_ENT; 344462306a36Sopenharmony_ci 344562306a36Sopenharmony_ci /* Skip DWORD 2 for type 1 functions */ 344662306a36Sopenharmony_ci if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) 344762306a36Sopenharmony_ci offset += 4; 344862306a36Sopenharmony_ci 344962306a36Sopenharmony_ci /* parse each EA entry */ 345062306a36Sopenharmony_ci for (i = 0; i < num_ent; ++i) 345162306a36Sopenharmony_ci offset = pci_ea_read(dev, offset); 345262306a36Sopenharmony_ci} 345362306a36Sopenharmony_ci 345462306a36Sopenharmony_cistatic void pci_add_saved_cap(struct pci_dev *pci_dev, 345562306a36Sopenharmony_ci struct pci_cap_saved_state *new_cap) 345662306a36Sopenharmony_ci{ 345762306a36Sopenharmony_ci hlist_add_head(&new_cap->next, &pci_dev->saved_cap_space); 345862306a36Sopenharmony_ci} 345962306a36Sopenharmony_ci 346062306a36Sopenharmony_ci/** 346162306a36Sopenharmony_ci * _pci_add_cap_save_buffer - allocate buffer for saving given 346262306a36Sopenharmony_ci * capability registers 346362306a36Sopenharmony_ci * @dev: the PCI device 346462306a36Sopenharmony_ci * @cap: the capability to allocate the buffer for 346562306a36Sopenharmony_ci * @extended: Standard or Extended capability ID 346662306a36Sopenharmony_ci * @size: requested size of the buffer 346762306a36Sopenharmony_ci */ 346862306a36Sopenharmony_cistatic int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap, 346962306a36Sopenharmony_ci bool extended, unsigned int size) 347062306a36Sopenharmony_ci{ 347162306a36Sopenharmony_ci int pos; 347262306a36Sopenharmony_ci struct pci_cap_saved_state *save_state; 347362306a36Sopenharmony_ci 347462306a36Sopenharmony_ci if (extended) 347562306a36Sopenharmony_ci pos = pci_find_ext_capability(dev, cap); 347662306a36Sopenharmony_ci else 347762306a36Sopenharmony_ci pos = pci_find_capability(dev, cap); 347862306a36Sopenharmony_ci 347962306a36Sopenharmony_ci if (!pos) 348062306a36Sopenharmony_ci return 0; 348162306a36Sopenharmony_ci 348262306a36Sopenharmony_ci save_state = kzalloc(sizeof(*save_state) + size, GFP_KERNEL); 348362306a36Sopenharmony_ci if (!save_state) 348462306a36Sopenharmony_ci return -ENOMEM; 348562306a36Sopenharmony_ci 348662306a36Sopenharmony_ci save_state->cap.cap_nr = cap; 348762306a36Sopenharmony_ci save_state->cap.cap_extended = extended; 348862306a36Sopenharmony_ci save_state->cap.size = size; 348962306a36Sopenharmony_ci pci_add_saved_cap(dev, save_state); 349062306a36Sopenharmony_ci 349162306a36Sopenharmony_ci return 0; 349262306a36Sopenharmony_ci} 349362306a36Sopenharmony_ci 349462306a36Sopenharmony_ciint pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size) 349562306a36Sopenharmony_ci{ 349662306a36Sopenharmony_ci return _pci_add_cap_save_buffer(dev, cap, false, size); 349762306a36Sopenharmony_ci} 349862306a36Sopenharmony_ci 349962306a36Sopenharmony_ciint pci_add_ext_cap_save_buffer(struct pci_dev *dev, u16 cap, unsigned int size) 350062306a36Sopenharmony_ci{ 350162306a36Sopenharmony_ci return _pci_add_cap_save_buffer(dev, cap, true, size); 350262306a36Sopenharmony_ci} 350362306a36Sopenharmony_ci 350462306a36Sopenharmony_ci/** 350562306a36Sopenharmony_ci * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities 350662306a36Sopenharmony_ci * @dev: the PCI device 350762306a36Sopenharmony_ci */ 350862306a36Sopenharmony_civoid pci_allocate_cap_save_buffers(struct pci_dev *dev) 350962306a36Sopenharmony_ci{ 351062306a36Sopenharmony_ci int error; 351162306a36Sopenharmony_ci 351262306a36Sopenharmony_ci error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP, 351362306a36Sopenharmony_ci PCI_EXP_SAVE_REGS * sizeof(u16)); 351462306a36Sopenharmony_ci if (error) 351562306a36Sopenharmony_ci pci_err(dev, "unable to preallocate PCI Express save buffer\n"); 351662306a36Sopenharmony_ci 351762306a36Sopenharmony_ci error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_PCIX, sizeof(u16)); 351862306a36Sopenharmony_ci if (error) 351962306a36Sopenharmony_ci pci_err(dev, "unable to preallocate PCI-X save buffer\n"); 352062306a36Sopenharmony_ci 352162306a36Sopenharmony_ci error = pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_LTR, 352262306a36Sopenharmony_ci 2 * sizeof(u16)); 352362306a36Sopenharmony_ci if (error) 352462306a36Sopenharmony_ci pci_err(dev, "unable to allocate suspend buffer for LTR\n"); 352562306a36Sopenharmony_ci 352662306a36Sopenharmony_ci pci_allocate_vc_save_buffers(dev); 352762306a36Sopenharmony_ci} 352862306a36Sopenharmony_ci 352962306a36Sopenharmony_civoid pci_free_cap_save_buffers(struct pci_dev *dev) 353062306a36Sopenharmony_ci{ 353162306a36Sopenharmony_ci struct pci_cap_saved_state *tmp; 353262306a36Sopenharmony_ci struct hlist_node *n; 353362306a36Sopenharmony_ci 353462306a36Sopenharmony_ci hlist_for_each_entry_safe(tmp, n, &dev->saved_cap_space, next) 353562306a36Sopenharmony_ci kfree(tmp); 353662306a36Sopenharmony_ci} 353762306a36Sopenharmony_ci 353862306a36Sopenharmony_ci/** 353962306a36Sopenharmony_ci * pci_configure_ari - enable or disable ARI forwarding 354062306a36Sopenharmony_ci * @dev: the PCI device 354162306a36Sopenharmony_ci * 354262306a36Sopenharmony_ci * If @dev and its upstream bridge both support ARI, enable ARI in the 354362306a36Sopenharmony_ci * bridge. Otherwise, disable ARI in the bridge. 354462306a36Sopenharmony_ci */ 354562306a36Sopenharmony_civoid pci_configure_ari(struct pci_dev *dev) 354662306a36Sopenharmony_ci{ 354762306a36Sopenharmony_ci u32 cap; 354862306a36Sopenharmony_ci struct pci_dev *bridge; 354962306a36Sopenharmony_ci 355062306a36Sopenharmony_ci if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) 355162306a36Sopenharmony_ci return; 355262306a36Sopenharmony_ci 355362306a36Sopenharmony_ci bridge = dev->bus->self; 355462306a36Sopenharmony_ci if (!bridge) 355562306a36Sopenharmony_ci return; 355662306a36Sopenharmony_ci 355762306a36Sopenharmony_ci pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap); 355862306a36Sopenharmony_ci if (!(cap & PCI_EXP_DEVCAP2_ARI)) 355962306a36Sopenharmony_ci return; 356062306a36Sopenharmony_ci 356162306a36Sopenharmony_ci if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) { 356262306a36Sopenharmony_ci pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, 356362306a36Sopenharmony_ci PCI_EXP_DEVCTL2_ARI); 356462306a36Sopenharmony_ci bridge->ari_enabled = 1; 356562306a36Sopenharmony_ci } else { 356662306a36Sopenharmony_ci pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2, 356762306a36Sopenharmony_ci PCI_EXP_DEVCTL2_ARI); 356862306a36Sopenharmony_ci bridge->ari_enabled = 0; 356962306a36Sopenharmony_ci } 357062306a36Sopenharmony_ci} 357162306a36Sopenharmony_ci 357262306a36Sopenharmony_cistatic bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) 357362306a36Sopenharmony_ci{ 357462306a36Sopenharmony_ci int pos; 357562306a36Sopenharmony_ci u16 cap, ctrl; 357662306a36Sopenharmony_ci 357762306a36Sopenharmony_ci pos = pdev->acs_cap; 357862306a36Sopenharmony_ci if (!pos) 357962306a36Sopenharmony_ci return false; 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_ci /* 358262306a36Sopenharmony_ci * Except for egress control, capabilities are either required 358362306a36Sopenharmony_ci * or only required if controllable. Features missing from the 358462306a36Sopenharmony_ci * capability field can therefore be assumed as hard-wired enabled. 358562306a36Sopenharmony_ci */ 358662306a36Sopenharmony_ci pci_read_config_word(pdev, pos + PCI_ACS_CAP, &cap); 358762306a36Sopenharmony_ci acs_flags &= (cap | PCI_ACS_EC); 358862306a36Sopenharmony_ci 358962306a36Sopenharmony_ci pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); 359062306a36Sopenharmony_ci return (ctrl & acs_flags) == acs_flags; 359162306a36Sopenharmony_ci} 359262306a36Sopenharmony_ci 359362306a36Sopenharmony_ci/** 359462306a36Sopenharmony_ci * pci_acs_enabled - test ACS against required flags for a given device 359562306a36Sopenharmony_ci * @pdev: device to test 359662306a36Sopenharmony_ci * @acs_flags: required PCI ACS flags 359762306a36Sopenharmony_ci * 359862306a36Sopenharmony_ci * Return true if the device supports the provided flags. Automatically 359962306a36Sopenharmony_ci * filters out flags that are not implemented on multifunction devices. 360062306a36Sopenharmony_ci * 360162306a36Sopenharmony_ci * Note that this interface checks the effective ACS capabilities of the 360262306a36Sopenharmony_ci * device rather than the actual capabilities. For instance, most single 360362306a36Sopenharmony_ci * function endpoints are not required to support ACS because they have no 360462306a36Sopenharmony_ci * opportunity for peer-to-peer access. We therefore return 'true' 360562306a36Sopenharmony_ci * regardless of whether the device exposes an ACS capability. This makes 360662306a36Sopenharmony_ci * it much easier for callers of this function to ignore the actual type 360762306a36Sopenharmony_ci * or topology of the device when testing ACS support. 360862306a36Sopenharmony_ci */ 360962306a36Sopenharmony_cibool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags) 361062306a36Sopenharmony_ci{ 361162306a36Sopenharmony_ci int ret; 361262306a36Sopenharmony_ci 361362306a36Sopenharmony_ci ret = pci_dev_specific_acs_enabled(pdev, acs_flags); 361462306a36Sopenharmony_ci if (ret >= 0) 361562306a36Sopenharmony_ci return ret > 0; 361662306a36Sopenharmony_ci 361762306a36Sopenharmony_ci /* 361862306a36Sopenharmony_ci * Conventional PCI and PCI-X devices never support ACS, either 361962306a36Sopenharmony_ci * effectively or actually. The shared bus topology implies that 362062306a36Sopenharmony_ci * any device on the bus can receive or snoop DMA. 362162306a36Sopenharmony_ci */ 362262306a36Sopenharmony_ci if (!pci_is_pcie(pdev)) 362362306a36Sopenharmony_ci return false; 362462306a36Sopenharmony_ci 362562306a36Sopenharmony_ci switch (pci_pcie_type(pdev)) { 362662306a36Sopenharmony_ci /* 362762306a36Sopenharmony_ci * PCI/X-to-PCIe bridges are not specifically mentioned by the spec, 362862306a36Sopenharmony_ci * but since their primary interface is PCI/X, we conservatively 362962306a36Sopenharmony_ci * handle them as we would a non-PCIe device. 363062306a36Sopenharmony_ci */ 363162306a36Sopenharmony_ci case PCI_EXP_TYPE_PCIE_BRIDGE: 363262306a36Sopenharmony_ci /* 363362306a36Sopenharmony_ci * PCIe 3.0, 6.12.1 excludes ACS on these devices. "ACS is never 363462306a36Sopenharmony_ci * applicable... must never implement an ACS Extended Capability...". 363562306a36Sopenharmony_ci * This seems arbitrary, but we take a conservative interpretation 363662306a36Sopenharmony_ci * of this statement. 363762306a36Sopenharmony_ci */ 363862306a36Sopenharmony_ci case PCI_EXP_TYPE_PCI_BRIDGE: 363962306a36Sopenharmony_ci case PCI_EXP_TYPE_RC_EC: 364062306a36Sopenharmony_ci return false; 364162306a36Sopenharmony_ci /* 364262306a36Sopenharmony_ci * PCIe 3.0, 6.12.1.1 specifies that downstream and root ports should 364362306a36Sopenharmony_ci * implement ACS in order to indicate their peer-to-peer capabilities, 364462306a36Sopenharmony_ci * regardless of whether they are single- or multi-function devices. 364562306a36Sopenharmony_ci */ 364662306a36Sopenharmony_ci case PCI_EXP_TYPE_DOWNSTREAM: 364762306a36Sopenharmony_ci case PCI_EXP_TYPE_ROOT_PORT: 364862306a36Sopenharmony_ci return pci_acs_flags_enabled(pdev, acs_flags); 364962306a36Sopenharmony_ci /* 365062306a36Sopenharmony_ci * PCIe 3.0, 6.12.1.2 specifies ACS capabilities that should be 365162306a36Sopenharmony_ci * implemented by the remaining PCIe types to indicate peer-to-peer 365262306a36Sopenharmony_ci * capabilities, but only when they are part of a multifunction 365362306a36Sopenharmony_ci * device. The footnote for section 6.12 indicates the specific 365462306a36Sopenharmony_ci * PCIe types included here. 365562306a36Sopenharmony_ci */ 365662306a36Sopenharmony_ci case PCI_EXP_TYPE_ENDPOINT: 365762306a36Sopenharmony_ci case PCI_EXP_TYPE_UPSTREAM: 365862306a36Sopenharmony_ci case PCI_EXP_TYPE_LEG_END: 365962306a36Sopenharmony_ci case PCI_EXP_TYPE_RC_END: 366062306a36Sopenharmony_ci if (!pdev->multifunction) 366162306a36Sopenharmony_ci break; 366262306a36Sopenharmony_ci 366362306a36Sopenharmony_ci return pci_acs_flags_enabled(pdev, acs_flags); 366462306a36Sopenharmony_ci } 366562306a36Sopenharmony_ci 366662306a36Sopenharmony_ci /* 366762306a36Sopenharmony_ci * PCIe 3.0, 6.12.1.3 specifies no ACS capabilities are applicable 366862306a36Sopenharmony_ci * to single function devices with the exception of downstream ports. 366962306a36Sopenharmony_ci */ 367062306a36Sopenharmony_ci return true; 367162306a36Sopenharmony_ci} 367262306a36Sopenharmony_ci 367362306a36Sopenharmony_ci/** 367462306a36Sopenharmony_ci * pci_acs_path_enabled - test ACS flags from start to end in a hierarchy 367562306a36Sopenharmony_ci * @start: starting downstream device 367662306a36Sopenharmony_ci * @end: ending upstream device or NULL to search to the root bus 367762306a36Sopenharmony_ci * @acs_flags: required flags 367862306a36Sopenharmony_ci * 367962306a36Sopenharmony_ci * Walk up a device tree from start to end testing PCI ACS support. If 368062306a36Sopenharmony_ci * any step along the way does not support the required flags, return false. 368162306a36Sopenharmony_ci */ 368262306a36Sopenharmony_cibool pci_acs_path_enabled(struct pci_dev *start, 368362306a36Sopenharmony_ci struct pci_dev *end, u16 acs_flags) 368462306a36Sopenharmony_ci{ 368562306a36Sopenharmony_ci struct pci_dev *pdev, *parent = start; 368662306a36Sopenharmony_ci 368762306a36Sopenharmony_ci do { 368862306a36Sopenharmony_ci pdev = parent; 368962306a36Sopenharmony_ci 369062306a36Sopenharmony_ci if (!pci_acs_enabled(pdev, acs_flags)) 369162306a36Sopenharmony_ci return false; 369262306a36Sopenharmony_ci 369362306a36Sopenharmony_ci if (pci_is_root_bus(pdev->bus)) 369462306a36Sopenharmony_ci return (end == NULL); 369562306a36Sopenharmony_ci 369662306a36Sopenharmony_ci parent = pdev->bus->self; 369762306a36Sopenharmony_ci } while (pdev != end); 369862306a36Sopenharmony_ci 369962306a36Sopenharmony_ci return true; 370062306a36Sopenharmony_ci} 370162306a36Sopenharmony_ci 370262306a36Sopenharmony_ci/** 370362306a36Sopenharmony_ci * pci_acs_init - Initialize ACS if hardware supports it 370462306a36Sopenharmony_ci * @dev: the PCI device 370562306a36Sopenharmony_ci */ 370662306a36Sopenharmony_civoid pci_acs_init(struct pci_dev *dev) 370762306a36Sopenharmony_ci{ 370862306a36Sopenharmony_ci dev->acs_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); 370962306a36Sopenharmony_ci 371062306a36Sopenharmony_ci /* 371162306a36Sopenharmony_ci * Attempt to enable ACS regardless of capability because some Root 371262306a36Sopenharmony_ci * Ports (e.g. those quirked with *_intel_pch_acs_*) do not have 371362306a36Sopenharmony_ci * the standard ACS capability but still support ACS via those 371462306a36Sopenharmony_ci * quirks. 371562306a36Sopenharmony_ci */ 371662306a36Sopenharmony_ci pci_enable_acs(dev); 371762306a36Sopenharmony_ci} 371862306a36Sopenharmony_ci 371962306a36Sopenharmony_ci/** 372062306a36Sopenharmony_ci * pci_rebar_find_pos - find position of resize ctrl reg for BAR 372162306a36Sopenharmony_ci * @pdev: PCI device 372262306a36Sopenharmony_ci * @bar: BAR to find 372362306a36Sopenharmony_ci * 372462306a36Sopenharmony_ci * Helper to find the position of the ctrl register for a BAR. 372562306a36Sopenharmony_ci * Returns -ENOTSUPP if resizable BARs are not supported at all. 372662306a36Sopenharmony_ci * Returns -ENOENT if no ctrl register for the BAR could be found. 372762306a36Sopenharmony_ci */ 372862306a36Sopenharmony_cistatic int pci_rebar_find_pos(struct pci_dev *pdev, int bar) 372962306a36Sopenharmony_ci{ 373062306a36Sopenharmony_ci unsigned int pos, nbars, i; 373162306a36Sopenharmony_ci u32 ctrl; 373262306a36Sopenharmony_ci 373362306a36Sopenharmony_ci pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_REBAR); 373462306a36Sopenharmony_ci if (!pos) 373562306a36Sopenharmony_ci return -ENOTSUPP; 373662306a36Sopenharmony_ci 373762306a36Sopenharmony_ci pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); 373862306a36Sopenharmony_ci nbars = (ctrl & PCI_REBAR_CTRL_NBAR_MASK) >> 373962306a36Sopenharmony_ci PCI_REBAR_CTRL_NBAR_SHIFT; 374062306a36Sopenharmony_ci 374162306a36Sopenharmony_ci for (i = 0; i < nbars; i++, pos += 8) { 374262306a36Sopenharmony_ci int bar_idx; 374362306a36Sopenharmony_ci 374462306a36Sopenharmony_ci pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); 374562306a36Sopenharmony_ci bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; 374662306a36Sopenharmony_ci if (bar_idx == bar) 374762306a36Sopenharmony_ci return pos; 374862306a36Sopenharmony_ci } 374962306a36Sopenharmony_ci 375062306a36Sopenharmony_ci return -ENOENT; 375162306a36Sopenharmony_ci} 375262306a36Sopenharmony_ci 375362306a36Sopenharmony_ci/** 375462306a36Sopenharmony_ci * pci_rebar_get_possible_sizes - get possible sizes for BAR 375562306a36Sopenharmony_ci * @pdev: PCI device 375662306a36Sopenharmony_ci * @bar: BAR to query 375762306a36Sopenharmony_ci * 375862306a36Sopenharmony_ci * Get the possible sizes of a resizable BAR as bitmask defined in the spec 375962306a36Sopenharmony_ci * (bit 0=1MB, bit 19=512GB). Returns 0 if BAR isn't resizable. 376062306a36Sopenharmony_ci */ 376162306a36Sopenharmony_ciu32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar) 376262306a36Sopenharmony_ci{ 376362306a36Sopenharmony_ci int pos; 376462306a36Sopenharmony_ci u32 cap; 376562306a36Sopenharmony_ci 376662306a36Sopenharmony_ci pos = pci_rebar_find_pos(pdev, bar); 376762306a36Sopenharmony_ci if (pos < 0) 376862306a36Sopenharmony_ci return 0; 376962306a36Sopenharmony_ci 377062306a36Sopenharmony_ci pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap); 377162306a36Sopenharmony_ci cap = FIELD_GET(PCI_REBAR_CAP_SIZES, cap); 377262306a36Sopenharmony_ci 377362306a36Sopenharmony_ci /* Sapphire RX 5600 XT Pulse has an invalid cap dword for BAR 0 */ 377462306a36Sopenharmony_ci if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x731f && 377562306a36Sopenharmony_ci bar == 0 && cap == 0x700) 377662306a36Sopenharmony_ci return 0x3f00; 377762306a36Sopenharmony_ci 377862306a36Sopenharmony_ci return cap; 377962306a36Sopenharmony_ci} 378062306a36Sopenharmony_ciEXPORT_SYMBOL(pci_rebar_get_possible_sizes); 378162306a36Sopenharmony_ci 378262306a36Sopenharmony_ci/** 378362306a36Sopenharmony_ci * pci_rebar_get_current_size - get the current size of a BAR 378462306a36Sopenharmony_ci * @pdev: PCI device 378562306a36Sopenharmony_ci * @bar: BAR to set size to 378662306a36Sopenharmony_ci * 378762306a36Sopenharmony_ci * Read the size of a BAR from the resizable BAR config. 378862306a36Sopenharmony_ci * Returns size if found or negative error code. 378962306a36Sopenharmony_ci */ 379062306a36Sopenharmony_ciint pci_rebar_get_current_size(struct pci_dev *pdev, int bar) 379162306a36Sopenharmony_ci{ 379262306a36Sopenharmony_ci int pos; 379362306a36Sopenharmony_ci u32 ctrl; 379462306a36Sopenharmony_ci 379562306a36Sopenharmony_ci pos = pci_rebar_find_pos(pdev, bar); 379662306a36Sopenharmony_ci if (pos < 0) 379762306a36Sopenharmony_ci return pos; 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); 380062306a36Sopenharmony_ci return (ctrl & PCI_REBAR_CTRL_BAR_SIZE) >> PCI_REBAR_CTRL_BAR_SHIFT; 380162306a36Sopenharmony_ci} 380262306a36Sopenharmony_ci 380362306a36Sopenharmony_ci/** 380462306a36Sopenharmony_ci * pci_rebar_set_size - set a new size for a BAR 380562306a36Sopenharmony_ci * @pdev: PCI device 380662306a36Sopenharmony_ci * @bar: BAR to set size to 380762306a36Sopenharmony_ci * @size: new size as defined in the spec (0=1MB, 19=512GB) 380862306a36Sopenharmony_ci * 380962306a36Sopenharmony_ci * Set the new size of a BAR as defined in the spec. 381062306a36Sopenharmony_ci * Returns zero if resizing was successful, error code otherwise. 381162306a36Sopenharmony_ci */ 381262306a36Sopenharmony_ciint pci_rebar_set_size(struct pci_dev *pdev, int bar, int size) 381362306a36Sopenharmony_ci{ 381462306a36Sopenharmony_ci int pos; 381562306a36Sopenharmony_ci u32 ctrl; 381662306a36Sopenharmony_ci 381762306a36Sopenharmony_ci pos = pci_rebar_find_pos(pdev, bar); 381862306a36Sopenharmony_ci if (pos < 0) 381962306a36Sopenharmony_ci return pos; 382062306a36Sopenharmony_ci 382162306a36Sopenharmony_ci pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); 382262306a36Sopenharmony_ci ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; 382362306a36Sopenharmony_ci ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT; 382462306a36Sopenharmony_ci pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); 382562306a36Sopenharmony_ci return 0; 382662306a36Sopenharmony_ci} 382762306a36Sopenharmony_ci 382862306a36Sopenharmony_ci/** 382962306a36Sopenharmony_ci * pci_enable_atomic_ops_to_root - enable AtomicOp requests to root port 383062306a36Sopenharmony_ci * @dev: the PCI device 383162306a36Sopenharmony_ci * @cap_mask: mask of desired AtomicOp sizes, including one or more of: 383262306a36Sopenharmony_ci * PCI_EXP_DEVCAP2_ATOMIC_COMP32 383362306a36Sopenharmony_ci * PCI_EXP_DEVCAP2_ATOMIC_COMP64 383462306a36Sopenharmony_ci * PCI_EXP_DEVCAP2_ATOMIC_COMP128 383562306a36Sopenharmony_ci * 383662306a36Sopenharmony_ci * Return 0 if all upstream bridges support AtomicOp routing, egress 383762306a36Sopenharmony_ci * blocking is disabled on all upstream ports, and the root port supports 383862306a36Sopenharmony_ci * the requested completion capabilities (32-bit, 64-bit and/or 128-bit 383962306a36Sopenharmony_ci * AtomicOp completion), or negative otherwise. 384062306a36Sopenharmony_ci */ 384162306a36Sopenharmony_ciint pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask) 384262306a36Sopenharmony_ci{ 384362306a36Sopenharmony_ci struct pci_bus *bus = dev->bus; 384462306a36Sopenharmony_ci struct pci_dev *bridge; 384562306a36Sopenharmony_ci u32 cap, ctl2; 384662306a36Sopenharmony_ci 384762306a36Sopenharmony_ci /* 384862306a36Sopenharmony_ci * Per PCIe r5.0, sec 9.3.5.10, the AtomicOp Requester Enable bit 384962306a36Sopenharmony_ci * in Device Control 2 is reserved in VFs and the PF value applies 385062306a36Sopenharmony_ci * to all associated VFs. 385162306a36Sopenharmony_ci */ 385262306a36Sopenharmony_ci if (dev->is_virtfn) 385362306a36Sopenharmony_ci return -EINVAL; 385462306a36Sopenharmony_ci 385562306a36Sopenharmony_ci if (!pci_is_pcie(dev)) 385662306a36Sopenharmony_ci return -EINVAL; 385762306a36Sopenharmony_ci 385862306a36Sopenharmony_ci /* 385962306a36Sopenharmony_ci * Per PCIe r4.0, sec 6.15, endpoints and root ports may be 386062306a36Sopenharmony_ci * AtomicOp requesters. For now, we only support endpoints as 386162306a36Sopenharmony_ci * requesters and root ports as completers. No endpoints as 386262306a36Sopenharmony_ci * completers, and no peer-to-peer. 386362306a36Sopenharmony_ci */ 386462306a36Sopenharmony_ci 386562306a36Sopenharmony_ci switch (pci_pcie_type(dev)) { 386662306a36Sopenharmony_ci case PCI_EXP_TYPE_ENDPOINT: 386762306a36Sopenharmony_ci case PCI_EXP_TYPE_LEG_END: 386862306a36Sopenharmony_ci case PCI_EXP_TYPE_RC_END: 386962306a36Sopenharmony_ci break; 387062306a36Sopenharmony_ci default: 387162306a36Sopenharmony_ci return -EINVAL; 387262306a36Sopenharmony_ci } 387362306a36Sopenharmony_ci 387462306a36Sopenharmony_ci while (bus->parent) { 387562306a36Sopenharmony_ci bridge = bus->self; 387662306a36Sopenharmony_ci 387762306a36Sopenharmony_ci pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap); 387862306a36Sopenharmony_ci 387962306a36Sopenharmony_ci switch (pci_pcie_type(bridge)) { 388062306a36Sopenharmony_ci /* Ensure switch ports support AtomicOp routing */ 388162306a36Sopenharmony_ci case PCI_EXP_TYPE_UPSTREAM: 388262306a36Sopenharmony_ci case PCI_EXP_TYPE_DOWNSTREAM: 388362306a36Sopenharmony_ci if (!(cap & PCI_EXP_DEVCAP2_ATOMIC_ROUTE)) 388462306a36Sopenharmony_ci return -EINVAL; 388562306a36Sopenharmony_ci break; 388662306a36Sopenharmony_ci 388762306a36Sopenharmony_ci /* Ensure root port supports all the sizes we care about */ 388862306a36Sopenharmony_ci case PCI_EXP_TYPE_ROOT_PORT: 388962306a36Sopenharmony_ci if ((cap & cap_mask) != cap_mask) 389062306a36Sopenharmony_ci return -EINVAL; 389162306a36Sopenharmony_ci break; 389262306a36Sopenharmony_ci } 389362306a36Sopenharmony_ci 389462306a36Sopenharmony_ci /* Ensure upstream ports don't block AtomicOps on egress */ 389562306a36Sopenharmony_ci if (pci_pcie_type(bridge) == PCI_EXP_TYPE_UPSTREAM) { 389662306a36Sopenharmony_ci pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, 389762306a36Sopenharmony_ci &ctl2); 389862306a36Sopenharmony_ci if (ctl2 & PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK) 389962306a36Sopenharmony_ci return -EINVAL; 390062306a36Sopenharmony_ci } 390162306a36Sopenharmony_ci 390262306a36Sopenharmony_ci bus = bus->parent; 390362306a36Sopenharmony_ci } 390462306a36Sopenharmony_ci 390562306a36Sopenharmony_ci pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, 390662306a36Sopenharmony_ci PCI_EXP_DEVCTL2_ATOMIC_REQ); 390762306a36Sopenharmony_ci return 0; 390862306a36Sopenharmony_ci} 390962306a36Sopenharmony_ciEXPORT_SYMBOL(pci_enable_atomic_ops_to_root); 391062306a36Sopenharmony_ci 391162306a36Sopenharmony_ci/** 391262306a36Sopenharmony_ci * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge 391362306a36Sopenharmony_ci * @dev: the PCI device 391462306a36Sopenharmony_ci * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD) 391562306a36Sopenharmony_ci * 391662306a36Sopenharmony_ci * Perform INTx swizzling for a device behind one level of bridge. This is 391762306a36Sopenharmony_ci * required by section 9.1 of the PCI-to-PCI bridge specification for devices 391862306a36Sopenharmony_ci * behind bridges on add-in cards. For devices with ARI enabled, the slot 391962306a36Sopenharmony_ci * number is always 0 (see the Implementation Note in section 2.2.8.1 of 392062306a36Sopenharmony_ci * the PCI Express Base Specification, Revision 2.1) 392162306a36Sopenharmony_ci */ 392262306a36Sopenharmony_ciu8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin) 392362306a36Sopenharmony_ci{ 392462306a36Sopenharmony_ci int slot; 392562306a36Sopenharmony_ci 392662306a36Sopenharmony_ci if (pci_ari_enabled(dev->bus)) 392762306a36Sopenharmony_ci slot = 0; 392862306a36Sopenharmony_ci else 392962306a36Sopenharmony_ci slot = PCI_SLOT(dev->devfn); 393062306a36Sopenharmony_ci 393162306a36Sopenharmony_ci return (((pin - 1) + slot) % 4) + 1; 393262306a36Sopenharmony_ci} 393362306a36Sopenharmony_ci 393462306a36Sopenharmony_ciint pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) 393562306a36Sopenharmony_ci{ 393662306a36Sopenharmony_ci u8 pin; 393762306a36Sopenharmony_ci 393862306a36Sopenharmony_ci pin = dev->pin; 393962306a36Sopenharmony_ci if (!pin) 394062306a36Sopenharmony_ci return -1; 394162306a36Sopenharmony_ci 394262306a36Sopenharmony_ci while (!pci_is_root_bus(dev->bus)) { 394362306a36Sopenharmony_ci pin = pci_swizzle_interrupt_pin(dev, pin); 394462306a36Sopenharmony_ci dev = dev->bus->self; 394562306a36Sopenharmony_ci } 394662306a36Sopenharmony_ci *bridge = dev; 394762306a36Sopenharmony_ci return pin; 394862306a36Sopenharmony_ci} 394962306a36Sopenharmony_ci 395062306a36Sopenharmony_ci/** 395162306a36Sopenharmony_ci * pci_common_swizzle - swizzle INTx all the way to root bridge 395262306a36Sopenharmony_ci * @dev: the PCI device 395362306a36Sopenharmony_ci * @pinp: pointer to the INTx pin value (1=INTA, 2=INTB, 3=INTD, 4=INTD) 395462306a36Sopenharmony_ci * 395562306a36Sopenharmony_ci * Perform INTx swizzling for a device. This traverses through all PCI-to-PCI 395662306a36Sopenharmony_ci * bridges all the way up to a PCI root bus. 395762306a36Sopenharmony_ci */ 395862306a36Sopenharmony_ciu8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp) 395962306a36Sopenharmony_ci{ 396062306a36Sopenharmony_ci u8 pin = *pinp; 396162306a36Sopenharmony_ci 396262306a36Sopenharmony_ci while (!pci_is_root_bus(dev->bus)) { 396362306a36Sopenharmony_ci pin = pci_swizzle_interrupt_pin(dev, pin); 396462306a36Sopenharmony_ci dev = dev->bus->self; 396562306a36Sopenharmony_ci } 396662306a36Sopenharmony_ci *pinp = pin; 396762306a36Sopenharmony_ci return PCI_SLOT(dev->devfn); 396862306a36Sopenharmony_ci} 396962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_common_swizzle); 397062306a36Sopenharmony_ci 397162306a36Sopenharmony_ci/** 397262306a36Sopenharmony_ci * pci_release_region - Release a PCI bar 397362306a36Sopenharmony_ci * @pdev: PCI device whose resources were previously reserved by 397462306a36Sopenharmony_ci * pci_request_region() 397562306a36Sopenharmony_ci * @bar: BAR to release 397662306a36Sopenharmony_ci * 397762306a36Sopenharmony_ci * Releases the PCI I/O and memory resources previously reserved by a 397862306a36Sopenharmony_ci * successful call to pci_request_region(). Call this function only 397962306a36Sopenharmony_ci * after all use of the PCI regions has ceased. 398062306a36Sopenharmony_ci */ 398162306a36Sopenharmony_civoid pci_release_region(struct pci_dev *pdev, int bar) 398262306a36Sopenharmony_ci{ 398362306a36Sopenharmony_ci struct pci_devres *dr; 398462306a36Sopenharmony_ci 398562306a36Sopenharmony_ci if (pci_resource_len(pdev, bar) == 0) 398662306a36Sopenharmony_ci return; 398762306a36Sopenharmony_ci if (pci_resource_flags(pdev, bar) & IORESOURCE_IO) 398862306a36Sopenharmony_ci release_region(pci_resource_start(pdev, bar), 398962306a36Sopenharmony_ci pci_resource_len(pdev, bar)); 399062306a36Sopenharmony_ci else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) 399162306a36Sopenharmony_ci release_mem_region(pci_resource_start(pdev, bar), 399262306a36Sopenharmony_ci pci_resource_len(pdev, bar)); 399362306a36Sopenharmony_ci 399462306a36Sopenharmony_ci dr = find_pci_dr(pdev); 399562306a36Sopenharmony_ci if (dr) 399662306a36Sopenharmony_ci dr->region_mask &= ~(1 << bar); 399762306a36Sopenharmony_ci} 399862306a36Sopenharmony_ciEXPORT_SYMBOL(pci_release_region); 399962306a36Sopenharmony_ci 400062306a36Sopenharmony_ci/** 400162306a36Sopenharmony_ci * __pci_request_region - Reserved PCI I/O and memory resource 400262306a36Sopenharmony_ci * @pdev: PCI device whose resources are to be reserved 400362306a36Sopenharmony_ci * @bar: BAR to be reserved 400462306a36Sopenharmony_ci * @res_name: Name to be associated with resource. 400562306a36Sopenharmony_ci * @exclusive: whether the region access is exclusive or not 400662306a36Sopenharmony_ci * 400762306a36Sopenharmony_ci * Mark the PCI region associated with PCI device @pdev BAR @bar as 400862306a36Sopenharmony_ci * being reserved by owner @res_name. Do not access any 400962306a36Sopenharmony_ci * address inside the PCI regions unless this call returns 401062306a36Sopenharmony_ci * successfully. 401162306a36Sopenharmony_ci * 401262306a36Sopenharmony_ci * If @exclusive is set, then the region is marked so that userspace 401362306a36Sopenharmony_ci * is explicitly not allowed to map the resource via /dev/mem or 401462306a36Sopenharmony_ci * sysfs MMIO access. 401562306a36Sopenharmony_ci * 401662306a36Sopenharmony_ci * Returns 0 on success, or %EBUSY on error. A warning 401762306a36Sopenharmony_ci * message is also printed on failure. 401862306a36Sopenharmony_ci */ 401962306a36Sopenharmony_cistatic int __pci_request_region(struct pci_dev *pdev, int bar, 402062306a36Sopenharmony_ci const char *res_name, int exclusive) 402162306a36Sopenharmony_ci{ 402262306a36Sopenharmony_ci struct pci_devres *dr; 402362306a36Sopenharmony_ci 402462306a36Sopenharmony_ci if (pci_resource_len(pdev, bar) == 0) 402562306a36Sopenharmony_ci return 0; 402662306a36Sopenharmony_ci 402762306a36Sopenharmony_ci if (pci_resource_flags(pdev, bar) & IORESOURCE_IO) { 402862306a36Sopenharmony_ci if (!request_region(pci_resource_start(pdev, bar), 402962306a36Sopenharmony_ci pci_resource_len(pdev, bar), res_name)) 403062306a36Sopenharmony_ci goto err_out; 403162306a36Sopenharmony_ci } else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { 403262306a36Sopenharmony_ci if (!__request_mem_region(pci_resource_start(pdev, bar), 403362306a36Sopenharmony_ci pci_resource_len(pdev, bar), res_name, 403462306a36Sopenharmony_ci exclusive)) 403562306a36Sopenharmony_ci goto err_out; 403662306a36Sopenharmony_ci } 403762306a36Sopenharmony_ci 403862306a36Sopenharmony_ci dr = find_pci_dr(pdev); 403962306a36Sopenharmony_ci if (dr) 404062306a36Sopenharmony_ci dr->region_mask |= 1 << bar; 404162306a36Sopenharmony_ci 404262306a36Sopenharmony_ci return 0; 404362306a36Sopenharmony_ci 404462306a36Sopenharmony_cierr_out: 404562306a36Sopenharmony_ci pci_warn(pdev, "BAR %d: can't reserve %pR\n", bar, 404662306a36Sopenharmony_ci &pdev->resource[bar]); 404762306a36Sopenharmony_ci return -EBUSY; 404862306a36Sopenharmony_ci} 404962306a36Sopenharmony_ci 405062306a36Sopenharmony_ci/** 405162306a36Sopenharmony_ci * pci_request_region - Reserve PCI I/O and memory resource 405262306a36Sopenharmony_ci * @pdev: PCI device whose resources are to be reserved 405362306a36Sopenharmony_ci * @bar: BAR to be reserved 405462306a36Sopenharmony_ci * @res_name: Name to be associated with resource 405562306a36Sopenharmony_ci * 405662306a36Sopenharmony_ci * Mark the PCI region associated with PCI device @pdev BAR @bar as 405762306a36Sopenharmony_ci * being reserved by owner @res_name. Do not access any 405862306a36Sopenharmony_ci * address inside the PCI regions unless this call returns 405962306a36Sopenharmony_ci * successfully. 406062306a36Sopenharmony_ci * 406162306a36Sopenharmony_ci * Returns 0 on success, or %EBUSY on error. A warning 406262306a36Sopenharmony_ci * message is also printed on failure. 406362306a36Sopenharmony_ci */ 406462306a36Sopenharmony_ciint pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) 406562306a36Sopenharmony_ci{ 406662306a36Sopenharmony_ci return __pci_request_region(pdev, bar, res_name, 0); 406762306a36Sopenharmony_ci} 406862306a36Sopenharmony_ciEXPORT_SYMBOL(pci_request_region); 406962306a36Sopenharmony_ci 407062306a36Sopenharmony_ci/** 407162306a36Sopenharmony_ci * pci_release_selected_regions - Release selected PCI I/O and memory resources 407262306a36Sopenharmony_ci * @pdev: PCI device whose resources were previously reserved 407362306a36Sopenharmony_ci * @bars: Bitmask of BARs to be released 407462306a36Sopenharmony_ci * 407562306a36Sopenharmony_ci * Release selected PCI I/O and memory resources previously reserved. 407662306a36Sopenharmony_ci * Call this function only after all use of the PCI regions has ceased. 407762306a36Sopenharmony_ci */ 407862306a36Sopenharmony_civoid pci_release_selected_regions(struct pci_dev *pdev, int bars) 407962306a36Sopenharmony_ci{ 408062306a36Sopenharmony_ci int i; 408162306a36Sopenharmony_ci 408262306a36Sopenharmony_ci for (i = 0; i < PCI_STD_NUM_BARS; i++) 408362306a36Sopenharmony_ci if (bars & (1 << i)) 408462306a36Sopenharmony_ci pci_release_region(pdev, i); 408562306a36Sopenharmony_ci} 408662306a36Sopenharmony_ciEXPORT_SYMBOL(pci_release_selected_regions); 408762306a36Sopenharmony_ci 408862306a36Sopenharmony_cistatic int __pci_request_selected_regions(struct pci_dev *pdev, int bars, 408962306a36Sopenharmony_ci const char *res_name, int excl) 409062306a36Sopenharmony_ci{ 409162306a36Sopenharmony_ci int i; 409262306a36Sopenharmony_ci 409362306a36Sopenharmony_ci for (i = 0; i < PCI_STD_NUM_BARS; i++) 409462306a36Sopenharmony_ci if (bars & (1 << i)) 409562306a36Sopenharmony_ci if (__pci_request_region(pdev, i, res_name, excl)) 409662306a36Sopenharmony_ci goto err_out; 409762306a36Sopenharmony_ci return 0; 409862306a36Sopenharmony_ci 409962306a36Sopenharmony_cierr_out: 410062306a36Sopenharmony_ci while (--i >= 0) 410162306a36Sopenharmony_ci if (bars & (1 << i)) 410262306a36Sopenharmony_ci pci_release_region(pdev, i); 410362306a36Sopenharmony_ci 410462306a36Sopenharmony_ci return -EBUSY; 410562306a36Sopenharmony_ci} 410662306a36Sopenharmony_ci 410762306a36Sopenharmony_ci 410862306a36Sopenharmony_ci/** 410962306a36Sopenharmony_ci * pci_request_selected_regions - Reserve selected PCI I/O and memory resources 411062306a36Sopenharmony_ci * @pdev: PCI device whose resources are to be reserved 411162306a36Sopenharmony_ci * @bars: Bitmask of BARs to be requested 411262306a36Sopenharmony_ci * @res_name: Name to be associated with resource 411362306a36Sopenharmony_ci */ 411462306a36Sopenharmony_ciint pci_request_selected_regions(struct pci_dev *pdev, int bars, 411562306a36Sopenharmony_ci const char *res_name) 411662306a36Sopenharmony_ci{ 411762306a36Sopenharmony_ci return __pci_request_selected_regions(pdev, bars, res_name, 0); 411862306a36Sopenharmony_ci} 411962306a36Sopenharmony_ciEXPORT_SYMBOL(pci_request_selected_regions); 412062306a36Sopenharmony_ci 412162306a36Sopenharmony_ciint pci_request_selected_regions_exclusive(struct pci_dev *pdev, int bars, 412262306a36Sopenharmony_ci const char *res_name) 412362306a36Sopenharmony_ci{ 412462306a36Sopenharmony_ci return __pci_request_selected_regions(pdev, bars, res_name, 412562306a36Sopenharmony_ci IORESOURCE_EXCLUSIVE); 412662306a36Sopenharmony_ci} 412762306a36Sopenharmony_ciEXPORT_SYMBOL(pci_request_selected_regions_exclusive); 412862306a36Sopenharmony_ci 412962306a36Sopenharmony_ci/** 413062306a36Sopenharmony_ci * pci_release_regions - Release reserved PCI I/O and memory resources 413162306a36Sopenharmony_ci * @pdev: PCI device whose resources were previously reserved by 413262306a36Sopenharmony_ci * pci_request_regions() 413362306a36Sopenharmony_ci * 413462306a36Sopenharmony_ci * Releases all PCI I/O and memory resources previously reserved by a 413562306a36Sopenharmony_ci * successful call to pci_request_regions(). Call this function only 413662306a36Sopenharmony_ci * after all use of the PCI regions has ceased. 413762306a36Sopenharmony_ci */ 413862306a36Sopenharmony_ci 413962306a36Sopenharmony_civoid pci_release_regions(struct pci_dev *pdev) 414062306a36Sopenharmony_ci{ 414162306a36Sopenharmony_ci pci_release_selected_regions(pdev, (1 << PCI_STD_NUM_BARS) - 1); 414262306a36Sopenharmony_ci} 414362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_release_regions); 414462306a36Sopenharmony_ci 414562306a36Sopenharmony_ci/** 414662306a36Sopenharmony_ci * pci_request_regions - Reserve PCI I/O and memory resources 414762306a36Sopenharmony_ci * @pdev: PCI device whose resources are to be reserved 414862306a36Sopenharmony_ci * @res_name: Name to be associated with resource. 414962306a36Sopenharmony_ci * 415062306a36Sopenharmony_ci * Mark all PCI regions associated with PCI device @pdev as 415162306a36Sopenharmony_ci * being reserved by owner @res_name. Do not access any 415262306a36Sopenharmony_ci * address inside the PCI regions unless this call returns 415362306a36Sopenharmony_ci * successfully. 415462306a36Sopenharmony_ci * 415562306a36Sopenharmony_ci * Returns 0 on success, or %EBUSY on error. A warning 415662306a36Sopenharmony_ci * message is also printed on failure. 415762306a36Sopenharmony_ci */ 415862306a36Sopenharmony_ciint pci_request_regions(struct pci_dev *pdev, const char *res_name) 415962306a36Sopenharmony_ci{ 416062306a36Sopenharmony_ci return pci_request_selected_regions(pdev, 416162306a36Sopenharmony_ci ((1 << PCI_STD_NUM_BARS) - 1), res_name); 416262306a36Sopenharmony_ci} 416362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_request_regions); 416462306a36Sopenharmony_ci 416562306a36Sopenharmony_ci/** 416662306a36Sopenharmony_ci * pci_request_regions_exclusive - Reserve PCI I/O and memory resources 416762306a36Sopenharmony_ci * @pdev: PCI device whose resources are to be reserved 416862306a36Sopenharmony_ci * @res_name: Name to be associated with resource. 416962306a36Sopenharmony_ci * 417062306a36Sopenharmony_ci * Mark all PCI regions associated with PCI device @pdev as being reserved 417162306a36Sopenharmony_ci * by owner @res_name. Do not access any address inside the PCI regions 417262306a36Sopenharmony_ci * unless this call returns successfully. 417362306a36Sopenharmony_ci * 417462306a36Sopenharmony_ci * pci_request_regions_exclusive() will mark the region so that /dev/mem 417562306a36Sopenharmony_ci * and the sysfs MMIO access will not be allowed. 417662306a36Sopenharmony_ci * 417762306a36Sopenharmony_ci * Returns 0 on success, or %EBUSY on error. A warning message is also 417862306a36Sopenharmony_ci * printed on failure. 417962306a36Sopenharmony_ci */ 418062306a36Sopenharmony_ciint pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name) 418162306a36Sopenharmony_ci{ 418262306a36Sopenharmony_ci return pci_request_selected_regions_exclusive(pdev, 418362306a36Sopenharmony_ci ((1 << PCI_STD_NUM_BARS) - 1), res_name); 418462306a36Sopenharmony_ci} 418562306a36Sopenharmony_ciEXPORT_SYMBOL(pci_request_regions_exclusive); 418662306a36Sopenharmony_ci 418762306a36Sopenharmony_ci/* 418862306a36Sopenharmony_ci * Record the PCI IO range (expressed as CPU physical address + size). 418962306a36Sopenharmony_ci * Return a negative value if an error has occurred, zero otherwise 419062306a36Sopenharmony_ci */ 419162306a36Sopenharmony_ciint pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr, 419262306a36Sopenharmony_ci resource_size_t size) 419362306a36Sopenharmony_ci{ 419462306a36Sopenharmony_ci int ret = 0; 419562306a36Sopenharmony_ci#ifdef PCI_IOBASE 419662306a36Sopenharmony_ci struct logic_pio_hwaddr *range; 419762306a36Sopenharmony_ci 419862306a36Sopenharmony_ci if (!size || addr + size < addr) 419962306a36Sopenharmony_ci return -EINVAL; 420062306a36Sopenharmony_ci 420162306a36Sopenharmony_ci range = kzalloc(sizeof(*range), GFP_ATOMIC); 420262306a36Sopenharmony_ci if (!range) 420362306a36Sopenharmony_ci return -ENOMEM; 420462306a36Sopenharmony_ci 420562306a36Sopenharmony_ci range->fwnode = fwnode; 420662306a36Sopenharmony_ci range->size = size; 420762306a36Sopenharmony_ci range->hw_start = addr; 420862306a36Sopenharmony_ci range->flags = LOGIC_PIO_CPU_MMIO; 420962306a36Sopenharmony_ci 421062306a36Sopenharmony_ci ret = logic_pio_register_range(range); 421162306a36Sopenharmony_ci if (ret) 421262306a36Sopenharmony_ci kfree(range); 421362306a36Sopenharmony_ci 421462306a36Sopenharmony_ci /* Ignore duplicates due to deferred probing */ 421562306a36Sopenharmony_ci if (ret == -EEXIST) 421662306a36Sopenharmony_ci ret = 0; 421762306a36Sopenharmony_ci#endif 421862306a36Sopenharmony_ci 421962306a36Sopenharmony_ci return ret; 422062306a36Sopenharmony_ci} 422162306a36Sopenharmony_ci 422262306a36Sopenharmony_ciphys_addr_t pci_pio_to_address(unsigned long pio) 422362306a36Sopenharmony_ci{ 422462306a36Sopenharmony_ci#ifdef PCI_IOBASE 422562306a36Sopenharmony_ci if (pio < MMIO_UPPER_LIMIT) 422662306a36Sopenharmony_ci return logic_pio_to_hwaddr(pio); 422762306a36Sopenharmony_ci#endif 422862306a36Sopenharmony_ci 422962306a36Sopenharmony_ci return (phys_addr_t) OF_BAD_ADDR; 423062306a36Sopenharmony_ci} 423162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_pio_to_address); 423262306a36Sopenharmony_ci 423362306a36Sopenharmony_ciunsigned long __weak pci_address_to_pio(phys_addr_t address) 423462306a36Sopenharmony_ci{ 423562306a36Sopenharmony_ci#ifdef PCI_IOBASE 423662306a36Sopenharmony_ci return logic_pio_trans_cpuaddr(address); 423762306a36Sopenharmony_ci#else 423862306a36Sopenharmony_ci if (address > IO_SPACE_LIMIT) 423962306a36Sopenharmony_ci return (unsigned long)-1; 424062306a36Sopenharmony_ci 424162306a36Sopenharmony_ci return (unsigned long) address; 424262306a36Sopenharmony_ci#endif 424362306a36Sopenharmony_ci} 424462306a36Sopenharmony_ci 424562306a36Sopenharmony_ci/** 424662306a36Sopenharmony_ci * pci_remap_iospace - Remap the memory mapped I/O space 424762306a36Sopenharmony_ci * @res: Resource describing the I/O space 424862306a36Sopenharmony_ci * @phys_addr: physical address of range to be mapped 424962306a36Sopenharmony_ci * 425062306a36Sopenharmony_ci * Remap the memory mapped I/O space described by the @res and the CPU 425162306a36Sopenharmony_ci * physical address @phys_addr into virtual address space. Only 425262306a36Sopenharmony_ci * architectures that have memory mapped IO functions defined (and the 425362306a36Sopenharmony_ci * PCI_IOBASE value defined) should call this function. 425462306a36Sopenharmony_ci */ 425562306a36Sopenharmony_ci#ifndef pci_remap_iospace 425662306a36Sopenharmony_ciint pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr) 425762306a36Sopenharmony_ci{ 425862306a36Sopenharmony_ci#if defined(PCI_IOBASE) && defined(CONFIG_MMU) 425962306a36Sopenharmony_ci unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start; 426062306a36Sopenharmony_ci 426162306a36Sopenharmony_ci if (!(res->flags & IORESOURCE_IO)) 426262306a36Sopenharmony_ci return -EINVAL; 426362306a36Sopenharmony_ci 426462306a36Sopenharmony_ci if (res->end > IO_SPACE_LIMIT) 426562306a36Sopenharmony_ci return -EINVAL; 426662306a36Sopenharmony_ci 426762306a36Sopenharmony_ci return ioremap_page_range(vaddr, vaddr + resource_size(res), phys_addr, 426862306a36Sopenharmony_ci pgprot_device(PAGE_KERNEL)); 426962306a36Sopenharmony_ci#else 427062306a36Sopenharmony_ci /* 427162306a36Sopenharmony_ci * This architecture does not have memory mapped I/O space, 427262306a36Sopenharmony_ci * so this function should never be called 427362306a36Sopenharmony_ci */ 427462306a36Sopenharmony_ci WARN_ONCE(1, "This architecture does not support memory mapped I/O\n"); 427562306a36Sopenharmony_ci return -ENODEV; 427662306a36Sopenharmony_ci#endif 427762306a36Sopenharmony_ci} 427862306a36Sopenharmony_ciEXPORT_SYMBOL(pci_remap_iospace); 427962306a36Sopenharmony_ci#endif 428062306a36Sopenharmony_ci 428162306a36Sopenharmony_ci/** 428262306a36Sopenharmony_ci * pci_unmap_iospace - Unmap the memory mapped I/O space 428362306a36Sopenharmony_ci * @res: resource to be unmapped 428462306a36Sopenharmony_ci * 428562306a36Sopenharmony_ci * Unmap the CPU virtual address @res from virtual address space. Only 428662306a36Sopenharmony_ci * architectures that have memory mapped IO functions defined (and the 428762306a36Sopenharmony_ci * PCI_IOBASE value defined) should call this function. 428862306a36Sopenharmony_ci */ 428962306a36Sopenharmony_civoid pci_unmap_iospace(struct resource *res) 429062306a36Sopenharmony_ci{ 429162306a36Sopenharmony_ci#if defined(PCI_IOBASE) && defined(CONFIG_MMU) 429262306a36Sopenharmony_ci unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start; 429362306a36Sopenharmony_ci 429462306a36Sopenharmony_ci vunmap_range(vaddr, vaddr + resource_size(res)); 429562306a36Sopenharmony_ci#endif 429662306a36Sopenharmony_ci} 429762306a36Sopenharmony_ciEXPORT_SYMBOL(pci_unmap_iospace); 429862306a36Sopenharmony_ci 429962306a36Sopenharmony_cistatic void devm_pci_unmap_iospace(struct device *dev, void *ptr) 430062306a36Sopenharmony_ci{ 430162306a36Sopenharmony_ci struct resource **res = ptr; 430262306a36Sopenharmony_ci 430362306a36Sopenharmony_ci pci_unmap_iospace(*res); 430462306a36Sopenharmony_ci} 430562306a36Sopenharmony_ci 430662306a36Sopenharmony_ci/** 430762306a36Sopenharmony_ci * devm_pci_remap_iospace - Managed pci_remap_iospace() 430862306a36Sopenharmony_ci * @dev: Generic device to remap IO address for 430962306a36Sopenharmony_ci * @res: Resource describing the I/O space 431062306a36Sopenharmony_ci * @phys_addr: physical address of range to be mapped 431162306a36Sopenharmony_ci * 431262306a36Sopenharmony_ci * Managed pci_remap_iospace(). Map is automatically unmapped on driver 431362306a36Sopenharmony_ci * detach. 431462306a36Sopenharmony_ci */ 431562306a36Sopenharmony_ciint devm_pci_remap_iospace(struct device *dev, const struct resource *res, 431662306a36Sopenharmony_ci phys_addr_t phys_addr) 431762306a36Sopenharmony_ci{ 431862306a36Sopenharmony_ci const struct resource **ptr; 431962306a36Sopenharmony_ci int error; 432062306a36Sopenharmony_ci 432162306a36Sopenharmony_ci ptr = devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL); 432262306a36Sopenharmony_ci if (!ptr) 432362306a36Sopenharmony_ci return -ENOMEM; 432462306a36Sopenharmony_ci 432562306a36Sopenharmony_ci error = pci_remap_iospace(res, phys_addr); 432662306a36Sopenharmony_ci if (error) { 432762306a36Sopenharmony_ci devres_free(ptr); 432862306a36Sopenharmony_ci } else { 432962306a36Sopenharmony_ci *ptr = res; 433062306a36Sopenharmony_ci devres_add(dev, ptr); 433162306a36Sopenharmony_ci } 433262306a36Sopenharmony_ci 433362306a36Sopenharmony_ci return error; 433462306a36Sopenharmony_ci} 433562306a36Sopenharmony_ciEXPORT_SYMBOL(devm_pci_remap_iospace); 433662306a36Sopenharmony_ci 433762306a36Sopenharmony_ci/** 433862306a36Sopenharmony_ci * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace() 433962306a36Sopenharmony_ci * @dev: Generic device to remap IO address for 434062306a36Sopenharmony_ci * @offset: Resource address to map 434162306a36Sopenharmony_ci * @size: Size of map 434262306a36Sopenharmony_ci * 434362306a36Sopenharmony_ci * Managed pci_remap_cfgspace(). Map is automatically unmapped on driver 434462306a36Sopenharmony_ci * detach. 434562306a36Sopenharmony_ci */ 434662306a36Sopenharmony_civoid __iomem *devm_pci_remap_cfgspace(struct device *dev, 434762306a36Sopenharmony_ci resource_size_t offset, 434862306a36Sopenharmony_ci resource_size_t size) 434962306a36Sopenharmony_ci{ 435062306a36Sopenharmony_ci void __iomem **ptr, *addr; 435162306a36Sopenharmony_ci 435262306a36Sopenharmony_ci ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); 435362306a36Sopenharmony_ci if (!ptr) 435462306a36Sopenharmony_ci return NULL; 435562306a36Sopenharmony_ci 435662306a36Sopenharmony_ci addr = pci_remap_cfgspace(offset, size); 435762306a36Sopenharmony_ci if (addr) { 435862306a36Sopenharmony_ci *ptr = addr; 435962306a36Sopenharmony_ci devres_add(dev, ptr); 436062306a36Sopenharmony_ci } else 436162306a36Sopenharmony_ci devres_free(ptr); 436262306a36Sopenharmony_ci 436362306a36Sopenharmony_ci return addr; 436462306a36Sopenharmony_ci} 436562306a36Sopenharmony_ciEXPORT_SYMBOL(devm_pci_remap_cfgspace); 436662306a36Sopenharmony_ci 436762306a36Sopenharmony_ci/** 436862306a36Sopenharmony_ci * devm_pci_remap_cfg_resource - check, request region and ioremap cfg resource 436962306a36Sopenharmony_ci * @dev: generic device to handle the resource for 437062306a36Sopenharmony_ci * @res: configuration space resource to be handled 437162306a36Sopenharmony_ci * 437262306a36Sopenharmony_ci * Checks that a resource is a valid memory region, requests the memory 437362306a36Sopenharmony_ci * region and ioremaps with pci_remap_cfgspace() API that ensures the 437462306a36Sopenharmony_ci * proper PCI configuration space memory attributes are guaranteed. 437562306a36Sopenharmony_ci * 437662306a36Sopenharmony_ci * All operations are managed and will be undone on driver detach. 437762306a36Sopenharmony_ci * 437862306a36Sopenharmony_ci * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code 437962306a36Sopenharmony_ci * on failure. Usage example:: 438062306a36Sopenharmony_ci * 438162306a36Sopenharmony_ci * res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 438262306a36Sopenharmony_ci * base = devm_pci_remap_cfg_resource(&pdev->dev, res); 438362306a36Sopenharmony_ci * if (IS_ERR(base)) 438462306a36Sopenharmony_ci * return PTR_ERR(base); 438562306a36Sopenharmony_ci */ 438662306a36Sopenharmony_civoid __iomem *devm_pci_remap_cfg_resource(struct device *dev, 438762306a36Sopenharmony_ci struct resource *res) 438862306a36Sopenharmony_ci{ 438962306a36Sopenharmony_ci resource_size_t size; 439062306a36Sopenharmony_ci const char *name; 439162306a36Sopenharmony_ci void __iomem *dest_ptr; 439262306a36Sopenharmony_ci 439362306a36Sopenharmony_ci BUG_ON(!dev); 439462306a36Sopenharmony_ci 439562306a36Sopenharmony_ci if (!res || resource_type(res) != IORESOURCE_MEM) { 439662306a36Sopenharmony_ci dev_err(dev, "invalid resource\n"); 439762306a36Sopenharmony_ci return IOMEM_ERR_PTR(-EINVAL); 439862306a36Sopenharmony_ci } 439962306a36Sopenharmony_ci 440062306a36Sopenharmony_ci size = resource_size(res); 440162306a36Sopenharmony_ci 440262306a36Sopenharmony_ci if (res->name) 440362306a36Sopenharmony_ci name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", dev_name(dev), 440462306a36Sopenharmony_ci res->name); 440562306a36Sopenharmony_ci else 440662306a36Sopenharmony_ci name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); 440762306a36Sopenharmony_ci if (!name) 440862306a36Sopenharmony_ci return IOMEM_ERR_PTR(-ENOMEM); 440962306a36Sopenharmony_ci 441062306a36Sopenharmony_ci if (!devm_request_mem_region(dev, res->start, size, name)) { 441162306a36Sopenharmony_ci dev_err(dev, "can't request region for resource %pR\n", res); 441262306a36Sopenharmony_ci return IOMEM_ERR_PTR(-EBUSY); 441362306a36Sopenharmony_ci } 441462306a36Sopenharmony_ci 441562306a36Sopenharmony_ci dest_ptr = devm_pci_remap_cfgspace(dev, res->start, size); 441662306a36Sopenharmony_ci if (!dest_ptr) { 441762306a36Sopenharmony_ci dev_err(dev, "ioremap failed for resource %pR\n", res); 441862306a36Sopenharmony_ci devm_release_mem_region(dev, res->start, size); 441962306a36Sopenharmony_ci dest_ptr = IOMEM_ERR_PTR(-ENOMEM); 442062306a36Sopenharmony_ci } 442162306a36Sopenharmony_ci 442262306a36Sopenharmony_ci return dest_ptr; 442362306a36Sopenharmony_ci} 442462306a36Sopenharmony_ciEXPORT_SYMBOL(devm_pci_remap_cfg_resource); 442562306a36Sopenharmony_ci 442662306a36Sopenharmony_cistatic void __pci_set_master(struct pci_dev *dev, bool enable) 442762306a36Sopenharmony_ci{ 442862306a36Sopenharmony_ci u16 old_cmd, cmd; 442962306a36Sopenharmony_ci 443062306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &old_cmd); 443162306a36Sopenharmony_ci if (enable) 443262306a36Sopenharmony_ci cmd = old_cmd | PCI_COMMAND_MASTER; 443362306a36Sopenharmony_ci else 443462306a36Sopenharmony_ci cmd = old_cmd & ~PCI_COMMAND_MASTER; 443562306a36Sopenharmony_ci if (cmd != old_cmd) { 443662306a36Sopenharmony_ci pci_dbg(dev, "%s bus mastering\n", 443762306a36Sopenharmony_ci enable ? "enabling" : "disabling"); 443862306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, cmd); 443962306a36Sopenharmony_ci } 444062306a36Sopenharmony_ci dev->is_busmaster = enable; 444162306a36Sopenharmony_ci} 444262306a36Sopenharmony_ci 444362306a36Sopenharmony_ci/** 444462306a36Sopenharmony_ci * pcibios_setup - process "pci=" kernel boot arguments 444562306a36Sopenharmony_ci * @str: string used to pass in "pci=" kernel boot arguments 444662306a36Sopenharmony_ci * 444762306a36Sopenharmony_ci * Process kernel boot arguments. This is the default implementation. 444862306a36Sopenharmony_ci * Architecture specific implementations can override this as necessary. 444962306a36Sopenharmony_ci */ 445062306a36Sopenharmony_cichar * __weak __init pcibios_setup(char *str) 445162306a36Sopenharmony_ci{ 445262306a36Sopenharmony_ci return str; 445362306a36Sopenharmony_ci} 445462306a36Sopenharmony_ci 445562306a36Sopenharmony_ci/** 445662306a36Sopenharmony_ci * pcibios_set_master - enable PCI bus-mastering for device dev 445762306a36Sopenharmony_ci * @dev: the PCI device to enable 445862306a36Sopenharmony_ci * 445962306a36Sopenharmony_ci * Enables PCI bus-mastering for the device. This is the default 446062306a36Sopenharmony_ci * implementation. Architecture specific implementations can override 446162306a36Sopenharmony_ci * this if necessary. 446262306a36Sopenharmony_ci */ 446362306a36Sopenharmony_civoid __weak pcibios_set_master(struct pci_dev *dev) 446462306a36Sopenharmony_ci{ 446562306a36Sopenharmony_ci u8 lat; 446662306a36Sopenharmony_ci 446762306a36Sopenharmony_ci /* The latency timer doesn't apply to PCIe (either Type 0 or Type 1) */ 446862306a36Sopenharmony_ci if (pci_is_pcie(dev)) 446962306a36Sopenharmony_ci return; 447062306a36Sopenharmony_ci 447162306a36Sopenharmony_ci pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); 447262306a36Sopenharmony_ci if (lat < 16) 447362306a36Sopenharmony_ci lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; 447462306a36Sopenharmony_ci else if (lat > pcibios_max_latency) 447562306a36Sopenharmony_ci lat = pcibios_max_latency; 447662306a36Sopenharmony_ci else 447762306a36Sopenharmony_ci return; 447862306a36Sopenharmony_ci 447962306a36Sopenharmony_ci pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); 448062306a36Sopenharmony_ci} 448162306a36Sopenharmony_ci 448262306a36Sopenharmony_ci/** 448362306a36Sopenharmony_ci * pci_set_master - enables bus-mastering for device dev 448462306a36Sopenharmony_ci * @dev: the PCI device to enable 448562306a36Sopenharmony_ci * 448662306a36Sopenharmony_ci * Enables bus-mastering on the device and calls pcibios_set_master() 448762306a36Sopenharmony_ci * to do the needed arch specific settings. 448862306a36Sopenharmony_ci */ 448962306a36Sopenharmony_civoid pci_set_master(struct pci_dev *dev) 449062306a36Sopenharmony_ci{ 449162306a36Sopenharmony_ci __pci_set_master(dev, true); 449262306a36Sopenharmony_ci pcibios_set_master(dev); 449362306a36Sopenharmony_ci} 449462306a36Sopenharmony_ciEXPORT_SYMBOL(pci_set_master); 449562306a36Sopenharmony_ci 449662306a36Sopenharmony_ci/** 449762306a36Sopenharmony_ci * pci_clear_master - disables bus-mastering for device dev 449862306a36Sopenharmony_ci * @dev: the PCI device to disable 449962306a36Sopenharmony_ci */ 450062306a36Sopenharmony_civoid pci_clear_master(struct pci_dev *dev) 450162306a36Sopenharmony_ci{ 450262306a36Sopenharmony_ci __pci_set_master(dev, false); 450362306a36Sopenharmony_ci} 450462306a36Sopenharmony_ciEXPORT_SYMBOL(pci_clear_master); 450562306a36Sopenharmony_ci 450662306a36Sopenharmony_ci/** 450762306a36Sopenharmony_ci * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed 450862306a36Sopenharmony_ci * @dev: the PCI device for which MWI is to be enabled 450962306a36Sopenharmony_ci * 451062306a36Sopenharmony_ci * Helper function for pci_set_mwi. 451162306a36Sopenharmony_ci * Originally copied from drivers/net/acenic.c. 451262306a36Sopenharmony_ci * Copyright 1998-2001 by Jes Sorensen, <jes@trained-monkey.org>. 451362306a36Sopenharmony_ci * 451462306a36Sopenharmony_ci * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 451562306a36Sopenharmony_ci */ 451662306a36Sopenharmony_ciint pci_set_cacheline_size(struct pci_dev *dev) 451762306a36Sopenharmony_ci{ 451862306a36Sopenharmony_ci u8 cacheline_size; 451962306a36Sopenharmony_ci 452062306a36Sopenharmony_ci if (!pci_cache_line_size) 452162306a36Sopenharmony_ci return -EINVAL; 452262306a36Sopenharmony_ci 452362306a36Sopenharmony_ci /* Validate current setting: the PCI_CACHE_LINE_SIZE must be 452462306a36Sopenharmony_ci equal to or multiple of the right value. */ 452562306a36Sopenharmony_ci pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline_size); 452662306a36Sopenharmony_ci if (cacheline_size >= pci_cache_line_size && 452762306a36Sopenharmony_ci (cacheline_size % pci_cache_line_size) == 0) 452862306a36Sopenharmony_ci return 0; 452962306a36Sopenharmony_ci 453062306a36Sopenharmony_ci /* Write the correct value. */ 453162306a36Sopenharmony_ci pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size); 453262306a36Sopenharmony_ci /* Read it back. */ 453362306a36Sopenharmony_ci pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline_size); 453462306a36Sopenharmony_ci if (cacheline_size == pci_cache_line_size) 453562306a36Sopenharmony_ci return 0; 453662306a36Sopenharmony_ci 453762306a36Sopenharmony_ci pci_dbg(dev, "cache line size of %d is not supported\n", 453862306a36Sopenharmony_ci pci_cache_line_size << 2); 453962306a36Sopenharmony_ci 454062306a36Sopenharmony_ci return -EINVAL; 454162306a36Sopenharmony_ci} 454262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_set_cacheline_size); 454362306a36Sopenharmony_ci 454462306a36Sopenharmony_ci/** 454562306a36Sopenharmony_ci * pci_set_mwi - enables memory-write-invalidate PCI transaction 454662306a36Sopenharmony_ci * @dev: the PCI device for which MWI is enabled 454762306a36Sopenharmony_ci * 454862306a36Sopenharmony_ci * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND. 454962306a36Sopenharmony_ci * 455062306a36Sopenharmony_ci * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 455162306a36Sopenharmony_ci */ 455262306a36Sopenharmony_ciint pci_set_mwi(struct pci_dev *dev) 455362306a36Sopenharmony_ci{ 455462306a36Sopenharmony_ci#ifdef PCI_DISABLE_MWI 455562306a36Sopenharmony_ci return 0; 455662306a36Sopenharmony_ci#else 455762306a36Sopenharmony_ci int rc; 455862306a36Sopenharmony_ci u16 cmd; 455962306a36Sopenharmony_ci 456062306a36Sopenharmony_ci rc = pci_set_cacheline_size(dev); 456162306a36Sopenharmony_ci if (rc) 456262306a36Sopenharmony_ci return rc; 456362306a36Sopenharmony_ci 456462306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &cmd); 456562306a36Sopenharmony_ci if (!(cmd & PCI_COMMAND_INVALIDATE)) { 456662306a36Sopenharmony_ci pci_dbg(dev, "enabling Mem-Wr-Inval\n"); 456762306a36Sopenharmony_ci cmd |= PCI_COMMAND_INVALIDATE; 456862306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, cmd); 456962306a36Sopenharmony_ci } 457062306a36Sopenharmony_ci return 0; 457162306a36Sopenharmony_ci#endif 457262306a36Sopenharmony_ci} 457362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_set_mwi); 457462306a36Sopenharmony_ci 457562306a36Sopenharmony_ci/** 457662306a36Sopenharmony_ci * pcim_set_mwi - a device-managed pci_set_mwi() 457762306a36Sopenharmony_ci * @dev: the PCI device for which MWI is enabled 457862306a36Sopenharmony_ci * 457962306a36Sopenharmony_ci * Managed pci_set_mwi(). 458062306a36Sopenharmony_ci * 458162306a36Sopenharmony_ci * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 458262306a36Sopenharmony_ci */ 458362306a36Sopenharmony_ciint pcim_set_mwi(struct pci_dev *dev) 458462306a36Sopenharmony_ci{ 458562306a36Sopenharmony_ci struct pci_devres *dr; 458662306a36Sopenharmony_ci 458762306a36Sopenharmony_ci dr = find_pci_dr(dev); 458862306a36Sopenharmony_ci if (!dr) 458962306a36Sopenharmony_ci return -ENOMEM; 459062306a36Sopenharmony_ci 459162306a36Sopenharmony_ci dr->mwi = 1; 459262306a36Sopenharmony_ci return pci_set_mwi(dev); 459362306a36Sopenharmony_ci} 459462306a36Sopenharmony_ciEXPORT_SYMBOL(pcim_set_mwi); 459562306a36Sopenharmony_ci 459662306a36Sopenharmony_ci/** 459762306a36Sopenharmony_ci * pci_try_set_mwi - enables memory-write-invalidate PCI transaction 459862306a36Sopenharmony_ci * @dev: the PCI device for which MWI is enabled 459962306a36Sopenharmony_ci * 460062306a36Sopenharmony_ci * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND. 460162306a36Sopenharmony_ci * Callers are not required to check the return value. 460262306a36Sopenharmony_ci * 460362306a36Sopenharmony_ci * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 460462306a36Sopenharmony_ci */ 460562306a36Sopenharmony_ciint pci_try_set_mwi(struct pci_dev *dev) 460662306a36Sopenharmony_ci{ 460762306a36Sopenharmony_ci#ifdef PCI_DISABLE_MWI 460862306a36Sopenharmony_ci return 0; 460962306a36Sopenharmony_ci#else 461062306a36Sopenharmony_ci return pci_set_mwi(dev); 461162306a36Sopenharmony_ci#endif 461262306a36Sopenharmony_ci} 461362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_try_set_mwi); 461462306a36Sopenharmony_ci 461562306a36Sopenharmony_ci/** 461662306a36Sopenharmony_ci * pci_clear_mwi - disables Memory-Write-Invalidate for device dev 461762306a36Sopenharmony_ci * @dev: the PCI device to disable 461862306a36Sopenharmony_ci * 461962306a36Sopenharmony_ci * Disables PCI Memory-Write-Invalidate transaction on the device 462062306a36Sopenharmony_ci */ 462162306a36Sopenharmony_civoid pci_clear_mwi(struct pci_dev *dev) 462262306a36Sopenharmony_ci{ 462362306a36Sopenharmony_ci#ifndef PCI_DISABLE_MWI 462462306a36Sopenharmony_ci u16 cmd; 462562306a36Sopenharmony_ci 462662306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &cmd); 462762306a36Sopenharmony_ci if (cmd & PCI_COMMAND_INVALIDATE) { 462862306a36Sopenharmony_ci cmd &= ~PCI_COMMAND_INVALIDATE; 462962306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, cmd); 463062306a36Sopenharmony_ci } 463162306a36Sopenharmony_ci#endif 463262306a36Sopenharmony_ci} 463362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_clear_mwi); 463462306a36Sopenharmony_ci 463562306a36Sopenharmony_ci/** 463662306a36Sopenharmony_ci * pci_disable_parity - disable parity checking for device 463762306a36Sopenharmony_ci * @dev: the PCI device to operate on 463862306a36Sopenharmony_ci * 463962306a36Sopenharmony_ci * Disable parity checking for device @dev 464062306a36Sopenharmony_ci */ 464162306a36Sopenharmony_civoid pci_disable_parity(struct pci_dev *dev) 464262306a36Sopenharmony_ci{ 464362306a36Sopenharmony_ci u16 cmd; 464462306a36Sopenharmony_ci 464562306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &cmd); 464662306a36Sopenharmony_ci if (cmd & PCI_COMMAND_PARITY) { 464762306a36Sopenharmony_ci cmd &= ~PCI_COMMAND_PARITY; 464862306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, cmd); 464962306a36Sopenharmony_ci } 465062306a36Sopenharmony_ci} 465162306a36Sopenharmony_ci 465262306a36Sopenharmony_ci/** 465362306a36Sopenharmony_ci * pci_intx - enables/disables PCI INTx for device dev 465462306a36Sopenharmony_ci * @pdev: the PCI device to operate on 465562306a36Sopenharmony_ci * @enable: boolean: whether to enable or disable PCI INTx 465662306a36Sopenharmony_ci * 465762306a36Sopenharmony_ci * Enables/disables PCI INTx for device @pdev 465862306a36Sopenharmony_ci */ 465962306a36Sopenharmony_civoid pci_intx(struct pci_dev *pdev, int enable) 466062306a36Sopenharmony_ci{ 466162306a36Sopenharmony_ci u16 pci_command, new; 466262306a36Sopenharmony_ci 466362306a36Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &pci_command); 466462306a36Sopenharmony_ci 466562306a36Sopenharmony_ci if (enable) 466662306a36Sopenharmony_ci new = pci_command & ~PCI_COMMAND_INTX_DISABLE; 466762306a36Sopenharmony_ci else 466862306a36Sopenharmony_ci new = pci_command | PCI_COMMAND_INTX_DISABLE; 466962306a36Sopenharmony_ci 467062306a36Sopenharmony_ci if (new != pci_command) { 467162306a36Sopenharmony_ci struct pci_devres *dr; 467262306a36Sopenharmony_ci 467362306a36Sopenharmony_ci pci_write_config_word(pdev, PCI_COMMAND, new); 467462306a36Sopenharmony_ci 467562306a36Sopenharmony_ci dr = find_pci_dr(pdev); 467662306a36Sopenharmony_ci if (dr && !dr->restore_intx) { 467762306a36Sopenharmony_ci dr->restore_intx = 1; 467862306a36Sopenharmony_ci dr->orig_intx = !enable; 467962306a36Sopenharmony_ci } 468062306a36Sopenharmony_ci } 468162306a36Sopenharmony_ci} 468262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_intx); 468362306a36Sopenharmony_ci 468462306a36Sopenharmony_cistatic bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask) 468562306a36Sopenharmony_ci{ 468662306a36Sopenharmony_ci struct pci_bus *bus = dev->bus; 468762306a36Sopenharmony_ci bool mask_updated = true; 468862306a36Sopenharmony_ci u32 cmd_status_dword; 468962306a36Sopenharmony_ci u16 origcmd, newcmd; 469062306a36Sopenharmony_ci unsigned long flags; 469162306a36Sopenharmony_ci bool irq_pending; 469262306a36Sopenharmony_ci 469362306a36Sopenharmony_ci /* 469462306a36Sopenharmony_ci * We do a single dword read to retrieve both command and status. 469562306a36Sopenharmony_ci * Document assumptions that make this possible. 469662306a36Sopenharmony_ci */ 469762306a36Sopenharmony_ci BUILD_BUG_ON(PCI_COMMAND % 4); 469862306a36Sopenharmony_ci BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS); 469962306a36Sopenharmony_ci 470062306a36Sopenharmony_ci raw_spin_lock_irqsave(&pci_lock, flags); 470162306a36Sopenharmony_ci 470262306a36Sopenharmony_ci bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword); 470362306a36Sopenharmony_ci 470462306a36Sopenharmony_ci irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT; 470562306a36Sopenharmony_ci 470662306a36Sopenharmony_ci /* 470762306a36Sopenharmony_ci * Check interrupt status register to see whether our device 470862306a36Sopenharmony_ci * triggered the interrupt (when masking) or the next IRQ is 470962306a36Sopenharmony_ci * already pending (when unmasking). 471062306a36Sopenharmony_ci */ 471162306a36Sopenharmony_ci if (mask != irq_pending) { 471262306a36Sopenharmony_ci mask_updated = false; 471362306a36Sopenharmony_ci goto done; 471462306a36Sopenharmony_ci } 471562306a36Sopenharmony_ci 471662306a36Sopenharmony_ci origcmd = cmd_status_dword; 471762306a36Sopenharmony_ci newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE; 471862306a36Sopenharmony_ci if (mask) 471962306a36Sopenharmony_ci newcmd |= PCI_COMMAND_INTX_DISABLE; 472062306a36Sopenharmony_ci if (newcmd != origcmd) 472162306a36Sopenharmony_ci bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd); 472262306a36Sopenharmony_ci 472362306a36Sopenharmony_cidone: 472462306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&pci_lock, flags); 472562306a36Sopenharmony_ci 472662306a36Sopenharmony_ci return mask_updated; 472762306a36Sopenharmony_ci} 472862306a36Sopenharmony_ci 472962306a36Sopenharmony_ci/** 473062306a36Sopenharmony_ci * pci_check_and_mask_intx - mask INTx on pending interrupt 473162306a36Sopenharmony_ci * @dev: the PCI device to operate on 473262306a36Sopenharmony_ci * 473362306a36Sopenharmony_ci * Check if the device dev has its INTx line asserted, mask it and return 473462306a36Sopenharmony_ci * true in that case. False is returned if no interrupt was pending. 473562306a36Sopenharmony_ci */ 473662306a36Sopenharmony_cibool pci_check_and_mask_intx(struct pci_dev *dev) 473762306a36Sopenharmony_ci{ 473862306a36Sopenharmony_ci return pci_check_and_set_intx_mask(dev, true); 473962306a36Sopenharmony_ci} 474062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_check_and_mask_intx); 474162306a36Sopenharmony_ci 474262306a36Sopenharmony_ci/** 474362306a36Sopenharmony_ci * pci_check_and_unmask_intx - unmask INTx if no interrupt is pending 474462306a36Sopenharmony_ci * @dev: the PCI device to operate on 474562306a36Sopenharmony_ci * 474662306a36Sopenharmony_ci * Check if the device dev has its INTx line asserted, unmask it if not and 474762306a36Sopenharmony_ci * return true. False is returned and the mask remains active if there was 474862306a36Sopenharmony_ci * still an interrupt pending. 474962306a36Sopenharmony_ci */ 475062306a36Sopenharmony_cibool pci_check_and_unmask_intx(struct pci_dev *dev) 475162306a36Sopenharmony_ci{ 475262306a36Sopenharmony_ci return pci_check_and_set_intx_mask(dev, false); 475362306a36Sopenharmony_ci} 475462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_check_and_unmask_intx); 475562306a36Sopenharmony_ci 475662306a36Sopenharmony_ci/** 475762306a36Sopenharmony_ci * pci_wait_for_pending_transaction - wait for pending transaction 475862306a36Sopenharmony_ci * @dev: the PCI device to operate on 475962306a36Sopenharmony_ci * 476062306a36Sopenharmony_ci * Return 0 if transaction is pending 1 otherwise. 476162306a36Sopenharmony_ci */ 476262306a36Sopenharmony_ciint pci_wait_for_pending_transaction(struct pci_dev *dev) 476362306a36Sopenharmony_ci{ 476462306a36Sopenharmony_ci if (!pci_is_pcie(dev)) 476562306a36Sopenharmony_ci return 1; 476662306a36Sopenharmony_ci 476762306a36Sopenharmony_ci return pci_wait_for_pending(dev, pci_pcie_cap(dev) + PCI_EXP_DEVSTA, 476862306a36Sopenharmony_ci PCI_EXP_DEVSTA_TRPND); 476962306a36Sopenharmony_ci} 477062306a36Sopenharmony_ciEXPORT_SYMBOL(pci_wait_for_pending_transaction); 477162306a36Sopenharmony_ci 477262306a36Sopenharmony_ci/** 477362306a36Sopenharmony_ci * pcie_flr - initiate a PCIe function level reset 477462306a36Sopenharmony_ci * @dev: device to reset 477562306a36Sopenharmony_ci * 477662306a36Sopenharmony_ci * Initiate a function level reset unconditionally on @dev without 477762306a36Sopenharmony_ci * checking any flags and DEVCAP 477862306a36Sopenharmony_ci */ 477962306a36Sopenharmony_ciint pcie_flr(struct pci_dev *dev) 478062306a36Sopenharmony_ci{ 478162306a36Sopenharmony_ci if (!pci_wait_for_pending_transaction(dev)) 478262306a36Sopenharmony_ci pci_err(dev, "timed out waiting for pending transaction; performing function level reset anyway\n"); 478362306a36Sopenharmony_ci 478462306a36Sopenharmony_ci pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); 478562306a36Sopenharmony_ci 478662306a36Sopenharmony_ci if (dev->imm_ready) 478762306a36Sopenharmony_ci return 0; 478862306a36Sopenharmony_ci 478962306a36Sopenharmony_ci /* 479062306a36Sopenharmony_ci * Per PCIe r4.0, sec 6.6.2, a device must complete an FLR within 479162306a36Sopenharmony_ci * 100ms, but may silently discard requests while the FLR is in 479262306a36Sopenharmony_ci * progress. Wait 100ms before trying to access the device. 479362306a36Sopenharmony_ci */ 479462306a36Sopenharmony_ci msleep(100); 479562306a36Sopenharmony_ci 479662306a36Sopenharmony_ci return pci_dev_wait(dev, "FLR", PCIE_RESET_READY_POLL_MS); 479762306a36Sopenharmony_ci} 479862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pcie_flr); 479962306a36Sopenharmony_ci 480062306a36Sopenharmony_ci/** 480162306a36Sopenharmony_ci * pcie_reset_flr - initiate a PCIe function level reset 480262306a36Sopenharmony_ci * @dev: device to reset 480362306a36Sopenharmony_ci * @probe: if true, return 0 if device can be reset this way 480462306a36Sopenharmony_ci * 480562306a36Sopenharmony_ci * Initiate a function level reset on @dev. 480662306a36Sopenharmony_ci */ 480762306a36Sopenharmony_ciint pcie_reset_flr(struct pci_dev *dev, bool probe) 480862306a36Sopenharmony_ci{ 480962306a36Sopenharmony_ci if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET) 481062306a36Sopenharmony_ci return -ENOTTY; 481162306a36Sopenharmony_ci 481262306a36Sopenharmony_ci if (!(dev->devcap & PCI_EXP_DEVCAP_FLR)) 481362306a36Sopenharmony_ci return -ENOTTY; 481462306a36Sopenharmony_ci 481562306a36Sopenharmony_ci if (probe) 481662306a36Sopenharmony_ci return 0; 481762306a36Sopenharmony_ci 481862306a36Sopenharmony_ci return pcie_flr(dev); 481962306a36Sopenharmony_ci} 482062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pcie_reset_flr); 482162306a36Sopenharmony_ci 482262306a36Sopenharmony_cistatic int pci_af_flr(struct pci_dev *dev, bool probe) 482362306a36Sopenharmony_ci{ 482462306a36Sopenharmony_ci int pos; 482562306a36Sopenharmony_ci u8 cap; 482662306a36Sopenharmony_ci 482762306a36Sopenharmony_ci pos = pci_find_capability(dev, PCI_CAP_ID_AF); 482862306a36Sopenharmony_ci if (!pos) 482962306a36Sopenharmony_ci return -ENOTTY; 483062306a36Sopenharmony_ci 483162306a36Sopenharmony_ci if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET) 483262306a36Sopenharmony_ci return -ENOTTY; 483362306a36Sopenharmony_ci 483462306a36Sopenharmony_ci pci_read_config_byte(dev, pos + PCI_AF_CAP, &cap); 483562306a36Sopenharmony_ci if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR)) 483662306a36Sopenharmony_ci return -ENOTTY; 483762306a36Sopenharmony_ci 483862306a36Sopenharmony_ci if (probe) 483962306a36Sopenharmony_ci return 0; 484062306a36Sopenharmony_ci 484162306a36Sopenharmony_ci /* 484262306a36Sopenharmony_ci * Wait for Transaction Pending bit to clear. A word-aligned test 484362306a36Sopenharmony_ci * is used, so we use the control offset rather than status and shift 484462306a36Sopenharmony_ci * the test bit to match. 484562306a36Sopenharmony_ci */ 484662306a36Sopenharmony_ci if (!pci_wait_for_pending(dev, pos + PCI_AF_CTRL, 484762306a36Sopenharmony_ci PCI_AF_STATUS_TP << 8)) 484862306a36Sopenharmony_ci pci_err(dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n"); 484962306a36Sopenharmony_ci 485062306a36Sopenharmony_ci pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); 485162306a36Sopenharmony_ci 485262306a36Sopenharmony_ci if (dev->imm_ready) 485362306a36Sopenharmony_ci return 0; 485462306a36Sopenharmony_ci 485562306a36Sopenharmony_ci /* 485662306a36Sopenharmony_ci * Per Advanced Capabilities for Conventional PCI ECN, 13 April 2006, 485762306a36Sopenharmony_ci * updated 27 July 2006; a device must complete an FLR within 485862306a36Sopenharmony_ci * 100ms, but may silently discard requests while the FLR is in 485962306a36Sopenharmony_ci * progress. Wait 100ms before trying to access the device. 486062306a36Sopenharmony_ci */ 486162306a36Sopenharmony_ci msleep(100); 486262306a36Sopenharmony_ci 486362306a36Sopenharmony_ci return pci_dev_wait(dev, "AF_FLR", PCIE_RESET_READY_POLL_MS); 486462306a36Sopenharmony_ci} 486562306a36Sopenharmony_ci 486662306a36Sopenharmony_ci/** 486762306a36Sopenharmony_ci * pci_pm_reset - Put device into PCI_D3 and back into PCI_D0. 486862306a36Sopenharmony_ci * @dev: Device to reset. 486962306a36Sopenharmony_ci * @probe: if true, return 0 if the device can be reset this way. 487062306a36Sopenharmony_ci * 487162306a36Sopenharmony_ci * If @dev supports native PCI PM and its PCI_PM_CTRL_NO_SOFT_RESET flag is 487262306a36Sopenharmony_ci * unset, it will be reinitialized internally when going from PCI_D3hot to 487362306a36Sopenharmony_ci * PCI_D0. If that's the case and the device is not in a low-power state 487462306a36Sopenharmony_ci * already, force it into PCI_D3hot and back to PCI_D0, causing it to be reset. 487562306a36Sopenharmony_ci * 487662306a36Sopenharmony_ci * NOTE: This causes the caller to sleep for twice the device power transition 487762306a36Sopenharmony_ci * cooldown period, which for the D0->D3hot and D3hot->D0 transitions is 10 ms 487862306a36Sopenharmony_ci * by default (i.e. unless the @dev's d3hot_delay field has a different value). 487962306a36Sopenharmony_ci * Moreover, only devices in D0 can be reset by this function. 488062306a36Sopenharmony_ci */ 488162306a36Sopenharmony_cistatic int pci_pm_reset(struct pci_dev *dev, bool probe) 488262306a36Sopenharmony_ci{ 488362306a36Sopenharmony_ci u16 csr; 488462306a36Sopenharmony_ci 488562306a36Sopenharmony_ci if (!dev->pm_cap || dev->dev_flags & PCI_DEV_FLAGS_NO_PM_RESET) 488662306a36Sopenharmony_ci return -ENOTTY; 488762306a36Sopenharmony_ci 488862306a36Sopenharmony_ci pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr); 488962306a36Sopenharmony_ci if (csr & PCI_PM_CTRL_NO_SOFT_RESET) 489062306a36Sopenharmony_ci return -ENOTTY; 489162306a36Sopenharmony_ci 489262306a36Sopenharmony_ci if (probe) 489362306a36Sopenharmony_ci return 0; 489462306a36Sopenharmony_ci 489562306a36Sopenharmony_ci if (dev->current_state != PCI_D0) 489662306a36Sopenharmony_ci return -EINVAL; 489762306a36Sopenharmony_ci 489862306a36Sopenharmony_ci csr &= ~PCI_PM_CTRL_STATE_MASK; 489962306a36Sopenharmony_ci csr |= PCI_D3hot; 490062306a36Sopenharmony_ci pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); 490162306a36Sopenharmony_ci pci_dev_d3_sleep(dev); 490262306a36Sopenharmony_ci 490362306a36Sopenharmony_ci csr &= ~PCI_PM_CTRL_STATE_MASK; 490462306a36Sopenharmony_ci csr |= PCI_D0; 490562306a36Sopenharmony_ci pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); 490662306a36Sopenharmony_ci pci_dev_d3_sleep(dev); 490762306a36Sopenharmony_ci 490862306a36Sopenharmony_ci return pci_dev_wait(dev, "PM D3hot->D0", PCIE_RESET_READY_POLL_MS); 490962306a36Sopenharmony_ci} 491062306a36Sopenharmony_ci 491162306a36Sopenharmony_ci/** 491262306a36Sopenharmony_ci * pcie_wait_for_link_status - Wait for link status change 491362306a36Sopenharmony_ci * @pdev: Device whose link to wait for. 491462306a36Sopenharmony_ci * @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE. 491562306a36Sopenharmony_ci * @active: Waiting for active or inactive? 491662306a36Sopenharmony_ci * 491762306a36Sopenharmony_ci * Return 0 if successful, or -ETIMEDOUT if status has not changed within 491862306a36Sopenharmony_ci * PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. 491962306a36Sopenharmony_ci */ 492062306a36Sopenharmony_cistatic int pcie_wait_for_link_status(struct pci_dev *pdev, 492162306a36Sopenharmony_ci bool use_lt, bool active) 492262306a36Sopenharmony_ci{ 492362306a36Sopenharmony_ci u16 lnksta_mask, lnksta_match; 492462306a36Sopenharmony_ci unsigned long end_jiffies; 492562306a36Sopenharmony_ci u16 lnksta; 492662306a36Sopenharmony_ci 492762306a36Sopenharmony_ci lnksta_mask = use_lt ? PCI_EXP_LNKSTA_LT : PCI_EXP_LNKSTA_DLLLA; 492862306a36Sopenharmony_ci lnksta_match = active ? lnksta_mask : 0; 492962306a36Sopenharmony_ci 493062306a36Sopenharmony_ci end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS); 493162306a36Sopenharmony_ci do { 493262306a36Sopenharmony_ci pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta); 493362306a36Sopenharmony_ci if ((lnksta & lnksta_mask) == lnksta_match) 493462306a36Sopenharmony_ci return 0; 493562306a36Sopenharmony_ci msleep(1); 493662306a36Sopenharmony_ci } while (time_before(jiffies, end_jiffies)); 493762306a36Sopenharmony_ci 493862306a36Sopenharmony_ci return -ETIMEDOUT; 493962306a36Sopenharmony_ci} 494062306a36Sopenharmony_ci 494162306a36Sopenharmony_ci/** 494262306a36Sopenharmony_ci * pcie_retrain_link - Request a link retrain and wait for it to complete 494362306a36Sopenharmony_ci * @pdev: Device whose link to retrain. 494462306a36Sopenharmony_ci * @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE, for status. 494562306a36Sopenharmony_ci * 494662306a36Sopenharmony_ci * Retrain completion status is retrieved from the Link Status Register 494762306a36Sopenharmony_ci * according to @use_lt. It is not verified whether the use of the DLLLA 494862306a36Sopenharmony_ci * bit is valid. 494962306a36Sopenharmony_ci * 495062306a36Sopenharmony_ci * Return 0 if successful, or -ETIMEDOUT if training has not completed 495162306a36Sopenharmony_ci * within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. 495262306a36Sopenharmony_ci */ 495362306a36Sopenharmony_ciint pcie_retrain_link(struct pci_dev *pdev, bool use_lt) 495462306a36Sopenharmony_ci{ 495562306a36Sopenharmony_ci int rc; 495662306a36Sopenharmony_ci 495762306a36Sopenharmony_ci /* 495862306a36Sopenharmony_ci * Ensure the updated LNKCTL parameters are used during link 495962306a36Sopenharmony_ci * training by checking that there is no ongoing link training to 496062306a36Sopenharmony_ci * avoid LTSSM race as recommended in Implementation Note at the 496162306a36Sopenharmony_ci * end of PCIe r6.0.1 sec 7.5.3.7. 496262306a36Sopenharmony_ci */ 496362306a36Sopenharmony_ci rc = pcie_wait_for_link_status(pdev, use_lt, !use_lt); 496462306a36Sopenharmony_ci if (rc) 496562306a36Sopenharmony_ci return rc; 496662306a36Sopenharmony_ci 496762306a36Sopenharmony_ci pcie_capability_set_word(pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RL); 496862306a36Sopenharmony_ci if (pdev->clear_retrain_link) { 496962306a36Sopenharmony_ci /* 497062306a36Sopenharmony_ci * Due to an erratum in some devices the Retrain Link bit 497162306a36Sopenharmony_ci * needs to be cleared again manually to allow the link 497262306a36Sopenharmony_ci * training to succeed. 497362306a36Sopenharmony_ci */ 497462306a36Sopenharmony_ci pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_RL); 497562306a36Sopenharmony_ci } 497662306a36Sopenharmony_ci 497762306a36Sopenharmony_ci return pcie_wait_for_link_status(pdev, use_lt, !use_lt); 497862306a36Sopenharmony_ci} 497962306a36Sopenharmony_ci 498062306a36Sopenharmony_ci/** 498162306a36Sopenharmony_ci * pcie_wait_for_link_delay - Wait until link is active or inactive 498262306a36Sopenharmony_ci * @pdev: Bridge device 498362306a36Sopenharmony_ci * @active: waiting for active or inactive? 498462306a36Sopenharmony_ci * @delay: Delay to wait after link has become active (in ms) 498562306a36Sopenharmony_ci * 498662306a36Sopenharmony_ci * Use this to wait till link becomes active or inactive. 498762306a36Sopenharmony_ci */ 498862306a36Sopenharmony_cistatic bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, 498962306a36Sopenharmony_ci int delay) 499062306a36Sopenharmony_ci{ 499162306a36Sopenharmony_ci int rc; 499262306a36Sopenharmony_ci 499362306a36Sopenharmony_ci /* 499462306a36Sopenharmony_ci * Some controllers might not implement link active reporting. In this 499562306a36Sopenharmony_ci * case, we wait for 1000 ms + any delay requested by the caller. 499662306a36Sopenharmony_ci */ 499762306a36Sopenharmony_ci if (!pdev->link_active_reporting) { 499862306a36Sopenharmony_ci msleep(PCIE_LINK_RETRAIN_TIMEOUT_MS + delay); 499962306a36Sopenharmony_ci return true; 500062306a36Sopenharmony_ci } 500162306a36Sopenharmony_ci 500262306a36Sopenharmony_ci /* 500362306a36Sopenharmony_ci * PCIe r4.0 sec 6.6.1, a component must enter LTSSM Detect within 20ms, 500462306a36Sopenharmony_ci * after which we should expect an link active if the reset was 500562306a36Sopenharmony_ci * successful. If so, software must wait a minimum 100ms before sending 500662306a36Sopenharmony_ci * configuration requests to devices downstream this port. 500762306a36Sopenharmony_ci * 500862306a36Sopenharmony_ci * If the link fails to activate, either the device was physically 500962306a36Sopenharmony_ci * removed or the link is permanently failed. 501062306a36Sopenharmony_ci */ 501162306a36Sopenharmony_ci if (active) 501262306a36Sopenharmony_ci msleep(20); 501362306a36Sopenharmony_ci rc = pcie_wait_for_link_status(pdev, false, active); 501462306a36Sopenharmony_ci if (active) { 501562306a36Sopenharmony_ci if (rc) 501662306a36Sopenharmony_ci rc = pcie_failed_link_retrain(pdev); 501762306a36Sopenharmony_ci if (rc) 501862306a36Sopenharmony_ci return false; 501962306a36Sopenharmony_ci 502062306a36Sopenharmony_ci msleep(delay); 502162306a36Sopenharmony_ci return true; 502262306a36Sopenharmony_ci } 502362306a36Sopenharmony_ci 502462306a36Sopenharmony_ci if (rc) 502562306a36Sopenharmony_ci return false; 502662306a36Sopenharmony_ci 502762306a36Sopenharmony_ci return true; 502862306a36Sopenharmony_ci} 502962306a36Sopenharmony_ci 503062306a36Sopenharmony_ci/** 503162306a36Sopenharmony_ci * pcie_wait_for_link - Wait until link is active or inactive 503262306a36Sopenharmony_ci * @pdev: Bridge device 503362306a36Sopenharmony_ci * @active: waiting for active or inactive? 503462306a36Sopenharmony_ci * 503562306a36Sopenharmony_ci * Use this to wait till link becomes active or inactive. 503662306a36Sopenharmony_ci */ 503762306a36Sopenharmony_cibool pcie_wait_for_link(struct pci_dev *pdev, bool active) 503862306a36Sopenharmony_ci{ 503962306a36Sopenharmony_ci return pcie_wait_for_link_delay(pdev, active, 100); 504062306a36Sopenharmony_ci} 504162306a36Sopenharmony_ci 504262306a36Sopenharmony_ci/* 504362306a36Sopenharmony_ci * Find maximum D3cold delay required by all the devices on the bus. The 504462306a36Sopenharmony_ci * spec says 100 ms, but firmware can lower it and we allow drivers to 504562306a36Sopenharmony_ci * increase it as well. 504662306a36Sopenharmony_ci * 504762306a36Sopenharmony_ci * Called with @pci_bus_sem locked for reading. 504862306a36Sopenharmony_ci */ 504962306a36Sopenharmony_cistatic int pci_bus_max_d3cold_delay(const struct pci_bus *bus) 505062306a36Sopenharmony_ci{ 505162306a36Sopenharmony_ci const struct pci_dev *pdev; 505262306a36Sopenharmony_ci int min_delay = 100; 505362306a36Sopenharmony_ci int max_delay = 0; 505462306a36Sopenharmony_ci 505562306a36Sopenharmony_ci list_for_each_entry(pdev, &bus->devices, bus_list) { 505662306a36Sopenharmony_ci if (pdev->d3cold_delay < min_delay) 505762306a36Sopenharmony_ci min_delay = pdev->d3cold_delay; 505862306a36Sopenharmony_ci if (pdev->d3cold_delay > max_delay) 505962306a36Sopenharmony_ci max_delay = pdev->d3cold_delay; 506062306a36Sopenharmony_ci } 506162306a36Sopenharmony_ci 506262306a36Sopenharmony_ci return max(min_delay, max_delay); 506362306a36Sopenharmony_ci} 506462306a36Sopenharmony_ci 506562306a36Sopenharmony_ci/** 506662306a36Sopenharmony_ci * pci_bridge_wait_for_secondary_bus - Wait for secondary bus to be accessible 506762306a36Sopenharmony_ci * @dev: PCI bridge 506862306a36Sopenharmony_ci * @reset_type: reset type in human-readable form 506962306a36Sopenharmony_ci * 507062306a36Sopenharmony_ci * Handle necessary delays before access to the devices on the secondary 507162306a36Sopenharmony_ci * side of the bridge are permitted after D3cold to D0 transition 507262306a36Sopenharmony_ci * or Conventional Reset. 507362306a36Sopenharmony_ci * 507462306a36Sopenharmony_ci * For PCIe this means the delays in PCIe 5.0 section 6.6.1. For 507562306a36Sopenharmony_ci * conventional PCI it means Tpvrh + Trhfa specified in PCI 3.0 section 507662306a36Sopenharmony_ci * 4.3.2. 507762306a36Sopenharmony_ci * 507862306a36Sopenharmony_ci * Return 0 on success or -ENOTTY if the first device on the secondary bus 507962306a36Sopenharmony_ci * failed to become accessible. 508062306a36Sopenharmony_ci */ 508162306a36Sopenharmony_ciint pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) 508262306a36Sopenharmony_ci{ 508362306a36Sopenharmony_ci struct pci_dev *child; 508462306a36Sopenharmony_ci int delay; 508562306a36Sopenharmony_ci 508662306a36Sopenharmony_ci if (pci_dev_is_disconnected(dev)) 508762306a36Sopenharmony_ci return 0; 508862306a36Sopenharmony_ci 508962306a36Sopenharmony_ci if (!pci_is_bridge(dev)) 509062306a36Sopenharmony_ci return 0; 509162306a36Sopenharmony_ci 509262306a36Sopenharmony_ci down_read(&pci_bus_sem); 509362306a36Sopenharmony_ci 509462306a36Sopenharmony_ci /* 509562306a36Sopenharmony_ci * We only deal with devices that are present currently on the bus. 509662306a36Sopenharmony_ci * For any hot-added devices the access delay is handled in pciehp 509762306a36Sopenharmony_ci * board_added(). In case of ACPI hotplug the firmware is expected 509862306a36Sopenharmony_ci * to configure the devices before OS is notified. 509962306a36Sopenharmony_ci */ 510062306a36Sopenharmony_ci if (!dev->subordinate || list_empty(&dev->subordinate->devices)) { 510162306a36Sopenharmony_ci up_read(&pci_bus_sem); 510262306a36Sopenharmony_ci return 0; 510362306a36Sopenharmony_ci } 510462306a36Sopenharmony_ci 510562306a36Sopenharmony_ci /* Take d3cold_delay requirements into account */ 510662306a36Sopenharmony_ci delay = pci_bus_max_d3cold_delay(dev->subordinate); 510762306a36Sopenharmony_ci if (!delay) { 510862306a36Sopenharmony_ci up_read(&pci_bus_sem); 510962306a36Sopenharmony_ci return 0; 511062306a36Sopenharmony_ci } 511162306a36Sopenharmony_ci 511262306a36Sopenharmony_ci child = list_first_entry(&dev->subordinate->devices, struct pci_dev, 511362306a36Sopenharmony_ci bus_list); 511462306a36Sopenharmony_ci up_read(&pci_bus_sem); 511562306a36Sopenharmony_ci 511662306a36Sopenharmony_ci /* 511762306a36Sopenharmony_ci * Conventional PCI and PCI-X we need to wait Tpvrh + Trhfa before 511862306a36Sopenharmony_ci * accessing the device after reset (that is 1000 ms + 100 ms). 511962306a36Sopenharmony_ci */ 512062306a36Sopenharmony_ci if (!pci_is_pcie(dev)) { 512162306a36Sopenharmony_ci pci_dbg(dev, "waiting %d ms for secondary bus\n", 1000 + delay); 512262306a36Sopenharmony_ci msleep(1000 + delay); 512362306a36Sopenharmony_ci return 0; 512462306a36Sopenharmony_ci } 512562306a36Sopenharmony_ci 512662306a36Sopenharmony_ci /* 512762306a36Sopenharmony_ci * For PCIe downstream and root ports that do not support speeds 512862306a36Sopenharmony_ci * greater than 5 GT/s need to wait minimum 100 ms. For higher 512962306a36Sopenharmony_ci * speeds (gen3) we need to wait first for the data link layer to 513062306a36Sopenharmony_ci * become active. 513162306a36Sopenharmony_ci * 513262306a36Sopenharmony_ci * However, 100 ms is the minimum and the PCIe spec says the 513362306a36Sopenharmony_ci * software must allow at least 1s before it can determine that the 513462306a36Sopenharmony_ci * device that did not respond is a broken device. Also device can 513562306a36Sopenharmony_ci * take longer than that to respond if it indicates so through Request 513662306a36Sopenharmony_ci * Retry Status completions. 513762306a36Sopenharmony_ci * 513862306a36Sopenharmony_ci * Therefore we wait for 100 ms and check for the device presence 513962306a36Sopenharmony_ci * until the timeout expires. 514062306a36Sopenharmony_ci */ 514162306a36Sopenharmony_ci if (!pcie_downstream_port(dev)) 514262306a36Sopenharmony_ci return 0; 514362306a36Sopenharmony_ci 514462306a36Sopenharmony_ci if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) { 514562306a36Sopenharmony_ci u16 status; 514662306a36Sopenharmony_ci 514762306a36Sopenharmony_ci pci_dbg(dev, "waiting %d ms for downstream link\n", delay); 514862306a36Sopenharmony_ci msleep(delay); 514962306a36Sopenharmony_ci 515062306a36Sopenharmony_ci if (!pci_dev_wait(child, reset_type, PCI_RESET_WAIT - delay)) 515162306a36Sopenharmony_ci return 0; 515262306a36Sopenharmony_ci 515362306a36Sopenharmony_ci /* 515462306a36Sopenharmony_ci * If the port supports active link reporting we now check 515562306a36Sopenharmony_ci * whether the link is active and if not bail out early with 515662306a36Sopenharmony_ci * the assumption that the device is not present anymore. 515762306a36Sopenharmony_ci */ 515862306a36Sopenharmony_ci if (!dev->link_active_reporting) 515962306a36Sopenharmony_ci return -ENOTTY; 516062306a36Sopenharmony_ci 516162306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status); 516262306a36Sopenharmony_ci if (!(status & PCI_EXP_LNKSTA_DLLLA)) 516362306a36Sopenharmony_ci return -ENOTTY; 516462306a36Sopenharmony_ci 516562306a36Sopenharmony_ci return pci_dev_wait(child, reset_type, 516662306a36Sopenharmony_ci PCIE_RESET_READY_POLL_MS - PCI_RESET_WAIT); 516762306a36Sopenharmony_ci } 516862306a36Sopenharmony_ci 516962306a36Sopenharmony_ci pci_dbg(dev, "waiting %d ms for downstream link, after activation\n", 517062306a36Sopenharmony_ci delay); 517162306a36Sopenharmony_ci if (!pcie_wait_for_link_delay(dev, true, delay)) { 517262306a36Sopenharmony_ci /* Did not train, no need to wait any further */ 517362306a36Sopenharmony_ci pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n"); 517462306a36Sopenharmony_ci return -ENOTTY; 517562306a36Sopenharmony_ci } 517662306a36Sopenharmony_ci 517762306a36Sopenharmony_ci return pci_dev_wait(child, reset_type, 517862306a36Sopenharmony_ci PCIE_RESET_READY_POLL_MS - delay); 517962306a36Sopenharmony_ci} 518062306a36Sopenharmony_ci 518162306a36Sopenharmony_civoid pci_reset_secondary_bus(struct pci_dev *dev) 518262306a36Sopenharmony_ci{ 518362306a36Sopenharmony_ci u16 ctrl; 518462306a36Sopenharmony_ci 518562306a36Sopenharmony_ci pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &ctrl); 518662306a36Sopenharmony_ci ctrl |= PCI_BRIDGE_CTL_BUS_RESET; 518762306a36Sopenharmony_ci pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); 518862306a36Sopenharmony_ci 518962306a36Sopenharmony_ci /* 519062306a36Sopenharmony_ci * PCI spec v3.0 7.6.4.2 requires minimum Trst of 1ms. Double 519162306a36Sopenharmony_ci * this to 2ms to ensure that we meet the minimum requirement. 519262306a36Sopenharmony_ci */ 519362306a36Sopenharmony_ci msleep(2); 519462306a36Sopenharmony_ci 519562306a36Sopenharmony_ci ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; 519662306a36Sopenharmony_ci pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl); 519762306a36Sopenharmony_ci} 519862306a36Sopenharmony_ci 519962306a36Sopenharmony_civoid __weak pcibios_reset_secondary_bus(struct pci_dev *dev) 520062306a36Sopenharmony_ci{ 520162306a36Sopenharmony_ci pci_reset_secondary_bus(dev); 520262306a36Sopenharmony_ci} 520362306a36Sopenharmony_ci 520462306a36Sopenharmony_ci/** 520562306a36Sopenharmony_ci * pci_bridge_secondary_bus_reset - Reset the secondary bus on a PCI bridge. 520662306a36Sopenharmony_ci * @dev: Bridge device 520762306a36Sopenharmony_ci * 520862306a36Sopenharmony_ci * Use the bridge control register to assert reset on the secondary bus. 520962306a36Sopenharmony_ci * Devices on the secondary bus are left in power-on state. 521062306a36Sopenharmony_ci */ 521162306a36Sopenharmony_ciint pci_bridge_secondary_bus_reset(struct pci_dev *dev) 521262306a36Sopenharmony_ci{ 521362306a36Sopenharmony_ci pcibios_reset_secondary_bus(dev); 521462306a36Sopenharmony_ci 521562306a36Sopenharmony_ci return pci_bridge_wait_for_secondary_bus(dev, "bus reset"); 521662306a36Sopenharmony_ci} 521762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_bridge_secondary_bus_reset); 521862306a36Sopenharmony_ci 521962306a36Sopenharmony_cistatic int pci_parent_bus_reset(struct pci_dev *dev, bool probe) 522062306a36Sopenharmony_ci{ 522162306a36Sopenharmony_ci struct pci_dev *pdev; 522262306a36Sopenharmony_ci 522362306a36Sopenharmony_ci if (pci_is_root_bus(dev->bus) || dev->subordinate || 522462306a36Sopenharmony_ci !dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) 522562306a36Sopenharmony_ci return -ENOTTY; 522662306a36Sopenharmony_ci 522762306a36Sopenharmony_ci list_for_each_entry(pdev, &dev->bus->devices, bus_list) 522862306a36Sopenharmony_ci if (pdev != dev) 522962306a36Sopenharmony_ci return -ENOTTY; 523062306a36Sopenharmony_ci 523162306a36Sopenharmony_ci if (probe) 523262306a36Sopenharmony_ci return 0; 523362306a36Sopenharmony_ci 523462306a36Sopenharmony_ci return pci_bridge_secondary_bus_reset(dev->bus->self); 523562306a36Sopenharmony_ci} 523662306a36Sopenharmony_ci 523762306a36Sopenharmony_cistatic int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, bool probe) 523862306a36Sopenharmony_ci{ 523962306a36Sopenharmony_ci int rc = -ENOTTY; 524062306a36Sopenharmony_ci 524162306a36Sopenharmony_ci if (!hotplug || !try_module_get(hotplug->owner)) 524262306a36Sopenharmony_ci return rc; 524362306a36Sopenharmony_ci 524462306a36Sopenharmony_ci if (hotplug->ops->reset_slot) 524562306a36Sopenharmony_ci rc = hotplug->ops->reset_slot(hotplug, probe); 524662306a36Sopenharmony_ci 524762306a36Sopenharmony_ci module_put(hotplug->owner); 524862306a36Sopenharmony_ci 524962306a36Sopenharmony_ci return rc; 525062306a36Sopenharmony_ci} 525162306a36Sopenharmony_ci 525262306a36Sopenharmony_cistatic int pci_dev_reset_slot_function(struct pci_dev *dev, bool probe) 525362306a36Sopenharmony_ci{ 525462306a36Sopenharmony_ci if (dev->multifunction || dev->subordinate || !dev->slot || 525562306a36Sopenharmony_ci dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) 525662306a36Sopenharmony_ci return -ENOTTY; 525762306a36Sopenharmony_ci 525862306a36Sopenharmony_ci return pci_reset_hotplug_slot(dev->slot->hotplug, probe); 525962306a36Sopenharmony_ci} 526062306a36Sopenharmony_ci 526162306a36Sopenharmony_cistatic int pci_reset_bus_function(struct pci_dev *dev, bool probe) 526262306a36Sopenharmony_ci{ 526362306a36Sopenharmony_ci int rc; 526462306a36Sopenharmony_ci 526562306a36Sopenharmony_ci rc = pci_dev_reset_slot_function(dev, probe); 526662306a36Sopenharmony_ci if (rc != -ENOTTY) 526762306a36Sopenharmony_ci return rc; 526862306a36Sopenharmony_ci return pci_parent_bus_reset(dev, probe); 526962306a36Sopenharmony_ci} 527062306a36Sopenharmony_ci 527162306a36Sopenharmony_civoid pci_dev_lock(struct pci_dev *dev) 527262306a36Sopenharmony_ci{ 527362306a36Sopenharmony_ci /* block PM suspend, driver probe, etc. */ 527462306a36Sopenharmony_ci device_lock(&dev->dev); 527562306a36Sopenharmony_ci pci_cfg_access_lock(dev); 527662306a36Sopenharmony_ci} 527762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_dev_lock); 527862306a36Sopenharmony_ci 527962306a36Sopenharmony_ci/* Return 1 on successful lock, 0 on contention */ 528062306a36Sopenharmony_ciint pci_dev_trylock(struct pci_dev *dev) 528162306a36Sopenharmony_ci{ 528262306a36Sopenharmony_ci if (device_trylock(&dev->dev)) { 528362306a36Sopenharmony_ci if (pci_cfg_access_trylock(dev)) 528462306a36Sopenharmony_ci return 1; 528562306a36Sopenharmony_ci device_unlock(&dev->dev); 528662306a36Sopenharmony_ci } 528762306a36Sopenharmony_ci 528862306a36Sopenharmony_ci return 0; 528962306a36Sopenharmony_ci} 529062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_dev_trylock); 529162306a36Sopenharmony_ci 529262306a36Sopenharmony_civoid pci_dev_unlock(struct pci_dev *dev) 529362306a36Sopenharmony_ci{ 529462306a36Sopenharmony_ci pci_cfg_access_unlock(dev); 529562306a36Sopenharmony_ci device_unlock(&dev->dev); 529662306a36Sopenharmony_ci} 529762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_dev_unlock); 529862306a36Sopenharmony_ci 529962306a36Sopenharmony_cistatic void pci_dev_save_and_disable(struct pci_dev *dev) 530062306a36Sopenharmony_ci{ 530162306a36Sopenharmony_ci const struct pci_error_handlers *err_handler = 530262306a36Sopenharmony_ci dev->driver ? dev->driver->err_handler : NULL; 530362306a36Sopenharmony_ci 530462306a36Sopenharmony_ci /* 530562306a36Sopenharmony_ci * dev->driver->err_handler->reset_prepare() is protected against 530662306a36Sopenharmony_ci * races with ->remove() by the device lock, which must be held by 530762306a36Sopenharmony_ci * the caller. 530862306a36Sopenharmony_ci */ 530962306a36Sopenharmony_ci if (err_handler && err_handler->reset_prepare) 531062306a36Sopenharmony_ci err_handler->reset_prepare(dev); 531162306a36Sopenharmony_ci 531262306a36Sopenharmony_ci /* 531362306a36Sopenharmony_ci * Wake-up device prior to save. PM registers default to D0 after 531462306a36Sopenharmony_ci * reset and a simple register restore doesn't reliably return 531562306a36Sopenharmony_ci * to a non-D0 state anyway. 531662306a36Sopenharmony_ci */ 531762306a36Sopenharmony_ci pci_set_power_state(dev, PCI_D0); 531862306a36Sopenharmony_ci 531962306a36Sopenharmony_ci pci_save_state(dev); 532062306a36Sopenharmony_ci /* 532162306a36Sopenharmony_ci * Disable the device by clearing the Command register, except for 532262306a36Sopenharmony_ci * INTx-disable which is set. This not only disables MMIO and I/O port 532362306a36Sopenharmony_ci * BARs, but also prevents the device from being Bus Master, preventing 532462306a36Sopenharmony_ci * DMA from the device including MSI/MSI-X interrupts. For PCI 2.3 532562306a36Sopenharmony_ci * compliant devices, INTx-disable prevents legacy interrupts. 532662306a36Sopenharmony_ci */ 532762306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); 532862306a36Sopenharmony_ci} 532962306a36Sopenharmony_ci 533062306a36Sopenharmony_cistatic void pci_dev_restore(struct pci_dev *dev) 533162306a36Sopenharmony_ci{ 533262306a36Sopenharmony_ci const struct pci_error_handlers *err_handler = 533362306a36Sopenharmony_ci dev->driver ? dev->driver->err_handler : NULL; 533462306a36Sopenharmony_ci 533562306a36Sopenharmony_ci pci_restore_state(dev); 533662306a36Sopenharmony_ci 533762306a36Sopenharmony_ci /* 533862306a36Sopenharmony_ci * dev->driver->err_handler->reset_done() is protected against 533962306a36Sopenharmony_ci * races with ->remove() by the device lock, which must be held by 534062306a36Sopenharmony_ci * the caller. 534162306a36Sopenharmony_ci */ 534262306a36Sopenharmony_ci if (err_handler && err_handler->reset_done) 534362306a36Sopenharmony_ci err_handler->reset_done(dev); 534462306a36Sopenharmony_ci} 534562306a36Sopenharmony_ci 534662306a36Sopenharmony_ci/* dev->reset_methods[] is a 0-terminated list of indices into this array */ 534762306a36Sopenharmony_cistatic const struct pci_reset_fn_method pci_reset_fn_methods[] = { 534862306a36Sopenharmony_ci { }, 534962306a36Sopenharmony_ci { pci_dev_specific_reset, .name = "device_specific" }, 535062306a36Sopenharmony_ci { pci_dev_acpi_reset, .name = "acpi" }, 535162306a36Sopenharmony_ci { pcie_reset_flr, .name = "flr" }, 535262306a36Sopenharmony_ci { pci_af_flr, .name = "af_flr" }, 535362306a36Sopenharmony_ci { pci_pm_reset, .name = "pm" }, 535462306a36Sopenharmony_ci { pci_reset_bus_function, .name = "bus" }, 535562306a36Sopenharmony_ci}; 535662306a36Sopenharmony_ci 535762306a36Sopenharmony_cistatic ssize_t reset_method_show(struct device *dev, 535862306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 535962306a36Sopenharmony_ci{ 536062306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev); 536162306a36Sopenharmony_ci ssize_t len = 0; 536262306a36Sopenharmony_ci int i, m; 536362306a36Sopenharmony_ci 536462306a36Sopenharmony_ci for (i = 0; i < PCI_NUM_RESET_METHODS; i++) { 536562306a36Sopenharmony_ci m = pdev->reset_methods[i]; 536662306a36Sopenharmony_ci if (!m) 536762306a36Sopenharmony_ci break; 536862306a36Sopenharmony_ci 536962306a36Sopenharmony_ci len += sysfs_emit_at(buf, len, "%s%s", len ? " " : "", 537062306a36Sopenharmony_ci pci_reset_fn_methods[m].name); 537162306a36Sopenharmony_ci } 537262306a36Sopenharmony_ci 537362306a36Sopenharmony_ci if (len) 537462306a36Sopenharmony_ci len += sysfs_emit_at(buf, len, "\n"); 537562306a36Sopenharmony_ci 537662306a36Sopenharmony_ci return len; 537762306a36Sopenharmony_ci} 537862306a36Sopenharmony_ci 537962306a36Sopenharmony_cistatic int reset_method_lookup(const char *name) 538062306a36Sopenharmony_ci{ 538162306a36Sopenharmony_ci int m; 538262306a36Sopenharmony_ci 538362306a36Sopenharmony_ci for (m = 1; m < PCI_NUM_RESET_METHODS; m++) { 538462306a36Sopenharmony_ci if (sysfs_streq(name, pci_reset_fn_methods[m].name)) 538562306a36Sopenharmony_ci return m; 538662306a36Sopenharmony_ci } 538762306a36Sopenharmony_ci 538862306a36Sopenharmony_ci return 0; /* not found */ 538962306a36Sopenharmony_ci} 539062306a36Sopenharmony_ci 539162306a36Sopenharmony_cistatic ssize_t reset_method_store(struct device *dev, 539262306a36Sopenharmony_ci struct device_attribute *attr, 539362306a36Sopenharmony_ci const char *buf, size_t count) 539462306a36Sopenharmony_ci{ 539562306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev); 539662306a36Sopenharmony_ci char *options, *name; 539762306a36Sopenharmony_ci int m, n; 539862306a36Sopenharmony_ci u8 reset_methods[PCI_NUM_RESET_METHODS] = { 0 }; 539962306a36Sopenharmony_ci 540062306a36Sopenharmony_ci if (sysfs_streq(buf, "")) { 540162306a36Sopenharmony_ci pdev->reset_methods[0] = 0; 540262306a36Sopenharmony_ci pci_warn(pdev, "All device reset methods disabled by user"); 540362306a36Sopenharmony_ci return count; 540462306a36Sopenharmony_ci } 540562306a36Sopenharmony_ci 540662306a36Sopenharmony_ci if (sysfs_streq(buf, "default")) { 540762306a36Sopenharmony_ci pci_init_reset_methods(pdev); 540862306a36Sopenharmony_ci return count; 540962306a36Sopenharmony_ci } 541062306a36Sopenharmony_ci 541162306a36Sopenharmony_ci options = kstrndup(buf, count, GFP_KERNEL); 541262306a36Sopenharmony_ci if (!options) 541362306a36Sopenharmony_ci return -ENOMEM; 541462306a36Sopenharmony_ci 541562306a36Sopenharmony_ci n = 0; 541662306a36Sopenharmony_ci while ((name = strsep(&options, " ")) != NULL) { 541762306a36Sopenharmony_ci if (sysfs_streq(name, "")) 541862306a36Sopenharmony_ci continue; 541962306a36Sopenharmony_ci 542062306a36Sopenharmony_ci name = strim(name); 542162306a36Sopenharmony_ci 542262306a36Sopenharmony_ci m = reset_method_lookup(name); 542362306a36Sopenharmony_ci if (!m) { 542462306a36Sopenharmony_ci pci_err(pdev, "Invalid reset method '%s'", name); 542562306a36Sopenharmony_ci goto error; 542662306a36Sopenharmony_ci } 542762306a36Sopenharmony_ci 542862306a36Sopenharmony_ci if (pci_reset_fn_methods[m].reset_fn(pdev, PCI_RESET_PROBE)) { 542962306a36Sopenharmony_ci pci_err(pdev, "Unsupported reset method '%s'", name); 543062306a36Sopenharmony_ci goto error; 543162306a36Sopenharmony_ci } 543262306a36Sopenharmony_ci 543362306a36Sopenharmony_ci if (n == PCI_NUM_RESET_METHODS - 1) { 543462306a36Sopenharmony_ci pci_err(pdev, "Too many reset methods\n"); 543562306a36Sopenharmony_ci goto error; 543662306a36Sopenharmony_ci } 543762306a36Sopenharmony_ci 543862306a36Sopenharmony_ci reset_methods[n++] = m; 543962306a36Sopenharmony_ci } 544062306a36Sopenharmony_ci 544162306a36Sopenharmony_ci reset_methods[n] = 0; 544262306a36Sopenharmony_ci 544362306a36Sopenharmony_ci /* Warn if dev-specific supported but not highest priority */ 544462306a36Sopenharmony_ci if (pci_reset_fn_methods[1].reset_fn(pdev, PCI_RESET_PROBE) == 0 && 544562306a36Sopenharmony_ci reset_methods[0] != 1) 544662306a36Sopenharmony_ci pci_warn(pdev, "Device-specific reset disabled/de-prioritized by user"); 544762306a36Sopenharmony_ci memcpy(pdev->reset_methods, reset_methods, sizeof(pdev->reset_methods)); 544862306a36Sopenharmony_ci kfree(options); 544962306a36Sopenharmony_ci return count; 545062306a36Sopenharmony_ci 545162306a36Sopenharmony_cierror: 545262306a36Sopenharmony_ci /* Leave previous methods unchanged */ 545362306a36Sopenharmony_ci kfree(options); 545462306a36Sopenharmony_ci return -EINVAL; 545562306a36Sopenharmony_ci} 545662306a36Sopenharmony_cistatic DEVICE_ATTR_RW(reset_method); 545762306a36Sopenharmony_ci 545862306a36Sopenharmony_cistatic struct attribute *pci_dev_reset_method_attrs[] = { 545962306a36Sopenharmony_ci &dev_attr_reset_method.attr, 546062306a36Sopenharmony_ci NULL, 546162306a36Sopenharmony_ci}; 546262306a36Sopenharmony_ci 546362306a36Sopenharmony_cistatic umode_t pci_dev_reset_method_attr_is_visible(struct kobject *kobj, 546462306a36Sopenharmony_ci struct attribute *a, int n) 546562306a36Sopenharmony_ci{ 546662306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 546762306a36Sopenharmony_ci 546862306a36Sopenharmony_ci if (!pci_reset_supported(pdev)) 546962306a36Sopenharmony_ci return 0; 547062306a36Sopenharmony_ci 547162306a36Sopenharmony_ci return a->mode; 547262306a36Sopenharmony_ci} 547362306a36Sopenharmony_ci 547462306a36Sopenharmony_ciconst struct attribute_group pci_dev_reset_method_attr_group = { 547562306a36Sopenharmony_ci .attrs = pci_dev_reset_method_attrs, 547662306a36Sopenharmony_ci .is_visible = pci_dev_reset_method_attr_is_visible, 547762306a36Sopenharmony_ci}; 547862306a36Sopenharmony_ci 547962306a36Sopenharmony_ci/** 548062306a36Sopenharmony_ci * __pci_reset_function_locked - reset a PCI device function while holding 548162306a36Sopenharmony_ci * the @dev mutex lock. 548262306a36Sopenharmony_ci * @dev: PCI device to reset 548362306a36Sopenharmony_ci * 548462306a36Sopenharmony_ci * Some devices allow an individual function to be reset without affecting 548562306a36Sopenharmony_ci * other functions in the same device. The PCI device must be responsive 548662306a36Sopenharmony_ci * to PCI config space in order to use this function. 548762306a36Sopenharmony_ci * 548862306a36Sopenharmony_ci * The device function is presumed to be unused and the caller is holding 548962306a36Sopenharmony_ci * the device mutex lock when this function is called. 549062306a36Sopenharmony_ci * 549162306a36Sopenharmony_ci * Resetting the device will make the contents of PCI configuration space 549262306a36Sopenharmony_ci * random, so any caller of this must be prepared to reinitialise the 549362306a36Sopenharmony_ci * device including MSI, bus mastering, BARs, decoding IO and memory spaces, 549462306a36Sopenharmony_ci * etc. 549562306a36Sopenharmony_ci * 549662306a36Sopenharmony_ci * Returns 0 if the device function was successfully reset or negative if the 549762306a36Sopenharmony_ci * device doesn't support resetting a single function. 549862306a36Sopenharmony_ci */ 549962306a36Sopenharmony_ciint __pci_reset_function_locked(struct pci_dev *dev) 550062306a36Sopenharmony_ci{ 550162306a36Sopenharmony_ci int i, m, rc; 550262306a36Sopenharmony_ci 550362306a36Sopenharmony_ci might_sleep(); 550462306a36Sopenharmony_ci 550562306a36Sopenharmony_ci /* 550662306a36Sopenharmony_ci * A reset method returns -ENOTTY if it doesn't support this device and 550762306a36Sopenharmony_ci * we should try the next method. 550862306a36Sopenharmony_ci * 550962306a36Sopenharmony_ci * If it returns 0 (success), we're finished. If it returns any other 551062306a36Sopenharmony_ci * error, we're also finished: this indicates that further reset 551162306a36Sopenharmony_ci * mechanisms might be broken on the device. 551262306a36Sopenharmony_ci */ 551362306a36Sopenharmony_ci for (i = 0; i < PCI_NUM_RESET_METHODS; i++) { 551462306a36Sopenharmony_ci m = dev->reset_methods[i]; 551562306a36Sopenharmony_ci if (!m) 551662306a36Sopenharmony_ci return -ENOTTY; 551762306a36Sopenharmony_ci 551862306a36Sopenharmony_ci rc = pci_reset_fn_methods[m].reset_fn(dev, PCI_RESET_DO_RESET); 551962306a36Sopenharmony_ci if (!rc) 552062306a36Sopenharmony_ci return 0; 552162306a36Sopenharmony_ci if (rc != -ENOTTY) 552262306a36Sopenharmony_ci return rc; 552362306a36Sopenharmony_ci } 552462306a36Sopenharmony_ci 552562306a36Sopenharmony_ci return -ENOTTY; 552662306a36Sopenharmony_ci} 552762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__pci_reset_function_locked); 552862306a36Sopenharmony_ci 552962306a36Sopenharmony_ci/** 553062306a36Sopenharmony_ci * pci_init_reset_methods - check whether device can be safely reset 553162306a36Sopenharmony_ci * and store supported reset mechanisms. 553262306a36Sopenharmony_ci * @dev: PCI device to check for reset mechanisms 553362306a36Sopenharmony_ci * 553462306a36Sopenharmony_ci * Some devices allow an individual function to be reset without affecting 553562306a36Sopenharmony_ci * other functions in the same device. The PCI device must be in D0-D3hot 553662306a36Sopenharmony_ci * state. 553762306a36Sopenharmony_ci * 553862306a36Sopenharmony_ci * Stores reset mechanisms supported by device in reset_methods byte array 553962306a36Sopenharmony_ci * which is a member of struct pci_dev. 554062306a36Sopenharmony_ci */ 554162306a36Sopenharmony_civoid pci_init_reset_methods(struct pci_dev *dev) 554262306a36Sopenharmony_ci{ 554362306a36Sopenharmony_ci int m, i, rc; 554462306a36Sopenharmony_ci 554562306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(pci_reset_fn_methods) != PCI_NUM_RESET_METHODS); 554662306a36Sopenharmony_ci 554762306a36Sopenharmony_ci might_sleep(); 554862306a36Sopenharmony_ci 554962306a36Sopenharmony_ci i = 0; 555062306a36Sopenharmony_ci for (m = 1; m < PCI_NUM_RESET_METHODS; m++) { 555162306a36Sopenharmony_ci rc = pci_reset_fn_methods[m].reset_fn(dev, PCI_RESET_PROBE); 555262306a36Sopenharmony_ci if (!rc) 555362306a36Sopenharmony_ci dev->reset_methods[i++] = m; 555462306a36Sopenharmony_ci else if (rc != -ENOTTY) 555562306a36Sopenharmony_ci break; 555662306a36Sopenharmony_ci } 555762306a36Sopenharmony_ci 555862306a36Sopenharmony_ci dev->reset_methods[i] = 0; 555962306a36Sopenharmony_ci} 556062306a36Sopenharmony_ci 556162306a36Sopenharmony_ci/** 556262306a36Sopenharmony_ci * pci_reset_function - quiesce and reset a PCI device function 556362306a36Sopenharmony_ci * @dev: PCI device to reset 556462306a36Sopenharmony_ci * 556562306a36Sopenharmony_ci * Some devices allow an individual function to be reset without affecting 556662306a36Sopenharmony_ci * other functions in the same device. The PCI device must be responsive 556762306a36Sopenharmony_ci * to PCI config space in order to use this function. 556862306a36Sopenharmony_ci * 556962306a36Sopenharmony_ci * This function does not just reset the PCI portion of a device, but 557062306a36Sopenharmony_ci * clears all the state associated with the device. This function differs 557162306a36Sopenharmony_ci * from __pci_reset_function_locked() in that it saves and restores device state 557262306a36Sopenharmony_ci * over the reset and takes the PCI device lock. 557362306a36Sopenharmony_ci * 557462306a36Sopenharmony_ci * Returns 0 if the device function was successfully reset or negative if the 557562306a36Sopenharmony_ci * device doesn't support resetting a single function. 557662306a36Sopenharmony_ci */ 557762306a36Sopenharmony_ciint pci_reset_function(struct pci_dev *dev) 557862306a36Sopenharmony_ci{ 557962306a36Sopenharmony_ci int rc; 558062306a36Sopenharmony_ci 558162306a36Sopenharmony_ci if (!pci_reset_supported(dev)) 558262306a36Sopenharmony_ci return -ENOTTY; 558362306a36Sopenharmony_ci 558462306a36Sopenharmony_ci pci_dev_lock(dev); 558562306a36Sopenharmony_ci pci_dev_save_and_disable(dev); 558662306a36Sopenharmony_ci 558762306a36Sopenharmony_ci rc = __pci_reset_function_locked(dev); 558862306a36Sopenharmony_ci 558962306a36Sopenharmony_ci pci_dev_restore(dev); 559062306a36Sopenharmony_ci pci_dev_unlock(dev); 559162306a36Sopenharmony_ci 559262306a36Sopenharmony_ci return rc; 559362306a36Sopenharmony_ci} 559462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_reset_function); 559562306a36Sopenharmony_ci 559662306a36Sopenharmony_ci/** 559762306a36Sopenharmony_ci * pci_reset_function_locked - quiesce and reset a PCI device function 559862306a36Sopenharmony_ci * @dev: PCI device to reset 559962306a36Sopenharmony_ci * 560062306a36Sopenharmony_ci * Some devices allow an individual function to be reset without affecting 560162306a36Sopenharmony_ci * other functions in the same device. The PCI device must be responsive 560262306a36Sopenharmony_ci * to PCI config space in order to use this function. 560362306a36Sopenharmony_ci * 560462306a36Sopenharmony_ci * This function does not just reset the PCI portion of a device, but 560562306a36Sopenharmony_ci * clears all the state associated with the device. This function differs 560662306a36Sopenharmony_ci * from __pci_reset_function_locked() in that it saves and restores device state 560762306a36Sopenharmony_ci * over the reset. It also differs from pci_reset_function() in that it 560862306a36Sopenharmony_ci * requires the PCI device lock to be held. 560962306a36Sopenharmony_ci * 561062306a36Sopenharmony_ci * Returns 0 if the device function was successfully reset or negative if the 561162306a36Sopenharmony_ci * device doesn't support resetting a single function. 561262306a36Sopenharmony_ci */ 561362306a36Sopenharmony_ciint pci_reset_function_locked(struct pci_dev *dev) 561462306a36Sopenharmony_ci{ 561562306a36Sopenharmony_ci int rc; 561662306a36Sopenharmony_ci 561762306a36Sopenharmony_ci if (!pci_reset_supported(dev)) 561862306a36Sopenharmony_ci return -ENOTTY; 561962306a36Sopenharmony_ci 562062306a36Sopenharmony_ci pci_dev_save_and_disable(dev); 562162306a36Sopenharmony_ci 562262306a36Sopenharmony_ci rc = __pci_reset_function_locked(dev); 562362306a36Sopenharmony_ci 562462306a36Sopenharmony_ci pci_dev_restore(dev); 562562306a36Sopenharmony_ci 562662306a36Sopenharmony_ci return rc; 562762306a36Sopenharmony_ci} 562862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_reset_function_locked); 562962306a36Sopenharmony_ci 563062306a36Sopenharmony_ci/** 563162306a36Sopenharmony_ci * pci_try_reset_function - quiesce and reset a PCI device function 563262306a36Sopenharmony_ci * @dev: PCI device to reset 563362306a36Sopenharmony_ci * 563462306a36Sopenharmony_ci * Same as above, except return -EAGAIN if unable to lock device. 563562306a36Sopenharmony_ci */ 563662306a36Sopenharmony_ciint pci_try_reset_function(struct pci_dev *dev) 563762306a36Sopenharmony_ci{ 563862306a36Sopenharmony_ci int rc; 563962306a36Sopenharmony_ci 564062306a36Sopenharmony_ci if (!pci_reset_supported(dev)) 564162306a36Sopenharmony_ci return -ENOTTY; 564262306a36Sopenharmony_ci 564362306a36Sopenharmony_ci if (!pci_dev_trylock(dev)) 564462306a36Sopenharmony_ci return -EAGAIN; 564562306a36Sopenharmony_ci 564662306a36Sopenharmony_ci pci_dev_save_and_disable(dev); 564762306a36Sopenharmony_ci rc = __pci_reset_function_locked(dev); 564862306a36Sopenharmony_ci pci_dev_restore(dev); 564962306a36Sopenharmony_ci pci_dev_unlock(dev); 565062306a36Sopenharmony_ci 565162306a36Sopenharmony_ci return rc; 565262306a36Sopenharmony_ci} 565362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_try_reset_function); 565462306a36Sopenharmony_ci 565562306a36Sopenharmony_ci/* Do any devices on or below this bus prevent a bus reset? */ 565662306a36Sopenharmony_cistatic bool pci_bus_resettable(struct pci_bus *bus) 565762306a36Sopenharmony_ci{ 565862306a36Sopenharmony_ci struct pci_dev *dev; 565962306a36Sopenharmony_ci 566062306a36Sopenharmony_ci 566162306a36Sopenharmony_ci if (bus->self && (bus->self->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)) 566262306a36Sopenharmony_ci return false; 566362306a36Sopenharmony_ci 566462306a36Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 566562306a36Sopenharmony_ci if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || 566662306a36Sopenharmony_ci (dev->subordinate && !pci_bus_resettable(dev->subordinate))) 566762306a36Sopenharmony_ci return false; 566862306a36Sopenharmony_ci } 566962306a36Sopenharmony_ci 567062306a36Sopenharmony_ci return true; 567162306a36Sopenharmony_ci} 567262306a36Sopenharmony_ci 567362306a36Sopenharmony_ci/* Lock devices from the top of the tree down */ 567462306a36Sopenharmony_cistatic void pci_bus_lock(struct pci_bus *bus) 567562306a36Sopenharmony_ci{ 567662306a36Sopenharmony_ci struct pci_dev *dev; 567762306a36Sopenharmony_ci 567862306a36Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 567962306a36Sopenharmony_ci pci_dev_lock(dev); 568062306a36Sopenharmony_ci if (dev->subordinate) 568162306a36Sopenharmony_ci pci_bus_lock(dev->subordinate); 568262306a36Sopenharmony_ci } 568362306a36Sopenharmony_ci} 568462306a36Sopenharmony_ci 568562306a36Sopenharmony_ci/* Unlock devices from the bottom of the tree up */ 568662306a36Sopenharmony_cistatic void pci_bus_unlock(struct pci_bus *bus) 568762306a36Sopenharmony_ci{ 568862306a36Sopenharmony_ci struct pci_dev *dev; 568962306a36Sopenharmony_ci 569062306a36Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 569162306a36Sopenharmony_ci if (dev->subordinate) 569262306a36Sopenharmony_ci pci_bus_unlock(dev->subordinate); 569362306a36Sopenharmony_ci pci_dev_unlock(dev); 569462306a36Sopenharmony_ci } 569562306a36Sopenharmony_ci} 569662306a36Sopenharmony_ci 569762306a36Sopenharmony_ci/* Return 1 on successful lock, 0 on contention */ 569862306a36Sopenharmony_cistatic int pci_bus_trylock(struct pci_bus *bus) 569962306a36Sopenharmony_ci{ 570062306a36Sopenharmony_ci struct pci_dev *dev; 570162306a36Sopenharmony_ci 570262306a36Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 570362306a36Sopenharmony_ci if (!pci_dev_trylock(dev)) 570462306a36Sopenharmony_ci goto unlock; 570562306a36Sopenharmony_ci if (dev->subordinate) { 570662306a36Sopenharmony_ci if (!pci_bus_trylock(dev->subordinate)) { 570762306a36Sopenharmony_ci pci_dev_unlock(dev); 570862306a36Sopenharmony_ci goto unlock; 570962306a36Sopenharmony_ci } 571062306a36Sopenharmony_ci } 571162306a36Sopenharmony_ci } 571262306a36Sopenharmony_ci return 1; 571362306a36Sopenharmony_ci 571462306a36Sopenharmony_ciunlock: 571562306a36Sopenharmony_ci list_for_each_entry_continue_reverse(dev, &bus->devices, bus_list) { 571662306a36Sopenharmony_ci if (dev->subordinate) 571762306a36Sopenharmony_ci pci_bus_unlock(dev->subordinate); 571862306a36Sopenharmony_ci pci_dev_unlock(dev); 571962306a36Sopenharmony_ci } 572062306a36Sopenharmony_ci return 0; 572162306a36Sopenharmony_ci} 572262306a36Sopenharmony_ci 572362306a36Sopenharmony_ci/* Do any devices on or below this slot prevent a bus reset? */ 572462306a36Sopenharmony_cistatic bool pci_slot_resettable(struct pci_slot *slot) 572562306a36Sopenharmony_ci{ 572662306a36Sopenharmony_ci struct pci_dev *dev; 572762306a36Sopenharmony_ci 572862306a36Sopenharmony_ci if (slot->bus->self && 572962306a36Sopenharmony_ci (slot->bus->self->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)) 573062306a36Sopenharmony_ci return false; 573162306a36Sopenharmony_ci 573262306a36Sopenharmony_ci list_for_each_entry(dev, &slot->bus->devices, bus_list) { 573362306a36Sopenharmony_ci if (!dev->slot || dev->slot != slot) 573462306a36Sopenharmony_ci continue; 573562306a36Sopenharmony_ci if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || 573662306a36Sopenharmony_ci (dev->subordinate && !pci_bus_resettable(dev->subordinate))) 573762306a36Sopenharmony_ci return false; 573862306a36Sopenharmony_ci } 573962306a36Sopenharmony_ci 574062306a36Sopenharmony_ci return true; 574162306a36Sopenharmony_ci} 574262306a36Sopenharmony_ci 574362306a36Sopenharmony_ci/* Lock devices from the top of the tree down */ 574462306a36Sopenharmony_cistatic void pci_slot_lock(struct pci_slot *slot) 574562306a36Sopenharmony_ci{ 574662306a36Sopenharmony_ci struct pci_dev *dev; 574762306a36Sopenharmony_ci 574862306a36Sopenharmony_ci list_for_each_entry(dev, &slot->bus->devices, bus_list) { 574962306a36Sopenharmony_ci if (!dev->slot || dev->slot != slot) 575062306a36Sopenharmony_ci continue; 575162306a36Sopenharmony_ci pci_dev_lock(dev); 575262306a36Sopenharmony_ci if (dev->subordinate) 575362306a36Sopenharmony_ci pci_bus_lock(dev->subordinate); 575462306a36Sopenharmony_ci } 575562306a36Sopenharmony_ci} 575662306a36Sopenharmony_ci 575762306a36Sopenharmony_ci/* Unlock devices from the bottom of the tree up */ 575862306a36Sopenharmony_cistatic void pci_slot_unlock(struct pci_slot *slot) 575962306a36Sopenharmony_ci{ 576062306a36Sopenharmony_ci struct pci_dev *dev; 576162306a36Sopenharmony_ci 576262306a36Sopenharmony_ci list_for_each_entry(dev, &slot->bus->devices, bus_list) { 576362306a36Sopenharmony_ci if (!dev->slot || dev->slot != slot) 576462306a36Sopenharmony_ci continue; 576562306a36Sopenharmony_ci if (dev->subordinate) 576662306a36Sopenharmony_ci pci_bus_unlock(dev->subordinate); 576762306a36Sopenharmony_ci pci_dev_unlock(dev); 576862306a36Sopenharmony_ci } 576962306a36Sopenharmony_ci} 577062306a36Sopenharmony_ci 577162306a36Sopenharmony_ci/* Return 1 on successful lock, 0 on contention */ 577262306a36Sopenharmony_cistatic int pci_slot_trylock(struct pci_slot *slot) 577362306a36Sopenharmony_ci{ 577462306a36Sopenharmony_ci struct pci_dev *dev; 577562306a36Sopenharmony_ci 577662306a36Sopenharmony_ci list_for_each_entry(dev, &slot->bus->devices, bus_list) { 577762306a36Sopenharmony_ci if (!dev->slot || dev->slot != slot) 577862306a36Sopenharmony_ci continue; 577962306a36Sopenharmony_ci if (!pci_dev_trylock(dev)) 578062306a36Sopenharmony_ci goto unlock; 578162306a36Sopenharmony_ci if (dev->subordinate) { 578262306a36Sopenharmony_ci if (!pci_bus_trylock(dev->subordinate)) { 578362306a36Sopenharmony_ci pci_dev_unlock(dev); 578462306a36Sopenharmony_ci goto unlock; 578562306a36Sopenharmony_ci } 578662306a36Sopenharmony_ci } 578762306a36Sopenharmony_ci } 578862306a36Sopenharmony_ci return 1; 578962306a36Sopenharmony_ci 579062306a36Sopenharmony_ciunlock: 579162306a36Sopenharmony_ci list_for_each_entry_continue_reverse(dev, 579262306a36Sopenharmony_ci &slot->bus->devices, bus_list) { 579362306a36Sopenharmony_ci if (!dev->slot || dev->slot != slot) 579462306a36Sopenharmony_ci continue; 579562306a36Sopenharmony_ci if (dev->subordinate) 579662306a36Sopenharmony_ci pci_bus_unlock(dev->subordinate); 579762306a36Sopenharmony_ci pci_dev_unlock(dev); 579862306a36Sopenharmony_ci } 579962306a36Sopenharmony_ci return 0; 580062306a36Sopenharmony_ci} 580162306a36Sopenharmony_ci 580262306a36Sopenharmony_ci/* 580362306a36Sopenharmony_ci * Save and disable devices from the top of the tree down while holding 580462306a36Sopenharmony_ci * the @dev mutex lock for the entire tree. 580562306a36Sopenharmony_ci */ 580662306a36Sopenharmony_cistatic void pci_bus_save_and_disable_locked(struct pci_bus *bus) 580762306a36Sopenharmony_ci{ 580862306a36Sopenharmony_ci struct pci_dev *dev; 580962306a36Sopenharmony_ci 581062306a36Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 581162306a36Sopenharmony_ci pci_dev_save_and_disable(dev); 581262306a36Sopenharmony_ci if (dev->subordinate) 581362306a36Sopenharmony_ci pci_bus_save_and_disable_locked(dev->subordinate); 581462306a36Sopenharmony_ci } 581562306a36Sopenharmony_ci} 581662306a36Sopenharmony_ci 581762306a36Sopenharmony_ci/* 581862306a36Sopenharmony_ci * Restore devices from top of the tree down while holding @dev mutex lock 581962306a36Sopenharmony_ci * for the entire tree. Parent bridges need to be restored before we can 582062306a36Sopenharmony_ci * get to subordinate devices. 582162306a36Sopenharmony_ci */ 582262306a36Sopenharmony_cistatic void pci_bus_restore_locked(struct pci_bus *bus) 582362306a36Sopenharmony_ci{ 582462306a36Sopenharmony_ci struct pci_dev *dev; 582562306a36Sopenharmony_ci 582662306a36Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 582762306a36Sopenharmony_ci pci_dev_restore(dev); 582862306a36Sopenharmony_ci if (dev->subordinate) 582962306a36Sopenharmony_ci pci_bus_restore_locked(dev->subordinate); 583062306a36Sopenharmony_ci } 583162306a36Sopenharmony_ci} 583262306a36Sopenharmony_ci 583362306a36Sopenharmony_ci/* 583462306a36Sopenharmony_ci * Save and disable devices from the top of the tree down while holding 583562306a36Sopenharmony_ci * the @dev mutex lock for the entire tree. 583662306a36Sopenharmony_ci */ 583762306a36Sopenharmony_cistatic void pci_slot_save_and_disable_locked(struct pci_slot *slot) 583862306a36Sopenharmony_ci{ 583962306a36Sopenharmony_ci struct pci_dev *dev; 584062306a36Sopenharmony_ci 584162306a36Sopenharmony_ci list_for_each_entry(dev, &slot->bus->devices, bus_list) { 584262306a36Sopenharmony_ci if (!dev->slot || dev->slot != slot) 584362306a36Sopenharmony_ci continue; 584462306a36Sopenharmony_ci pci_dev_save_and_disable(dev); 584562306a36Sopenharmony_ci if (dev->subordinate) 584662306a36Sopenharmony_ci pci_bus_save_and_disable_locked(dev->subordinate); 584762306a36Sopenharmony_ci } 584862306a36Sopenharmony_ci} 584962306a36Sopenharmony_ci 585062306a36Sopenharmony_ci/* 585162306a36Sopenharmony_ci * Restore devices from top of the tree down while holding @dev mutex lock 585262306a36Sopenharmony_ci * for the entire tree. Parent bridges need to be restored before we can 585362306a36Sopenharmony_ci * get to subordinate devices. 585462306a36Sopenharmony_ci */ 585562306a36Sopenharmony_cistatic void pci_slot_restore_locked(struct pci_slot *slot) 585662306a36Sopenharmony_ci{ 585762306a36Sopenharmony_ci struct pci_dev *dev; 585862306a36Sopenharmony_ci 585962306a36Sopenharmony_ci list_for_each_entry(dev, &slot->bus->devices, bus_list) { 586062306a36Sopenharmony_ci if (!dev->slot || dev->slot != slot) 586162306a36Sopenharmony_ci continue; 586262306a36Sopenharmony_ci pci_dev_restore(dev); 586362306a36Sopenharmony_ci if (dev->subordinate) 586462306a36Sopenharmony_ci pci_bus_restore_locked(dev->subordinate); 586562306a36Sopenharmony_ci } 586662306a36Sopenharmony_ci} 586762306a36Sopenharmony_ci 586862306a36Sopenharmony_cistatic int pci_slot_reset(struct pci_slot *slot, bool probe) 586962306a36Sopenharmony_ci{ 587062306a36Sopenharmony_ci int rc; 587162306a36Sopenharmony_ci 587262306a36Sopenharmony_ci if (!slot || !pci_slot_resettable(slot)) 587362306a36Sopenharmony_ci return -ENOTTY; 587462306a36Sopenharmony_ci 587562306a36Sopenharmony_ci if (!probe) 587662306a36Sopenharmony_ci pci_slot_lock(slot); 587762306a36Sopenharmony_ci 587862306a36Sopenharmony_ci might_sleep(); 587962306a36Sopenharmony_ci 588062306a36Sopenharmony_ci rc = pci_reset_hotplug_slot(slot->hotplug, probe); 588162306a36Sopenharmony_ci 588262306a36Sopenharmony_ci if (!probe) 588362306a36Sopenharmony_ci pci_slot_unlock(slot); 588462306a36Sopenharmony_ci 588562306a36Sopenharmony_ci return rc; 588662306a36Sopenharmony_ci} 588762306a36Sopenharmony_ci 588862306a36Sopenharmony_ci/** 588962306a36Sopenharmony_ci * pci_probe_reset_slot - probe whether a PCI slot can be reset 589062306a36Sopenharmony_ci * @slot: PCI slot to probe 589162306a36Sopenharmony_ci * 589262306a36Sopenharmony_ci * Return 0 if slot can be reset, negative if a slot reset is not supported. 589362306a36Sopenharmony_ci */ 589462306a36Sopenharmony_ciint pci_probe_reset_slot(struct pci_slot *slot) 589562306a36Sopenharmony_ci{ 589662306a36Sopenharmony_ci return pci_slot_reset(slot, PCI_RESET_PROBE); 589762306a36Sopenharmony_ci} 589862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_probe_reset_slot); 589962306a36Sopenharmony_ci 590062306a36Sopenharmony_ci/** 590162306a36Sopenharmony_ci * __pci_reset_slot - Try to reset a PCI slot 590262306a36Sopenharmony_ci * @slot: PCI slot to reset 590362306a36Sopenharmony_ci * 590462306a36Sopenharmony_ci * A PCI bus may host multiple slots, each slot may support a reset mechanism 590562306a36Sopenharmony_ci * independent of other slots. For instance, some slots may support slot power 590662306a36Sopenharmony_ci * control. In the case of a 1:1 bus to slot architecture, this function may 590762306a36Sopenharmony_ci * wrap the bus reset to avoid spurious slot related events such as hotplug. 590862306a36Sopenharmony_ci * Generally a slot reset should be attempted before a bus reset. All of the 590962306a36Sopenharmony_ci * function of the slot and any subordinate buses behind the slot are reset 591062306a36Sopenharmony_ci * through this function. PCI config space of all devices in the slot and 591162306a36Sopenharmony_ci * behind the slot is saved before and restored after reset. 591262306a36Sopenharmony_ci * 591362306a36Sopenharmony_ci * Same as above except return -EAGAIN if the slot cannot be locked 591462306a36Sopenharmony_ci */ 591562306a36Sopenharmony_cistatic int __pci_reset_slot(struct pci_slot *slot) 591662306a36Sopenharmony_ci{ 591762306a36Sopenharmony_ci int rc; 591862306a36Sopenharmony_ci 591962306a36Sopenharmony_ci rc = pci_slot_reset(slot, PCI_RESET_PROBE); 592062306a36Sopenharmony_ci if (rc) 592162306a36Sopenharmony_ci return rc; 592262306a36Sopenharmony_ci 592362306a36Sopenharmony_ci if (pci_slot_trylock(slot)) { 592462306a36Sopenharmony_ci pci_slot_save_and_disable_locked(slot); 592562306a36Sopenharmony_ci might_sleep(); 592662306a36Sopenharmony_ci rc = pci_reset_hotplug_slot(slot->hotplug, PCI_RESET_DO_RESET); 592762306a36Sopenharmony_ci pci_slot_restore_locked(slot); 592862306a36Sopenharmony_ci pci_slot_unlock(slot); 592962306a36Sopenharmony_ci } else 593062306a36Sopenharmony_ci rc = -EAGAIN; 593162306a36Sopenharmony_ci 593262306a36Sopenharmony_ci return rc; 593362306a36Sopenharmony_ci} 593462306a36Sopenharmony_ci 593562306a36Sopenharmony_cistatic int pci_bus_reset(struct pci_bus *bus, bool probe) 593662306a36Sopenharmony_ci{ 593762306a36Sopenharmony_ci int ret; 593862306a36Sopenharmony_ci 593962306a36Sopenharmony_ci if (!bus->self || !pci_bus_resettable(bus)) 594062306a36Sopenharmony_ci return -ENOTTY; 594162306a36Sopenharmony_ci 594262306a36Sopenharmony_ci if (probe) 594362306a36Sopenharmony_ci return 0; 594462306a36Sopenharmony_ci 594562306a36Sopenharmony_ci pci_bus_lock(bus); 594662306a36Sopenharmony_ci 594762306a36Sopenharmony_ci might_sleep(); 594862306a36Sopenharmony_ci 594962306a36Sopenharmony_ci ret = pci_bridge_secondary_bus_reset(bus->self); 595062306a36Sopenharmony_ci 595162306a36Sopenharmony_ci pci_bus_unlock(bus); 595262306a36Sopenharmony_ci 595362306a36Sopenharmony_ci return ret; 595462306a36Sopenharmony_ci} 595562306a36Sopenharmony_ci 595662306a36Sopenharmony_ci/** 595762306a36Sopenharmony_ci * pci_bus_error_reset - reset the bridge's subordinate bus 595862306a36Sopenharmony_ci * @bridge: The parent device that connects to the bus to reset 595962306a36Sopenharmony_ci * 596062306a36Sopenharmony_ci * This function will first try to reset the slots on this bus if the method is 596162306a36Sopenharmony_ci * available. If slot reset fails or is not available, this will fall back to a 596262306a36Sopenharmony_ci * secondary bus reset. 596362306a36Sopenharmony_ci */ 596462306a36Sopenharmony_ciint pci_bus_error_reset(struct pci_dev *bridge) 596562306a36Sopenharmony_ci{ 596662306a36Sopenharmony_ci struct pci_bus *bus = bridge->subordinate; 596762306a36Sopenharmony_ci struct pci_slot *slot; 596862306a36Sopenharmony_ci 596962306a36Sopenharmony_ci if (!bus) 597062306a36Sopenharmony_ci return -ENOTTY; 597162306a36Sopenharmony_ci 597262306a36Sopenharmony_ci mutex_lock(&pci_slot_mutex); 597362306a36Sopenharmony_ci if (list_empty(&bus->slots)) 597462306a36Sopenharmony_ci goto bus_reset; 597562306a36Sopenharmony_ci 597662306a36Sopenharmony_ci list_for_each_entry(slot, &bus->slots, list) 597762306a36Sopenharmony_ci if (pci_probe_reset_slot(slot)) 597862306a36Sopenharmony_ci goto bus_reset; 597962306a36Sopenharmony_ci 598062306a36Sopenharmony_ci list_for_each_entry(slot, &bus->slots, list) 598162306a36Sopenharmony_ci if (pci_slot_reset(slot, PCI_RESET_DO_RESET)) 598262306a36Sopenharmony_ci goto bus_reset; 598362306a36Sopenharmony_ci 598462306a36Sopenharmony_ci mutex_unlock(&pci_slot_mutex); 598562306a36Sopenharmony_ci return 0; 598662306a36Sopenharmony_cibus_reset: 598762306a36Sopenharmony_ci mutex_unlock(&pci_slot_mutex); 598862306a36Sopenharmony_ci return pci_bus_reset(bridge->subordinate, PCI_RESET_DO_RESET); 598962306a36Sopenharmony_ci} 599062306a36Sopenharmony_ci 599162306a36Sopenharmony_ci/** 599262306a36Sopenharmony_ci * pci_probe_reset_bus - probe whether a PCI bus can be reset 599362306a36Sopenharmony_ci * @bus: PCI bus to probe 599462306a36Sopenharmony_ci * 599562306a36Sopenharmony_ci * Return 0 if bus can be reset, negative if a bus reset is not supported. 599662306a36Sopenharmony_ci */ 599762306a36Sopenharmony_ciint pci_probe_reset_bus(struct pci_bus *bus) 599862306a36Sopenharmony_ci{ 599962306a36Sopenharmony_ci return pci_bus_reset(bus, PCI_RESET_PROBE); 600062306a36Sopenharmony_ci} 600162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_probe_reset_bus); 600262306a36Sopenharmony_ci 600362306a36Sopenharmony_ci/** 600462306a36Sopenharmony_ci * __pci_reset_bus - Try to reset a PCI bus 600562306a36Sopenharmony_ci * @bus: top level PCI bus to reset 600662306a36Sopenharmony_ci * 600762306a36Sopenharmony_ci * Same as above except return -EAGAIN if the bus cannot be locked 600862306a36Sopenharmony_ci */ 600962306a36Sopenharmony_cistatic int __pci_reset_bus(struct pci_bus *bus) 601062306a36Sopenharmony_ci{ 601162306a36Sopenharmony_ci int rc; 601262306a36Sopenharmony_ci 601362306a36Sopenharmony_ci rc = pci_bus_reset(bus, PCI_RESET_PROBE); 601462306a36Sopenharmony_ci if (rc) 601562306a36Sopenharmony_ci return rc; 601662306a36Sopenharmony_ci 601762306a36Sopenharmony_ci if (pci_bus_trylock(bus)) { 601862306a36Sopenharmony_ci pci_bus_save_and_disable_locked(bus); 601962306a36Sopenharmony_ci might_sleep(); 602062306a36Sopenharmony_ci rc = pci_bridge_secondary_bus_reset(bus->self); 602162306a36Sopenharmony_ci pci_bus_restore_locked(bus); 602262306a36Sopenharmony_ci pci_bus_unlock(bus); 602362306a36Sopenharmony_ci } else 602462306a36Sopenharmony_ci rc = -EAGAIN; 602562306a36Sopenharmony_ci 602662306a36Sopenharmony_ci return rc; 602762306a36Sopenharmony_ci} 602862306a36Sopenharmony_ci 602962306a36Sopenharmony_ci/** 603062306a36Sopenharmony_ci * pci_reset_bus - Try to reset a PCI bus 603162306a36Sopenharmony_ci * @pdev: top level PCI device to reset via slot/bus 603262306a36Sopenharmony_ci * 603362306a36Sopenharmony_ci * Same as above except return -EAGAIN if the bus cannot be locked 603462306a36Sopenharmony_ci */ 603562306a36Sopenharmony_ciint pci_reset_bus(struct pci_dev *pdev) 603662306a36Sopenharmony_ci{ 603762306a36Sopenharmony_ci return (!pci_probe_reset_slot(pdev->slot)) ? 603862306a36Sopenharmony_ci __pci_reset_slot(pdev->slot) : __pci_reset_bus(pdev->bus); 603962306a36Sopenharmony_ci} 604062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_reset_bus); 604162306a36Sopenharmony_ci 604262306a36Sopenharmony_ci/** 604362306a36Sopenharmony_ci * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count 604462306a36Sopenharmony_ci * @dev: PCI device to query 604562306a36Sopenharmony_ci * 604662306a36Sopenharmony_ci * Returns mmrbc: maximum designed memory read count in bytes or 604762306a36Sopenharmony_ci * appropriate error value. 604862306a36Sopenharmony_ci */ 604962306a36Sopenharmony_ciint pcix_get_max_mmrbc(struct pci_dev *dev) 605062306a36Sopenharmony_ci{ 605162306a36Sopenharmony_ci int cap; 605262306a36Sopenharmony_ci u32 stat; 605362306a36Sopenharmony_ci 605462306a36Sopenharmony_ci cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); 605562306a36Sopenharmony_ci if (!cap) 605662306a36Sopenharmony_ci return -EINVAL; 605762306a36Sopenharmony_ci 605862306a36Sopenharmony_ci if (pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat)) 605962306a36Sopenharmony_ci return -EINVAL; 606062306a36Sopenharmony_ci 606162306a36Sopenharmony_ci return 512 << ((stat & PCI_X_STATUS_MAX_READ) >> 21); 606262306a36Sopenharmony_ci} 606362306a36Sopenharmony_ciEXPORT_SYMBOL(pcix_get_max_mmrbc); 606462306a36Sopenharmony_ci 606562306a36Sopenharmony_ci/** 606662306a36Sopenharmony_ci * pcix_get_mmrbc - get PCI-X maximum memory read byte count 606762306a36Sopenharmony_ci * @dev: PCI device to query 606862306a36Sopenharmony_ci * 606962306a36Sopenharmony_ci * Returns mmrbc: maximum memory read count in bytes or appropriate error 607062306a36Sopenharmony_ci * value. 607162306a36Sopenharmony_ci */ 607262306a36Sopenharmony_ciint pcix_get_mmrbc(struct pci_dev *dev) 607362306a36Sopenharmony_ci{ 607462306a36Sopenharmony_ci int cap; 607562306a36Sopenharmony_ci u16 cmd; 607662306a36Sopenharmony_ci 607762306a36Sopenharmony_ci cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); 607862306a36Sopenharmony_ci if (!cap) 607962306a36Sopenharmony_ci return -EINVAL; 608062306a36Sopenharmony_ci 608162306a36Sopenharmony_ci if (pci_read_config_word(dev, cap + PCI_X_CMD, &cmd)) 608262306a36Sopenharmony_ci return -EINVAL; 608362306a36Sopenharmony_ci 608462306a36Sopenharmony_ci return 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2); 608562306a36Sopenharmony_ci} 608662306a36Sopenharmony_ciEXPORT_SYMBOL(pcix_get_mmrbc); 608762306a36Sopenharmony_ci 608862306a36Sopenharmony_ci/** 608962306a36Sopenharmony_ci * pcix_set_mmrbc - set PCI-X maximum memory read byte count 609062306a36Sopenharmony_ci * @dev: PCI device to query 609162306a36Sopenharmony_ci * @mmrbc: maximum memory read count in bytes 609262306a36Sopenharmony_ci * valid values are 512, 1024, 2048, 4096 609362306a36Sopenharmony_ci * 609462306a36Sopenharmony_ci * If possible sets maximum memory read byte count, some bridges have errata 609562306a36Sopenharmony_ci * that prevent this. 609662306a36Sopenharmony_ci */ 609762306a36Sopenharmony_ciint pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) 609862306a36Sopenharmony_ci{ 609962306a36Sopenharmony_ci int cap; 610062306a36Sopenharmony_ci u32 stat, v, o; 610162306a36Sopenharmony_ci u16 cmd; 610262306a36Sopenharmony_ci 610362306a36Sopenharmony_ci if (mmrbc < 512 || mmrbc > 4096 || !is_power_of_2(mmrbc)) 610462306a36Sopenharmony_ci return -EINVAL; 610562306a36Sopenharmony_ci 610662306a36Sopenharmony_ci v = ffs(mmrbc) - 10; 610762306a36Sopenharmony_ci 610862306a36Sopenharmony_ci cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); 610962306a36Sopenharmony_ci if (!cap) 611062306a36Sopenharmony_ci return -EINVAL; 611162306a36Sopenharmony_ci 611262306a36Sopenharmony_ci if (pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat)) 611362306a36Sopenharmony_ci return -EINVAL; 611462306a36Sopenharmony_ci 611562306a36Sopenharmony_ci if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21) 611662306a36Sopenharmony_ci return -E2BIG; 611762306a36Sopenharmony_ci 611862306a36Sopenharmony_ci if (pci_read_config_word(dev, cap + PCI_X_CMD, &cmd)) 611962306a36Sopenharmony_ci return -EINVAL; 612062306a36Sopenharmony_ci 612162306a36Sopenharmony_ci o = (cmd & PCI_X_CMD_MAX_READ) >> 2; 612262306a36Sopenharmony_ci if (o != v) { 612362306a36Sopenharmony_ci if (v > o && (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC)) 612462306a36Sopenharmony_ci return -EIO; 612562306a36Sopenharmony_ci 612662306a36Sopenharmony_ci cmd &= ~PCI_X_CMD_MAX_READ; 612762306a36Sopenharmony_ci cmd |= v << 2; 612862306a36Sopenharmony_ci if (pci_write_config_word(dev, cap + PCI_X_CMD, cmd)) 612962306a36Sopenharmony_ci return -EIO; 613062306a36Sopenharmony_ci } 613162306a36Sopenharmony_ci return 0; 613262306a36Sopenharmony_ci} 613362306a36Sopenharmony_ciEXPORT_SYMBOL(pcix_set_mmrbc); 613462306a36Sopenharmony_ci 613562306a36Sopenharmony_ci/** 613662306a36Sopenharmony_ci * pcie_get_readrq - get PCI Express read request size 613762306a36Sopenharmony_ci * @dev: PCI device to query 613862306a36Sopenharmony_ci * 613962306a36Sopenharmony_ci * Returns maximum memory read request in bytes or appropriate error value. 614062306a36Sopenharmony_ci */ 614162306a36Sopenharmony_ciint pcie_get_readrq(struct pci_dev *dev) 614262306a36Sopenharmony_ci{ 614362306a36Sopenharmony_ci u16 ctl; 614462306a36Sopenharmony_ci 614562306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); 614662306a36Sopenharmony_ci 614762306a36Sopenharmony_ci return 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12); 614862306a36Sopenharmony_ci} 614962306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_get_readrq); 615062306a36Sopenharmony_ci 615162306a36Sopenharmony_ci/** 615262306a36Sopenharmony_ci * pcie_set_readrq - set PCI Express maximum memory read request 615362306a36Sopenharmony_ci * @dev: PCI device to query 615462306a36Sopenharmony_ci * @rq: maximum memory read count in bytes 615562306a36Sopenharmony_ci * valid values are 128, 256, 512, 1024, 2048, 4096 615662306a36Sopenharmony_ci * 615762306a36Sopenharmony_ci * If possible sets maximum memory read request in bytes 615862306a36Sopenharmony_ci */ 615962306a36Sopenharmony_ciint pcie_set_readrq(struct pci_dev *dev, int rq) 616062306a36Sopenharmony_ci{ 616162306a36Sopenharmony_ci u16 v; 616262306a36Sopenharmony_ci int ret; 616362306a36Sopenharmony_ci struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus); 616462306a36Sopenharmony_ci 616562306a36Sopenharmony_ci if (rq < 128 || rq > 4096 || !is_power_of_2(rq)) 616662306a36Sopenharmony_ci return -EINVAL; 616762306a36Sopenharmony_ci 616862306a36Sopenharmony_ci /* 616962306a36Sopenharmony_ci * If using the "performance" PCIe config, we clamp the read rq 617062306a36Sopenharmony_ci * size to the max packet size to keep the host bridge from 617162306a36Sopenharmony_ci * generating requests larger than we can cope with. 617262306a36Sopenharmony_ci */ 617362306a36Sopenharmony_ci if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { 617462306a36Sopenharmony_ci int mps = pcie_get_mps(dev); 617562306a36Sopenharmony_ci 617662306a36Sopenharmony_ci if (mps < rq) 617762306a36Sopenharmony_ci rq = mps; 617862306a36Sopenharmony_ci } 617962306a36Sopenharmony_ci 618062306a36Sopenharmony_ci v = (ffs(rq) - 8) << 12; 618162306a36Sopenharmony_ci 618262306a36Sopenharmony_ci if (bridge->no_inc_mrrs) { 618362306a36Sopenharmony_ci int max_mrrs = pcie_get_readrq(dev); 618462306a36Sopenharmony_ci 618562306a36Sopenharmony_ci if (rq > max_mrrs) { 618662306a36Sopenharmony_ci pci_info(dev, "can't set Max_Read_Request_Size to %d; max is %d\n", rq, max_mrrs); 618762306a36Sopenharmony_ci return -EINVAL; 618862306a36Sopenharmony_ci } 618962306a36Sopenharmony_ci } 619062306a36Sopenharmony_ci 619162306a36Sopenharmony_ci ret = pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, 619262306a36Sopenharmony_ci PCI_EXP_DEVCTL_READRQ, v); 619362306a36Sopenharmony_ci 619462306a36Sopenharmony_ci return pcibios_err_to_errno(ret); 619562306a36Sopenharmony_ci} 619662306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_set_readrq); 619762306a36Sopenharmony_ci 619862306a36Sopenharmony_ci/** 619962306a36Sopenharmony_ci * pcie_get_mps - get PCI Express maximum payload size 620062306a36Sopenharmony_ci * @dev: PCI device to query 620162306a36Sopenharmony_ci * 620262306a36Sopenharmony_ci * Returns maximum payload size in bytes 620362306a36Sopenharmony_ci */ 620462306a36Sopenharmony_ciint pcie_get_mps(struct pci_dev *dev) 620562306a36Sopenharmony_ci{ 620662306a36Sopenharmony_ci u16 ctl; 620762306a36Sopenharmony_ci 620862306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); 620962306a36Sopenharmony_ci 621062306a36Sopenharmony_ci return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); 621162306a36Sopenharmony_ci} 621262306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_get_mps); 621362306a36Sopenharmony_ci 621462306a36Sopenharmony_ci/** 621562306a36Sopenharmony_ci * pcie_set_mps - set PCI Express maximum payload size 621662306a36Sopenharmony_ci * @dev: PCI device to query 621762306a36Sopenharmony_ci * @mps: maximum payload size in bytes 621862306a36Sopenharmony_ci * valid values are 128, 256, 512, 1024, 2048, 4096 621962306a36Sopenharmony_ci * 622062306a36Sopenharmony_ci * If possible sets maximum payload size 622162306a36Sopenharmony_ci */ 622262306a36Sopenharmony_ciint pcie_set_mps(struct pci_dev *dev, int mps) 622362306a36Sopenharmony_ci{ 622462306a36Sopenharmony_ci u16 v; 622562306a36Sopenharmony_ci int ret; 622662306a36Sopenharmony_ci 622762306a36Sopenharmony_ci if (mps < 128 || mps > 4096 || !is_power_of_2(mps)) 622862306a36Sopenharmony_ci return -EINVAL; 622962306a36Sopenharmony_ci 623062306a36Sopenharmony_ci v = ffs(mps) - 8; 623162306a36Sopenharmony_ci if (v > dev->pcie_mpss) 623262306a36Sopenharmony_ci return -EINVAL; 623362306a36Sopenharmony_ci v <<= 5; 623462306a36Sopenharmony_ci 623562306a36Sopenharmony_ci ret = pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, 623662306a36Sopenharmony_ci PCI_EXP_DEVCTL_PAYLOAD, v); 623762306a36Sopenharmony_ci 623862306a36Sopenharmony_ci return pcibios_err_to_errno(ret); 623962306a36Sopenharmony_ci} 624062306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_set_mps); 624162306a36Sopenharmony_ci 624262306a36Sopenharmony_ci/** 624362306a36Sopenharmony_ci * pcie_bandwidth_available - determine minimum link settings of a PCIe 624462306a36Sopenharmony_ci * device and its bandwidth limitation 624562306a36Sopenharmony_ci * @dev: PCI device to query 624662306a36Sopenharmony_ci * @limiting_dev: storage for device causing the bandwidth limitation 624762306a36Sopenharmony_ci * @speed: storage for speed of limiting device 624862306a36Sopenharmony_ci * @width: storage for width of limiting device 624962306a36Sopenharmony_ci * 625062306a36Sopenharmony_ci * Walk up the PCI device chain and find the point where the minimum 625162306a36Sopenharmony_ci * bandwidth is available. Return the bandwidth available there and (if 625262306a36Sopenharmony_ci * limiting_dev, speed, and width pointers are supplied) information about 625362306a36Sopenharmony_ci * that point. The bandwidth returned is in Mb/s, i.e., megabits/second of 625462306a36Sopenharmony_ci * raw bandwidth. 625562306a36Sopenharmony_ci */ 625662306a36Sopenharmony_ciu32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev, 625762306a36Sopenharmony_ci enum pci_bus_speed *speed, 625862306a36Sopenharmony_ci enum pcie_link_width *width) 625962306a36Sopenharmony_ci{ 626062306a36Sopenharmony_ci u16 lnksta; 626162306a36Sopenharmony_ci enum pci_bus_speed next_speed; 626262306a36Sopenharmony_ci enum pcie_link_width next_width; 626362306a36Sopenharmony_ci u32 bw, next_bw; 626462306a36Sopenharmony_ci 626562306a36Sopenharmony_ci if (speed) 626662306a36Sopenharmony_ci *speed = PCI_SPEED_UNKNOWN; 626762306a36Sopenharmony_ci if (width) 626862306a36Sopenharmony_ci *width = PCIE_LNK_WIDTH_UNKNOWN; 626962306a36Sopenharmony_ci 627062306a36Sopenharmony_ci bw = 0; 627162306a36Sopenharmony_ci 627262306a36Sopenharmony_ci while (dev) { 627362306a36Sopenharmony_ci pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); 627462306a36Sopenharmony_ci 627562306a36Sopenharmony_ci next_speed = pcie_link_speed[lnksta & PCI_EXP_LNKSTA_CLS]; 627662306a36Sopenharmony_ci next_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta); 627762306a36Sopenharmony_ci 627862306a36Sopenharmony_ci next_bw = next_width * PCIE_SPEED2MBS_ENC(next_speed); 627962306a36Sopenharmony_ci 628062306a36Sopenharmony_ci /* Check if current device limits the total bandwidth */ 628162306a36Sopenharmony_ci if (!bw || next_bw <= bw) { 628262306a36Sopenharmony_ci bw = next_bw; 628362306a36Sopenharmony_ci 628462306a36Sopenharmony_ci if (limiting_dev) 628562306a36Sopenharmony_ci *limiting_dev = dev; 628662306a36Sopenharmony_ci if (speed) 628762306a36Sopenharmony_ci *speed = next_speed; 628862306a36Sopenharmony_ci if (width) 628962306a36Sopenharmony_ci *width = next_width; 629062306a36Sopenharmony_ci } 629162306a36Sopenharmony_ci 629262306a36Sopenharmony_ci dev = pci_upstream_bridge(dev); 629362306a36Sopenharmony_ci } 629462306a36Sopenharmony_ci 629562306a36Sopenharmony_ci return bw; 629662306a36Sopenharmony_ci} 629762306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_bandwidth_available); 629862306a36Sopenharmony_ci 629962306a36Sopenharmony_ci/** 630062306a36Sopenharmony_ci * pcie_get_speed_cap - query for the PCI device's link speed capability 630162306a36Sopenharmony_ci * @dev: PCI device to query 630262306a36Sopenharmony_ci * 630362306a36Sopenharmony_ci * Query the PCI device speed capability. Return the maximum link speed 630462306a36Sopenharmony_ci * supported by the device. 630562306a36Sopenharmony_ci */ 630662306a36Sopenharmony_cienum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev) 630762306a36Sopenharmony_ci{ 630862306a36Sopenharmony_ci u32 lnkcap2, lnkcap; 630962306a36Sopenharmony_ci 631062306a36Sopenharmony_ci /* 631162306a36Sopenharmony_ci * Link Capabilities 2 was added in PCIe r3.0, sec 7.8.18. The 631262306a36Sopenharmony_ci * implementation note there recommends using the Supported Link 631362306a36Sopenharmony_ci * Speeds Vector in Link Capabilities 2 when supported. 631462306a36Sopenharmony_ci * 631562306a36Sopenharmony_ci * Without Link Capabilities 2, i.e., prior to PCIe r3.0, software 631662306a36Sopenharmony_ci * should use the Supported Link Speeds field in Link Capabilities, 631762306a36Sopenharmony_ci * where only 2.5 GT/s and 5.0 GT/s speeds were defined. 631862306a36Sopenharmony_ci */ 631962306a36Sopenharmony_ci pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2); 632062306a36Sopenharmony_ci 632162306a36Sopenharmony_ci /* PCIe r3.0-compliant */ 632262306a36Sopenharmony_ci if (lnkcap2) 632362306a36Sopenharmony_ci return PCIE_LNKCAP2_SLS2SPEED(lnkcap2); 632462306a36Sopenharmony_ci 632562306a36Sopenharmony_ci pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); 632662306a36Sopenharmony_ci if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB) 632762306a36Sopenharmony_ci return PCIE_SPEED_5_0GT; 632862306a36Sopenharmony_ci else if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_2_5GB) 632962306a36Sopenharmony_ci return PCIE_SPEED_2_5GT; 633062306a36Sopenharmony_ci 633162306a36Sopenharmony_ci return PCI_SPEED_UNKNOWN; 633262306a36Sopenharmony_ci} 633362306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_get_speed_cap); 633462306a36Sopenharmony_ci 633562306a36Sopenharmony_ci/** 633662306a36Sopenharmony_ci * pcie_get_width_cap - query for the PCI device's link width capability 633762306a36Sopenharmony_ci * @dev: PCI device to query 633862306a36Sopenharmony_ci * 633962306a36Sopenharmony_ci * Query the PCI device width capability. Return the maximum link width 634062306a36Sopenharmony_ci * supported by the device. 634162306a36Sopenharmony_ci */ 634262306a36Sopenharmony_cienum pcie_link_width pcie_get_width_cap(struct pci_dev *dev) 634362306a36Sopenharmony_ci{ 634462306a36Sopenharmony_ci u32 lnkcap; 634562306a36Sopenharmony_ci 634662306a36Sopenharmony_ci pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); 634762306a36Sopenharmony_ci if (lnkcap) 634862306a36Sopenharmony_ci return FIELD_GET(PCI_EXP_LNKCAP_MLW, lnkcap); 634962306a36Sopenharmony_ci 635062306a36Sopenharmony_ci return PCIE_LNK_WIDTH_UNKNOWN; 635162306a36Sopenharmony_ci} 635262306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_get_width_cap); 635362306a36Sopenharmony_ci 635462306a36Sopenharmony_ci/** 635562306a36Sopenharmony_ci * pcie_bandwidth_capable - calculate a PCI device's link bandwidth capability 635662306a36Sopenharmony_ci * @dev: PCI device 635762306a36Sopenharmony_ci * @speed: storage for link speed 635862306a36Sopenharmony_ci * @width: storage for link width 635962306a36Sopenharmony_ci * 636062306a36Sopenharmony_ci * Calculate a PCI device's link bandwidth by querying for its link speed 636162306a36Sopenharmony_ci * and width, multiplying them, and applying encoding overhead. The result 636262306a36Sopenharmony_ci * is in Mb/s, i.e., megabits/second of raw bandwidth. 636362306a36Sopenharmony_ci */ 636462306a36Sopenharmony_ciu32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed, 636562306a36Sopenharmony_ci enum pcie_link_width *width) 636662306a36Sopenharmony_ci{ 636762306a36Sopenharmony_ci *speed = pcie_get_speed_cap(dev); 636862306a36Sopenharmony_ci *width = pcie_get_width_cap(dev); 636962306a36Sopenharmony_ci 637062306a36Sopenharmony_ci if (*speed == PCI_SPEED_UNKNOWN || *width == PCIE_LNK_WIDTH_UNKNOWN) 637162306a36Sopenharmony_ci return 0; 637262306a36Sopenharmony_ci 637362306a36Sopenharmony_ci return *width * PCIE_SPEED2MBS_ENC(*speed); 637462306a36Sopenharmony_ci} 637562306a36Sopenharmony_ci 637662306a36Sopenharmony_ci/** 637762306a36Sopenharmony_ci * __pcie_print_link_status - Report the PCI device's link speed and width 637862306a36Sopenharmony_ci * @dev: PCI device to query 637962306a36Sopenharmony_ci * @verbose: Print info even when enough bandwidth is available 638062306a36Sopenharmony_ci * 638162306a36Sopenharmony_ci * If the available bandwidth at the device is less than the device is 638262306a36Sopenharmony_ci * capable of, report the device's maximum possible bandwidth and the 638362306a36Sopenharmony_ci * upstream link that limits its performance. If @verbose, always print 638462306a36Sopenharmony_ci * the available bandwidth, even if the device isn't constrained. 638562306a36Sopenharmony_ci */ 638662306a36Sopenharmony_civoid __pcie_print_link_status(struct pci_dev *dev, bool verbose) 638762306a36Sopenharmony_ci{ 638862306a36Sopenharmony_ci enum pcie_link_width width, width_cap; 638962306a36Sopenharmony_ci enum pci_bus_speed speed, speed_cap; 639062306a36Sopenharmony_ci struct pci_dev *limiting_dev = NULL; 639162306a36Sopenharmony_ci u32 bw_avail, bw_cap; 639262306a36Sopenharmony_ci 639362306a36Sopenharmony_ci bw_cap = pcie_bandwidth_capable(dev, &speed_cap, &width_cap); 639462306a36Sopenharmony_ci bw_avail = pcie_bandwidth_available(dev, &limiting_dev, &speed, &width); 639562306a36Sopenharmony_ci 639662306a36Sopenharmony_ci if (bw_avail >= bw_cap && verbose) 639762306a36Sopenharmony_ci pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth (%s x%d link)\n", 639862306a36Sopenharmony_ci bw_cap / 1000, bw_cap % 1000, 639962306a36Sopenharmony_ci pci_speed_string(speed_cap), width_cap); 640062306a36Sopenharmony_ci else if (bw_avail < bw_cap) 640162306a36Sopenharmony_ci pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth, limited by %s x%d link at %s (capable of %u.%03u Gb/s with %s x%d link)\n", 640262306a36Sopenharmony_ci bw_avail / 1000, bw_avail % 1000, 640362306a36Sopenharmony_ci pci_speed_string(speed), width, 640462306a36Sopenharmony_ci limiting_dev ? pci_name(limiting_dev) : "<unknown>", 640562306a36Sopenharmony_ci bw_cap / 1000, bw_cap % 1000, 640662306a36Sopenharmony_ci pci_speed_string(speed_cap), width_cap); 640762306a36Sopenharmony_ci} 640862306a36Sopenharmony_ci 640962306a36Sopenharmony_ci/** 641062306a36Sopenharmony_ci * pcie_print_link_status - Report the PCI device's link speed and width 641162306a36Sopenharmony_ci * @dev: PCI device to query 641262306a36Sopenharmony_ci * 641362306a36Sopenharmony_ci * Report the available bandwidth at the device. 641462306a36Sopenharmony_ci */ 641562306a36Sopenharmony_civoid pcie_print_link_status(struct pci_dev *dev) 641662306a36Sopenharmony_ci{ 641762306a36Sopenharmony_ci __pcie_print_link_status(dev, true); 641862306a36Sopenharmony_ci} 641962306a36Sopenharmony_ciEXPORT_SYMBOL(pcie_print_link_status); 642062306a36Sopenharmony_ci 642162306a36Sopenharmony_ci/** 642262306a36Sopenharmony_ci * pci_select_bars - Make BAR mask from the type of resource 642362306a36Sopenharmony_ci * @dev: the PCI device for which BAR mask is made 642462306a36Sopenharmony_ci * @flags: resource type mask to be selected 642562306a36Sopenharmony_ci * 642662306a36Sopenharmony_ci * This helper routine makes bar mask from the type of resource. 642762306a36Sopenharmony_ci */ 642862306a36Sopenharmony_ciint pci_select_bars(struct pci_dev *dev, unsigned long flags) 642962306a36Sopenharmony_ci{ 643062306a36Sopenharmony_ci int i, bars = 0; 643162306a36Sopenharmony_ci for (i = 0; i < PCI_NUM_RESOURCES; i++) 643262306a36Sopenharmony_ci if (pci_resource_flags(dev, i) & flags) 643362306a36Sopenharmony_ci bars |= (1 << i); 643462306a36Sopenharmony_ci return bars; 643562306a36Sopenharmony_ci} 643662306a36Sopenharmony_ciEXPORT_SYMBOL(pci_select_bars); 643762306a36Sopenharmony_ci 643862306a36Sopenharmony_ci/* Some architectures require additional programming to enable VGA */ 643962306a36Sopenharmony_cistatic arch_set_vga_state_t arch_set_vga_state; 644062306a36Sopenharmony_ci 644162306a36Sopenharmony_civoid __init pci_register_set_vga_state(arch_set_vga_state_t func) 644262306a36Sopenharmony_ci{ 644362306a36Sopenharmony_ci arch_set_vga_state = func; /* NULL disables */ 644462306a36Sopenharmony_ci} 644562306a36Sopenharmony_ci 644662306a36Sopenharmony_cistatic int pci_set_vga_state_arch(struct pci_dev *dev, bool decode, 644762306a36Sopenharmony_ci unsigned int command_bits, u32 flags) 644862306a36Sopenharmony_ci{ 644962306a36Sopenharmony_ci if (arch_set_vga_state) 645062306a36Sopenharmony_ci return arch_set_vga_state(dev, decode, command_bits, 645162306a36Sopenharmony_ci flags); 645262306a36Sopenharmony_ci return 0; 645362306a36Sopenharmony_ci} 645462306a36Sopenharmony_ci 645562306a36Sopenharmony_ci/** 645662306a36Sopenharmony_ci * pci_set_vga_state - set VGA decode state on device and parents if requested 645762306a36Sopenharmony_ci * @dev: the PCI device 645862306a36Sopenharmony_ci * @decode: true = enable decoding, false = disable decoding 645962306a36Sopenharmony_ci * @command_bits: PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY 646062306a36Sopenharmony_ci * @flags: traverse ancestors and change bridges 646162306a36Sopenharmony_ci * CHANGE_BRIDGE_ONLY / CHANGE_BRIDGE 646262306a36Sopenharmony_ci */ 646362306a36Sopenharmony_ciint pci_set_vga_state(struct pci_dev *dev, bool decode, 646462306a36Sopenharmony_ci unsigned int command_bits, u32 flags) 646562306a36Sopenharmony_ci{ 646662306a36Sopenharmony_ci struct pci_bus *bus; 646762306a36Sopenharmony_ci struct pci_dev *bridge; 646862306a36Sopenharmony_ci u16 cmd; 646962306a36Sopenharmony_ci int rc; 647062306a36Sopenharmony_ci 647162306a36Sopenharmony_ci WARN_ON((flags & PCI_VGA_STATE_CHANGE_DECODES) && (command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY))); 647262306a36Sopenharmony_ci 647362306a36Sopenharmony_ci /* ARCH specific VGA enables */ 647462306a36Sopenharmony_ci rc = pci_set_vga_state_arch(dev, decode, command_bits, flags); 647562306a36Sopenharmony_ci if (rc) 647662306a36Sopenharmony_ci return rc; 647762306a36Sopenharmony_ci 647862306a36Sopenharmony_ci if (flags & PCI_VGA_STATE_CHANGE_DECODES) { 647962306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &cmd); 648062306a36Sopenharmony_ci if (decode) 648162306a36Sopenharmony_ci cmd |= command_bits; 648262306a36Sopenharmony_ci else 648362306a36Sopenharmony_ci cmd &= ~command_bits; 648462306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, cmd); 648562306a36Sopenharmony_ci } 648662306a36Sopenharmony_ci 648762306a36Sopenharmony_ci if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE)) 648862306a36Sopenharmony_ci return 0; 648962306a36Sopenharmony_ci 649062306a36Sopenharmony_ci bus = dev->bus; 649162306a36Sopenharmony_ci while (bus) { 649262306a36Sopenharmony_ci bridge = bus->self; 649362306a36Sopenharmony_ci if (bridge) { 649462306a36Sopenharmony_ci pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, 649562306a36Sopenharmony_ci &cmd); 649662306a36Sopenharmony_ci if (decode) 649762306a36Sopenharmony_ci cmd |= PCI_BRIDGE_CTL_VGA; 649862306a36Sopenharmony_ci else 649962306a36Sopenharmony_ci cmd &= ~PCI_BRIDGE_CTL_VGA; 650062306a36Sopenharmony_ci pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, 650162306a36Sopenharmony_ci cmd); 650262306a36Sopenharmony_ci } 650362306a36Sopenharmony_ci bus = bus->parent; 650462306a36Sopenharmony_ci } 650562306a36Sopenharmony_ci return 0; 650662306a36Sopenharmony_ci} 650762306a36Sopenharmony_ci 650862306a36Sopenharmony_ci#ifdef CONFIG_ACPI 650962306a36Sopenharmony_cibool pci_pr3_present(struct pci_dev *pdev) 651062306a36Sopenharmony_ci{ 651162306a36Sopenharmony_ci struct acpi_device *adev; 651262306a36Sopenharmony_ci 651362306a36Sopenharmony_ci if (acpi_disabled) 651462306a36Sopenharmony_ci return false; 651562306a36Sopenharmony_ci 651662306a36Sopenharmony_ci adev = ACPI_COMPANION(&pdev->dev); 651762306a36Sopenharmony_ci if (!adev) 651862306a36Sopenharmony_ci return false; 651962306a36Sopenharmony_ci 652062306a36Sopenharmony_ci return adev->power.flags.power_resources && 652162306a36Sopenharmony_ci acpi_has_method(adev->handle, "_PR3"); 652262306a36Sopenharmony_ci} 652362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_pr3_present); 652462306a36Sopenharmony_ci#endif 652562306a36Sopenharmony_ci 652662306a36Sopenharmony_ci/** 652762306a36Sopenharmony_ci * pci_add_dma_alias - Add a DMA devfn alias for a device 652862306a36Sopenharmony_ci * @dev: the PCI device for which alias is added 652962306a36Sopenharmony_ci * @devfn_from: alias slot and function 653062306a36Sopenharmony_ci * @nr_devfns: number of subsequent devfns to alias 653162306a36Sopenharmony_ci * 653262306a36Sopenharmony_ci * This helper encodes an 8-bit devfn as a bit number in dma_alias_mask 653362306a36Sopenharmony_ci * which is used to program permissible bus-devfn source addresses for DMA 653462306a36Sopenharmony_ci * requests in an IOMMU. These aliases factor into IOMMU group creation 653562306a36Sopenharmony_ci * and are useful for devices generating DMA requests beyond or different 653662306a36Sopenharmony_ci * from their logical bus-devfn. Examples include device quirks where the 653762306a36Sopenharmony_ci * device simply uses the wrong devfn, as well as non-transparent bridges 653862306a36Sopenharmony_ci * where the alias may be a proxy for devices in another domain. 653962306a36Sopenharmony_ci * 654062306a36Sopenharmony_ci * IOMMU group creation is performed during device discovery or addition, 654162306a36Sopenharmony_ci * prior to any potential DMA mapping and therefore prior to driver probing 654262306a36Sopenharmony_ci * (especially for userspace assigned devices where IOMMU group definition 654362306a36Sopenharmony_ci * cannot be left as a userspace activity). DMA aliases should therefore 654462306a36Sopenharmony_ci * be configured via quirks, such as the PCI fixup header quirk. 654562306a36Sopenharmony_ci */ 654662306a36Sopenharmony_civoid pci_add_dma_alias(struct pci_dev *dev, u8 devfn_from, 654762306a36Sopenharmony_ci unsigned int nr_devfns) 654862306a36Sopenharmony_ci{ 654962306a36Sopenharmony_ci int devfn_to; 655062306a36Sopenharmony_ci 655162306a36Sopenharmony_ci nr_devfns = min(nr_devfns, (unsigned int)MAX_NR_DEVFNS - devfn_from); 655262306a36Sopenharmony_ci devfn_to = devfn_from + nr_devfns - 1; 655362306a36Sopenharmony_ci 655462306a36Sopenharmony_ci if (!dev->dma_alias_mask) 655562306a36Sopenharmony_ci dev->dma_alias_mask = bitmap_zalloc(MAX_NR_DEVFNS, GFP_KERNEL); 655662306a36Sopenharmony_ci if (!dev->dma_alias_mask) { 655762306a36Sopenharmony_ci pci_warn(dev, "Unable to allocate DMA alias mask\n"); 655862306a36Sopenharmony_ci return; 655962306a36Sopenharmony_ci } 656062306a36Sopenharmony_ci 656162306a36Sopenharmony_ci bitmap_set(dev->dma_alias_mask, devfn_from, nr_devfns); 656262306a36Sopenharmony_ci 656362306a36Sopenharmony_ci if (nr_devfns == 1) 656462306a36Sopenharmony_ci pci_info(dev, "Enabling fixed DMA alias to %02x.%d\n", 656562306a36Sopenharmony_ci PCI_SLOT(devfn_from), PCI_FUNC(devfn_from)); 656662306a36Sopenharmony_ci else if (nr_devfns > 1) 656762306a36Sopenharmony_ci pci_info(dev, "Enabling fixed DMA alias for devfn range from %02x.%d to %02x.%d\n", 656862306a36Sopenharmony_ci PCI_SLOT(devfn_from), PCI_FUNC(devfn_from), 656962306a36Sopenharmony_ci PCI_SLOT(devfn_to), PCI_FUNC(devfn_to)); 657062306a36Sopenharmony_ci} 657162306a36Sopenharmony_ci 657262306a36Sopenharmony_cibool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2) 657362306a36Sopenharmony_ci{ 657462306a36Sopenharmony_ci return (dev1->dma_alias_mask && 657562306a36Sopenharmony_ci test_bit(dev2->devfn, dev1->dma_alias_mask)) || 657662306a36Sopenharmony_ci (dev2->dma_alias_mask && 657762306a36Sopenharmony_ci test_bit(dev1->devfn, dev2->dma_alias_mask)) || 657862306a36Sopenharmony_ci pci_real_dma_dev(dev1) == dev2 || 657962306a36Sopenharmony_ci pci_real_dma_dev(dev2) == dev1; 658062306a36Sopenharmony_ci} 658162306a36Sopenharmony_ci 658262306a36Sopenharmony_cibool pci_device_is_present(struct pci_dev *pdev) 658362306a36Sopenharmony_ci{ 658462306a36Sopenharmony_ci u32 v; 658562306a36Sopenharmony_ci 658662306a36Sopenharmony_ci /* Check PF if pdev is a VF, since VF Vendor/Device IDs are 0xffff */ 658762306a36Sopenharmony_ci pdev = pci_physfn(pdev); 658862306a36Sopenharmony_ci if (pci_dev_is_disconnected(pdev)) 658962306a36Sopenharmony_ci return false; 659062306a36Sopenharmony_ci return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0); 659162306a36Sopenharmony_ci} 659262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_device_is_present); 659362306a36Sopenharmony_ci 659462306a36Sopenharmony_civoid pci_ignore_hotplug(struct pci_dev *dev) 659562306a36Sopenharmony_ci{ 659662306a36Sopenharmony_ci struct pci_dev *bridge = dev->bus->self; 659762306a36Sopenharmony_ci 659862306a36Sopenharmony_ci dev->ignore_hotplug = 1; 659962306a36Sopenharmony_ci /* Propagate the "ignore hotplug" setting to the parent bridge. */ 660062306a36Sopenharmony_ci if (bridge) 660162306a36Sopenharmony_ci bridge->ignore_hotplug = 1; 660262306a36Sopenharmony_ci} 660362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_ignore_hotplug); 660462306a36Sopenharmony_ci 660562306a36Sopenharmony_ci/** 660662306a36Sopenharmony_ci * pci_real_dma_dev - Get PCI DMA device for PCI device 660762306a36Sopenharmony_ci * @dev: the PCI device that may have a PCI DMA alias 660862306a36Sopenharmony_ci * 660962306a36Sopenharmony_ci * Permits the platform to provide architecture-specific functionality to 661062306a36Sopenharmony_ci * devices needing to alias DMA to another PCI device on another PCI bus. If 661162306a36Sopenharmony_ci * the PCI device is on the same bus, it is recommended to use 661262306a36Sopenharmony_ci * pci_add_dma_alias(). This is the default implementation. Architecture 661362306a36Sopenharmony_ci * implementations can override this. 661462306a36Sopenharmony_ci */ 661562306a36Sopenharmony_cistruct pci_dev __weak *pci_real_dma_dev(struct pci_dev *dev) 661662306a36Sopenharmony_ci{ 661762306a36Sopenharmony_ci return dev; 661862306a36Sopenharmony_ci} 661962306a36Sopenharmony_ci 662062306a36Sopenharmony_ciresource_size_t __weak pcibios_default_alignment(void) 662162306a36Sopenharmony_ci{ 662262306a36Sopenharmony_ci return 0; 662362306a36Sopenharmony_ci} 662462306a36Sopenharmony_ci 662562306a36Sopenharmony_ci/* 662662306a36Sopenharmony_ci * Arches that don't want to expose struct resource to userland as-is in 662762306a36Sopenharmony_ci * sysfs and /proc can implement their own pci_resource_to_user(). 662862306a36Sopenharmony_ci */ 662962306a36Sopenharmony_civoid __weak pci_resource_to_user(const struct pci_dev *dev, int bar, 663062306a36Sopenharmony_ci const struct resource *rsrc, 663162306a36Sopenharmony_ci resource_size_t *start, resource_size_t *end) 663262306a36Sopenharmony_ci{ 663362306a36Sopenharmony_ci *start = rsrc->start; 663462306a36Sopenharmony_ci *end = rsrc->end; 663562306a36Sopenharmony_ci} 663662306a36Sopenharmony_ci 663762306a36Sopenharmony_cistatic char *resource_alignment_param; 663862306a36Sopenharmony_cistatic DEFINE_SPINLOCK(resource_alignment_lock); 663962306a36Sopenharmony_ci 664062306a36Sopenharmony_ci/** 664162306a36Sopenharmony_ci * pci_specified_resource_alignment - get resource alignment specified by user. 664262306a36Sopenharmony_ci * @dev: the PCI device to get 664362306a36Sopenharmony_ci * @resize: whether or not to change resources' size when reassigning alignment 664462306a36Sopenharmony_ci * 664562306a36Sopenharmony_ci * RETURNS: Resource alignment if it is specified. 664662306a36Sopenharmony_ci * Zero if it is not specified. 664762306a36Sopenharmony_ci */ 664862306a36Sopenharmony_cistatic resource_size_t pci_specified_resource_alignment(struct pci_dev *dev, 664962306a36Sopenharmony_ci bool *resize) 665062306a36Sopenharmony_ci{ 665162306a36Sopenharmony_ci int align_order, count; 665262306a36Sopenharmony_ci resource_size_t align = pcibios_default_alignment(); 665362306a36Sopenharmony_ci const char *p; 665462306a36Sopenharmony_ci int ret; 665562306a36Sopenharmony_ci 665662306a36Sopenharmony_ci spin_lock(&resource_alignment_lock); 665762306a36Sopenharmony_ci p = resource_alignment_param; 665862306a36Sopenharmony_ci if (!p || !*p) 665962306a36Sopenharmony_ci goto out; 666062306a36Sopenharmony_ci if (pci_has_flag(PCI_PROBE_ONLY)) { 666162306a36Sopenharmony_ci align = 0; 666262306a36Sopenharmony_ci pr_info_once("PCI: Ignoring requested alignments (PCI_PROBE_ONLY)\n"); 666362306a36Sopenharmony_ci goto out; 666462306a36Sopenharmony_ci } 666562306a36Sopenharmony_ci 666662306a36Sopenharmony_ci while (*p) { 666762306a36Sopenharmony_ci count = 0; 666862306a36Sopenharmony_ci if (sscanf(p, "%d%n", &align_order, &count) == 1 && 666962306a36Sopenharmony_ci p[count] == '@') { 667062306a36Sopenharmony_ci p += count + 1; 667162306a36Sopenharmony_ci if (align_order > 63) { 667262306a36Sopenharmony_ci pr_err("PCI: Invalid requested alignment (order %d)\n", 667362306a36Sopenharmony_ci align_order); 667462306a36Sopenharmony_ci align_order = PAGE_SHIFT; 667562306a36Sopenharmony_ci } 667662306a36Sopenharmony_ci } else { 667762306a36Sopenharmony_ci align_order = PAGE_SHIFT; 667862306a36Sopenharmony_ci } 667962306a36Sopenharmony_ci 668062306a36Sopenharmony_ci ret = pci_dev_str_match(dev, p, &p); 668162306a36Sopenharmony_ci if (ret == 1) { 668262306a36Sopenharmony_ci *resize = true; 668362306a36Sopenharmony_ci align = 1ULL << align_order; 668462306a36Sopenharmony_ci break; 668562306a36Sopenharmony_ci } else if (ret < 0) { 668662306a36Sopenharmony_ci pr_err("PCI: Can't parse resource_alignment parameter: %s\n", 668762306a36Sopenharmony_ci p); 668862306a36Sopenharmony_ci break; 668962306a36Sopenharmony_ci } 669062306a36Sopenharmony_ci 669162306a36Sopenharmony_ci if (*p != ';' && *p != ',') { 669262306a36Sopenharmony_ci /* End of param or invalid format */ 669362306a36Sopenharmony_ci break; 669462306a36Sopenharmony_ci } 669562306a36Sopenharmony_ci p++; 669662306a36Sopenharmony_ci } 669762306a36Sopenharmony_ciout: 669862306a36Sopenharmony_ci spin_unlock(&resource_alignment_lock); 669962306a36Sopenharmony_ci return align; 670062306a36Sopenharmony_ci} 670162306a36Sopenharmony_ci 670262306a36Sopenharmony_cistatic void pci_request_resource_alignment(struct pci_dev *dev, int bar, 670362306a36Sopenharmony_ci resource_size_t align, bool resize) 670462306a36Sopenharmony_ci{ 670562306a36Sopenharmony_ci struct resource *r = &dev->resource[bar]; 670662306a36Sopenharmony_ci resource_size_t size; 670762306a36Sopenharmony_ci 670862306a36Sopenharmony_ci if (!(r->flags & IORESOURCE_MEM)) 670962306a36Sopenharmony_ci return; 671062306a36Sopenharmony_ci 671162306a36Sopenharmony_ci if (r->flags & IORESOURCE_PCI_FIXED) { 671262306a36Sopenharmony_ci pci_info(dev, "BAR%d %pR: ignoring requested alignment %#llx\n", 671362306a36Sopenharmony_ci bar, r, (unsigned long long)align); 671462306a36Sopenharmony_ci return; 671562306a36Sopenharmony_ci } 671662306a36Sopenharmony_ci 671762306a36Sopenharmony_ci size = resource_size(r); 671862306a36Sopenharmony_ci if (size >= align) 671962306a36Sopenharmony_ci return; 672062306a36Sopenharmony_ci 672162306a36Sopenharmony_ci /* 672262306a36Sopenharmony_ci * Increase the alignment of the resource. There are two ways we 672362306a36Sopenharmony_ci * can do this: 672462306a36Sopenharmony_ci * 672562306a36Sopenharmony_ci * 1) Increase the size of the resource. BARs are aligned on their 672662306a36Sopenharmony_ci * size, so when we reallocate space for this resource, we'll 672762306a36Sopenharmony_ci * allocate it with the larger alignment. This also prevents 672862306a36Sopenharmony_ci * assignment of any other BARs inside the alignment region, so 672962306a36Sopenharmony_ci * if we're requesting page alignment, this means no other BARs 673062306a36Sopenharmony_ci * will share the page. 673162306a36Sopenharmony_ci * 673262306a36Sopenharmony_ci * The disadvantage is that this makes the resource larger than 673362306a36Sopenharmony_ci * the hardware BAR, which may break drivers that compute things 673462306a36Sopenharmony_ci * based on the resource size, e.g., to find registers at a 673562306a36Sopenharmony_ci * fixed offset before the end of the BAR. 673662306a36Sopenharmony_ci * 673762306a36Sopenharmony_ci * 2) Retain the resource size, but use IORESOURCE_STARTALIGN and 673862306a36Sopenharmony_ci * set r->start to the desired alignment. By itself this 673962306a36Sopenharmony_ci * doesn't prevent other BARs being put inside the alignment 674062306a36Sopenharmony_ci * region, but if we realign *every* resource of every device in 674162306a36Sopenharmony_ci * the system, none of them will share an alignment region. 674262306a36Sopenharmony_ci * 674362306a36Sopenharmony_ci * When the user has requested alignment for only some devices via 674462306a36Sopenharmony_ci * the "pci=resource_alignment" argument, "resize" is true and we 674562306a36Sopenharmony_ci * use the first method. Otherwise we assume we're aligning all 674662306a36Sopenharmony_ci * devices and we use the second. 674762306a36Sopenharmony_ci */ 674862306a36Sopenharmony_ci 674962306a36Sopenharmony_ci pci_info(dev, "BAR%d %pR: requesting alignment to %#llx\n", 675062306a36Sopenharmony_ci bar, r, (unsigned long long)align); 675162306a36Sopenharmony_ci 675262306a36Sopenharmony_ci if (resize) { 675362306a36Sopenharmony_ci r->start = 0; 675462306a36Sopenharmony_ci r->end = align - 1; 675562306a36Sopenharmony_ci } else { 675662306a36Sopenharmony_ci r->flags &= ~IORESOURCE_SIZEALIGN; 675762306a36Sopenharmony_ci r->flags |= IORESOURCE_STARTALIGN; 675862306a36Sopenharmony_ci r->start = align; 675962306a36Sopenharmony_ci r->end = r->start + size - 1; 676062306a36Sopenharmony_ci } 676162306a36Sopenharmony_ci r->flags |= IORESOURCE_UNSET; 676262306a36Sopenharmony_ci} 676362306a36Sopenharmony_ci 676462306a36Sopenharmony_ci/* 676562306a36Sopenharmony_ci * This function disables memory decoding and releases memory resources 676662306a36Sopenharmony_ci * of the device specified by kernel's boot parameter 'pci=resource_alignment='. 676762306a36Sopenharmony_ci * It also rounds up size to specified alignment. 676862306a36Sopenharmony_ci * Later on, the kernel will assign page-aligned memory resource back 676962306a36Sopenharmony_ci * to the device. 677062306a36Sopenharmony_ci */ 677162306a36Sopenharmony_civoid pci_reassigndev_resource_alignment(struct pci_dev *dev) 677262306a36Sopenharmony_ci{ 677362306a36Sopenharmony_ci int i; 677462306a36Sopenharmony_ci struct resource *r; 677562306a36Sopenharmony_ci resource_size_t align; 677662306a36Sopenharmony_ci u16 command; 677762306a36Sopenharmony_ci bool resize = false; 677862306a36Sopenharmony_ci 677962306a36Sopenharmony_ci /* 678062306a36Sopenharmony_ci * VF BARs are read-only zero according to SR-IOV spec r1.1, sec 678162306a36Sopenharmony_ci * 3.4.1.11. Their resources are allocated from the space 678262306a36Sopenharmony_ci * described by the VF BARx register in the PF's SR-IOV capability. 678362306a36Sopenharmony_ci * We can't influence their alignment here. 678462306a36Sopenharmony_ci */ 678562306a36Sopenharmony_ci if (dev->is_virtfn) 678662306a36Sopenharmony_ci return; 678762306a36Sopenharmony_ci 678862306a36Sopenharmony_ci /* check if specified PCI is target device to reassign */ 678962306a36Sopenharmony_ci align = pci_specified_resource_alignment(dev, &resize); 679062306a36Sopenharmony_ci if (!align) 679162306a36Sopenharmony_ci return; 679262306a36Sopenharmony_ci 679362306a36Sopenharmony_ci if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL && 679462306a36Sopenharmony_ci (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) { 679562306a36Sopenharmony_ci pci_warn(dev, "Can't reassign resources to host bridge\n"); 679662306a36Sopenharmony_ci return; 679762306a36Sopenharmony_ci } 679862306a36Sopenharmony_ci 679962306a36Sopenharmony_ci pci_read_config_word(dev, PCI_COMMAND, &command); 680062306a36Sopenharmony_ci command &= ~PCI_COMMAND_MEMORY; 680162306a36Sopenharmony_ci pci_write_config_word(dev, PCI_COMMAND, command); 680262306a36Sopenharmony_ci 680362306a36Sopenharmony_ci for (i = 0; i <= PCI_ROM_RESOURCE; i++) 680462306a36Sopenharmony_ci pci_request_resource_alignment(dev, i, align, resize); 680562306a36Sopenharmony_ci 680662306a36Sopenharmony_ci /* 680762306a36Sopenharmony_ci * Need to disable bridge's resource window, 680862306a36Sopenharmony_ci * to enable the kernel to reassign new resource 680962306a36Sopenharmony_ci * window later on. 681062306a36Sopenharmony_ci */ 681162306a36Sopenharmony_ci if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 681262306a36Sopenharmony_ci for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { 681362306a36Sopenharmony_ci r = &dev->resource[i]; 681462306a36Sopenharmony_ci if (!(r->flags & IORESOURCE_MEM)) 681562306a36Sopenharmony_ci continue; 681662306a36Sopenharmony_ci r->flags |= IORESOURCE_UNSET; 681762306a36Sopenharmony_ci r->end = resource_size(r) - 1; 681862306a36Sopenharmony_ci r->start = 0; 681962306a36Sopenharmony_ci } 682062306a36Sopenharmony_ci pci_disable_bridge_window(dev); 682162306a36Sopenharmony_ci } 682262306a36Sopenharmony_ci} 682362306a36Sopenharmony_ci 682462306a36Sopenharmony_cistatic ssize_t resource_alignment_show(const struct bus_type *bus, char *buf) 682562306a36Sopenharmony_ci{ 682662306a36Sopenharmony_ci size_t count = 0; 682762306a36Sopenharmony_ci 682862306a36Sopenharmony_ci spin_lock(&resource_alignment_lock); 682962306a36Sopenharmony_ci if (resource_alignment_param) 683062306a36Sopenharmony_ci count = sysfs_emit(buf, "%s\n", resource_alignment_param); 683162306a36Sopenharmony_ci spin_unlock(&resource_alignment_lock); 683262306a36Sopenharmony_ci 683362306a36Sopenharmony_ci return count; 683462306a36Sopenharmony_ci} 683562306a36Sopenharmony_ci 683662306a36Sopenharmony_cistatic ssize_t resource_alignment_store(const struct bus_type *bus, 683762306a36Sopenharmony_ci const char *buf, size_t count) 683862306a36Sopenharmony_ci{ 683962306a36Sopenharmony_ci char *param, *old, *end; 684062306a36Sopenharmony_ci 684162306a36Sopenharmony_ci if (count >= (PAGE_SIZE - 1)) 684262306a36Sopenharmony_ci return -EINVAL; 684362306a36Sopenharmony_ci 684462306a36Sopenharmony_ci param = kstrndup(buf, count, GFP_KERNEL); 684562306a36Sopenharmony_ci if (!param) 684662306a36Sopenharmony_ci return -ENOMEM; 684762306a36Sopenharmony_ci 684862306a36Sopenharmony_ci end = strchr(param, '\n'); 684962306a36Sopenharmony_ci if (end) 685062306a36Sopenharmony_ci *end = '\0'; 685162306a36Sopenharmony_ci 685262306a36Sopenharmony_ci spin_lock(&resource_alignment_lock); 685362306a36Sopenharmony_ci old = resource_alignment_param; 685462306a36Sopenharmony_ci if (strlen(param)) { 685562306a36Sopenharmony_ci resource_alignment_param = param; 685662306a36Sopenharmony_ci } else { 685762306a36Sopenharmony_ci kfree(param); 685862306a36Sopenharmony_ci resource_alignment_param = NULL; 685962306a36Sopenharmony_ci } 686062306a36Sopenharmony_ci spin_unlock(&resource_alignment_lock); 686162306a36Sopenharmony_ci 686262306a36Sopenharmony_ci kfree(old); 686362306a36Sopenharmony_ci 686462306a36Sopenharmony_ci return count; 686562306a36Sopenharmony_ci} 686662306a36Sopenharmony_ci 686762306a36Sopenharmony_cistatic BUS_ATTR_RW(resource_alignment); 686862306a36Sopenharmony_ci 686962306a36Sopenharmony_cistatic int __init pci_resource_alignment_sysfs_init(void) 687062306a36Sopenharmony_ci{ 687162306a36Sopenharmony_ci return bus_create_file(&pci_bus_type, 687262306a36Sopenharmony_ci &bus_attr_resource_alignment); 687362306a36Sopenharmony_ci} 687462306a36Sopenharmony_cilate_initcall(pci_resource_alignment_sysfs_init); 687562306a36Sopenharmony_ci 687662306a36Sopenharmony_cistatic void pci_no_domains(void) 687762306a36Sopenharmony_ci{ 687862306a36Sopenharmony_ci#ifdef CONFIG_PCI_DOMAINS 687962306a36Sopenharmony_ci pci_domains_supported = 0; 688062306a36Sopenharmony_ci#endif 688162306a36Sopenharmony_ci} 688262306a36Sopenharmony_ci 688362306a36Sopenharmony_ci#ifdef CONFIG_PCI_DOMAINS_GENERIC 688462306a36Sopenharmony_cistatic DEFINE_IDA(pci_domain_nr_static_ida); 688562306a36Sopenharmony_cistatic DEFINE_IDA(pci_domain_nr_dynamic_ida); 688662306a36Sopenharmony_ci 688762306a36Sopenharmony_cistatic void of_pci_reserve_static_domain_nr(void) 688862306a36Sopenharmony_ci{ 688962306a36Sopenharmony_ci struct device_node *np; 689062306a36Sopenharmony_ci int domain_nr; 689162306a36Sopenharmony_ci 689262306a36Sopenharmony_ci for_each_node_by_type(np, "pci") { 689362306a36Sopenharmony_ci domain_nr = of_get_pci_domain_nr(np); 689462306a36Sopenharmony_ci if (domain_nr < 0) 689562306a36Sopenharmony_ci continue; 689662306a36Sopenharmony_ci /* 689762306a36Sopenharmony_ci * Permanently allocate domain_nr in dynamic_ida 689862306a36Sopenharmony_ci * to prevent it from dynamic allocation. 689962306a36Sopenharmony_ci */ 690062306a36Sopenharmony_ci ida_alloc_range(&pci_domain_nr_dynamic_ida, 690162306a36Sopenharmony_ci domain_nr, domain_nr, GFP_KERNEL); 690262306a36Sopenharmony_ci } 690362306a36Sopenharmony_ci} 690462306a36Sopenharmony_ci 690562306a36Sopenharmony_cistatic int of_pci_bus_find_domain_nr(struct device *parent) 690662306a36Sopenharmony_ci{ 690762306a36Sopenharmony_ci static bool static_domains_reserved = false; 690862306a36Sopenharmony_ci int domain_nr; 690962306a36Sopenharmony_ci 691062306a36Sopenharmony_ci /* On the first call scan device tree for static allocations. */ 691162306a36Sopenharmony_ci if (!static_domains_reserved) { 691262306a36Sopenharmony_ci of_pci_reserve_static_domain_nr(); 691362306a36Sopenharmony_ci static_domains_reserved = true; 691462306a36Sopenharmony_ci } 691562306a36Sopenharmony_ci 691662306a36Sopenharmony_ci if (parent) { 691762306a36Sopenharmony_ci /* 691862306a36Sopenharmony_ci * If domain is in DT, allocate it in static IDA. This 691962306a36Sopenharmony_ci * prevents duplicate static allocations in case of errors 692062306a36Sopenharmony_ci * in DT. 692162306a36Sopenharmony_ci */ 692262306a36Sopenharmony_ci domain_nr = of_get_pci_domain_nr(parent->of_node); 692362306a36Sopenharmony_ci if (domain_nr >= 0) 692462306a36Sopenharmony_ci return ida_alloc_range(&pci_domain_nr_static_ida, 692562306a36Sopenharmony_ci domain_nr, domain_nr, 692662306a36Sopenharmony_ci GFP_KERNEL); 692762306a36Sopenharmony_ci } 692862306a36Sopenharmony_ci 692962306a36Sopenharmony_ci /* 693062306a36Sopenharmony_ci * If domain was not specified in DT, choose a free ID from dynamic 693162306a36Sopenharmony_ci * allocations. All domain numbers from DT are permanently in 693262306a36Sopenharmony_ci * dynamic allocations to prevent assigning them to other DT nodes 693362306a36Sopenharmony_ci * without static domain. 693462306a36Sopenharmony_ci */ 693562306a36Sopenharmony_ci return ida_alloc(&pci_domain_nr_dynamic_ida, GFP_KERNEL); 693662306a36Sopenharmony_ci} 693762306a36Sopenharmony_ci 693862306a36Sopenharmony_cistatic void of_pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent) 693962306a36Sopenharmony_ci{ 694062306a36Sopenharmony_ci if (bus->domain_nr < 0) 694162306a36Sopenharmony_ci return; 694262306a36Sopenharmony_ci 694362306a36Sopenharmony_ci /* Release domain from IDA where it was allocated. */ 694462306a36Sopenharmony_ci if (of_get_pci_domain_nr(parent->of_node) == bus->domain_nr) 694562306a36Sopenharmony_ci ida_free(&pci_domain_nr_static_ida, bus->domain_nr); 694662306a36Sopenharmony_ci else 694762306a36Sopenharmony_ci ida_free(&pci_domain_nr_dynamic_ida, bus->domain_nr); 694862306a36Sopenharmony_ci} 694962306a36Sopenharmony_ci 695062306a36Sopenharmony_ciint pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent) 695162306a36Sopenharmony_ci{ 695262306a36Sopenharmony_ci return acpi_disabled ? of_pci_bus_find_domain_nr(parent) : 695362306a36Sopenharmony_ci acpi_pci_bus_find_domain_nr(bus); 695462306a36Sopenharmony_ci} 695562306a36Sopenharmony_ci 695662306a36Sopenharmony_civoid pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent) 695762306a36Sopenharmony_ci{ 695862306a36Sopenharmony_ci if (!acpi_disabled) 695962306a36Sopenharmony_ci return; 696062306a36Sopenharmony_ci of_pci_bus_release_domain_nr(bus, parent); 696162306a36Sopenharmony_ci} 696262306a36Sopenharmony_ci#endif 696362306a36Sopenharmony_ci 696462306a36Sopenharmony_ci/** 696562306a36Sopenharmony_ci * pci_ext_cfg_avail - can we access extended PCI config space? 696662306a36Sopenharmony_ci * 696762306a36Sopenharmony_ci * Returns 1 if we can access PCI extended config space (offsets 696862306a36Sopenharmony_ci * greater than 0xff). This is the default implementation. Architecture 696962306a36Sopenharmony_ci * implementations can override this. 697062306a36Sopenharmony_ci */ 697162306a36Sopenharmony_ciint __weak pci_ext_cfg_avail(void) 697262306a36Sopenharmony_ci{ 697362306a36Sopenharmony_ci return 1; 697462306a36Sopenharmony_ci} 697562306a36Sopenharmony_ci 697662306a36Sopenharmony_civoid __weak pci_fixup_cardbus(struct pci_bus *bus) 697762306a36Sopenharmony_ci{ 697862306a36Sopenharmony_ci} 697962306a36Sopenharmony_ciEXPORT_SYMBOL(pci_fixup_cardbus); 698062306a36Sopenharmony_ci 698162306a36Sopenharmony_cistatic int __init pci_setup(char *str) 698262306a36Sopenharmony_ci{ 698362306a36Sopenharmony_ci while (str) { 698462306a36Sopenharmony_ci char *k = strchr(str, ','); 698562306a36Sopenharmony_ci if (k) 698662306a36Sopenharmony_ci *k++ = 0; 698762306a36Sopenharmony_ci if (*str && (str = pcibios_setup(str)) && *str) { 698862306a36Sopenharmony_ci if (!strcmp(str, "nomsi")) { 698962306a36Sopenharmony_ci pci_no_msi(); 699062306a36Sopenharmony_ci } else if (!strncmp(str, "noats", 5)) { 699162306a36Sopenharmony_ci pr_info("PCIe: ATS is disabled\n"); 699262306a36Sopenharmony_ci pcie_ats_disabled = true; 699362306a36Sopenharmony_ci } else if (!strcmp(str, "noaer")) { 699462306a36Sopenharmony_ci pci_no_aer(); 699562306a36Sopenharmony_ci } else if (!strcmp(str, "earlydump")) { 699662306a36Sopenharmony_ci pci_early_dump = true; 699762306a36Sopenharmony_ci } else if (!strncmp(str, "realloc=", 8)) { 699862306a36Sopenharmony_ci pci_realloc_get_opt(str + 8); 699962306a36Sopenharmony_ci } else if (!strncmp(str, "realloc", 7)) { 700062306a36Sopenharmony_ci pci_realloc_get_opt("on"); 700162306a36Sopenharmony_ci } else if (!strcmp(str, "nodomains")) { 700262306a36Sopenharmony_ci pci_no_domains(); 700362306a36Sopenharmony_ci } else if (!strncmp(str, "noari", 5)) { 700462306a36Sopenharmony_ci pcie_ari_disabled = true; 700562306a36Sopenharmony_ci } else if (!strncmp(str, "cbiosize=", 9)) { 700662306a36Sopenharmony_ci pci_cardbus_io_size = memparse(str + 9, &str); 700762306a36Sopenharmony_ci } else if (!strncmp(str, "cbmemsize=", 10)) { 700862306a36Sopenharmony_ci pci_cardbus_mem_size = memparse(str + 10, &str); 700962306a36Sopenharmony_ci } else if (!strncmp(str, "resource_alignment=", 19)) { 701062306a36Sopenharmony_ci resource_alignment_param = str + 19; 701162306a36Sopenharmony_ci } else if (!strncmp(str, "ecrc=", 5)) { 701262306a36Sopenharmony_ci pcie_ecrc_get_policy(str + 5); 701362306a36Sopenharmony_ci } else if (!strncmp(str, "hpiosize=", 9)) { 701462306a36Sopenharmony_ci pci_hotplug_io_size = memparse(str + 9, &str); 701562306a36Sopenharmony_ci } else if (!strncmp(str, "hpmmiosize=", 11)) { 701662306a36Sopenharmony_ci pci_hotplug_mmio_size = memparse(str + 11, &str); 701762306a36Sopenharmony_ci } else if (!strncmp(str, "hpmmioprefsize=", 15)) { 701862306a36Sopenharmony_ci pci_hotplug_mmio_pref_size = memparse(str + 15, &str); 701962306a36Sopenharmony_ci } else if (!strncmp(str, "hpmemsize=", 10)) { 702062306a36Sopenharmony_ci pci_hotplug_mmio_size = memparse(str + 10, &str); 702162306a36Sopenharmony_ci pci_hotplug_mmio_pref_size = pci_hotplug_mmio_size; 702262306a36Sopenharmony_ci } else if (!strncmp(str, "hpbussize=", 10)) { 702362306a36Sopenharmony_ci pci_hotplug_bus_size = 702462306a36Sopenharmony_ci simple_strtoul(str + 10, &str, 0); 702562306a36Sopenharmony_ci if (pci_hotplug_bus_size > 0xff) 702662306a36Sopenharmony_ci pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE; 702762306a36Sopenharmony_ci } else if (!strncmp(str, "pcie_bus_tune_off", 17)) { 702862306a36Sopenharmony_ci pcie_bus_config = PCIE_BUS_TUNE_OFF; 702962306a36Sopenharmony_ci } else if (!strncmp(str, "pcie_bus_safe", 13)) { 703062306a36Sopenharmony_ci pcie_bus_config = PCIE_BUS_SAFE; 703162306a36Sopenharmony_ci } else if (!strncmp(str, "pcie_bus_perf", 13)) { 703262306a36Sopenharmony_ci pcie_bus_config = PCIE_BUS_PERFORMANCE; 703362306a36Sopenharmony_ci } else if (!strncmp(str, "pcie_bus_peer2peer", 18)) { 703462306a36Sopenharmony_ci pcie_bus_config = PCIE_BUS_PEER2PEER; 703562306a36Sopenharmony_ci } else if (!strncmp(str, "pcie_scan_all", 13)) { 703662306a36Sopenharmony_ci pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS); 703762306a36Sopenharmony_ci } else if (!strncmp(str, "disable_acs_redir=", 18)) { 703862306a36Sopenharmony_ci disable_acs_redir_param = str + 18; 703962306a36Sopenharmony_ci } else { 704062306a36Sopenharmony_ci pr_err("PCI: Unknown option `%s'\n", str); 704162306a36Sopenharmony_ci } 704262306a36Sopenharmony_ci } 704362306a36Sopenharmony_ci str = k; 704462306a36Sopenharmony_ci } 704562306a36Sopenharmony_ci return 0; 704662306a36Sopenharmony_ci} 704762306a36Sopenharmony_ciearly_param("pci", pci_setup); 704862306a36Sopenharmony_ci 704962306a36Sopenharmony_ci/* 705062306a36Sopenharmony_ci * 'resource_alignment_param' and 'disable_acs_redir_param' are initialized 705162306a36Sopenharmony_ci * in pci_setup(), above, to point to data in the __initdata section which 705262306a36Sopenharmony_ci * will be freed after the init sequence is complete. We can't allocate memory 705362306a36Sopenharmony_ci * in pci_setup() because some architectures do not have any memory allocation 705462306a36Sopenharmony_ci * service available during an early_param() call. So we allocate memory and 705562306a36Sopenharmony_ci * copy the variable here before the init section is freed. 705662306a36Sopenharmony_ci * 705762306a36Sopenharmony_ci */ 705862306a36Sopenharmony_cistatic int __init pci_realloc_setup_params(void) 705962306a36Sopenharmony_ci{ 706062306a36Sopenharmony_ci resource_alignment_param = kstrdup(resource_alignment_param, 706162306a36Sopenharmony_ci GFP_KERNEL); 706262306a36Sopenharmony_ci disable_acs_redir_param = kstrdup(disable_acs_redir_param, GFP_KERNEL); 706362306a36Sopenharmony_ci 706462306a36Sopenharmony_ci return 0; 706562306a36Sopenharmony_ci} 706662306a36Sopenharmony_cipure_initcall(pci_realloc_setup_params); 7067