18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * (C) Copyright 2002-2004, 2007 Greg Kroah-Hartman <greg@kroah.com> 48c2ecf20Sopenharmony_ci * (C) Copyright 2007 Novell Inc. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/pci.h> 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/device.h> 118c2ecf20Sopenharmony_ci#include <linux/mempolicy.h> 128c2ecf20Sopenharmony_ci#include <linux/string.h> 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/sched.h> 158c2ecf20Sopenharmony_ci#include <linux/sched/isolation.h> 168c2ecf20Sopenharmony_ci#include <linux/cpu.h> 178c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 188c2ecf20Sopenharmony_ci#include <linux/suspend.h> 198c2ecf20Sopenharmony_ci#include <linux/kexec.h> 208c2ecf20Sopenharmony_ci#include <linux/of_device.h> 218c2ecf20Sopenharmony_ci#include <linux/acpi.h> 228c2ecf20Sopenharmony_ci#include <linux/dma-map-ops.h> 238c2ecf20Sopenharmony_ci#include "pci.h" 248c2ecf20Sopenharmony_ci#include "pcie/portdrv.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistruct pci_dynid { 278c2ecf20Sopenharmony_ci struct list_head node; 288c2ecf20Sopenharmony_ci struct pci_device_id id; 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/** 328c2ecf20Sopenharmony_ci * pci_add_dynid - add a new PCI device ID to this driver and re-probe devices 338c2ecf20Sopenharmony_ci * @drv: target pci driver 348c2ecf20Sopenharmony_ci * @vendor: PCI vendor ID 358c2ecf20Sopenharmony_ci * @device: PCI device ID 368c2ecf20Sopenharmony_ci * @subvendor: PCI subvendor ID 378c2ecf20Sopenharmony_ci * @subdevice: PCI subdevice ID 388c2ecf20Sopenharmony_ci * @class: PCI class 398c2ecf20Sopenharmony_ci * @class_mask: PCI class mask 408c2ecf20Sopenharmony_ci * @driver_data: private driver data 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci * Adds a new dynamic pci device ID to this driver and causes the 438c2ecf20Sopenharmony_ci * driver to probe for all devices again. @drv must have been 448c2ecf20Sopenharmony_ci * registered prior to calling this function. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * CONTEXT: 478c2ecf20Sopenharmony_ci * Does GFP_KERNEL allocation. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * RETURNS: 508c2ecf20Sopenharmony_ci * 0 on success, -errno on failure. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ciint pci_add_dynid(struct pci_driver *drv, 538c2ecf20Sopenharmony_ci unsigned int vendor, unsigned int device, 548c2ecf20Sopenharmony_ci unsigned int subvendor, unsigned int subdevice, 558c2ecf20Sopenharmony_ci unsigned int class, unsigned int class_mask, 568c2ecf20Sopenharmony_ci unsigned long driver_data) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci struct pci_dynid *dynid; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); 618c2ecf20Sopenharmony_ci if (!dynid) 628c2ecf20Sopenharmony_ci return -ENOMEM; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci dynid->id.vendor = vendor; 658c2ecf20Sopenharmony_ci dynid->id.device = device; 668c2ecf20Sopenharmony_ci dynid->id.subvendor = subvendor; 678c2ecf20Sopenharmony_ci dynid->id.subdevice = subdevice; 688c2ecf20Sopenharmony_ci dynid->id.class = class; 698c2ecf20Sopenharmony_ci dynid->id.class_mask = class_mask; 708c2ecf20Sopenharmony_ci dynid->id.driver_data = driver_data; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci spin_lock(&drv->dynids.lock); 738c2ecf20Sopenharmony_ci list_add_tail(&dynid->node, &drv->dynids.list); 748c2ecf20Sopenharmony_ci spin_unlock(&drv->dynids.lock); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci return driver_attach(&drv->driver); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_add_dynid); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic void pci_free_dynids(struct pci_driver *drv) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci struct pci_dynid *dynid, *n; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci spin_lock(&drv->dynids.lock); 858c2ecf20Sopenharmony_ci list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { 868c2ecf20Sopenharmony_ci list_del(&dynid->node); 878c2ecf20Sopenharmony_ci kfree(dynid); 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci spin_unlock(&drv->dynids.lock); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/** 938c2ecf20Sopenharmony_ci * store_new_id - sysfs frontend to pci_add_dynid() 948c2ecf20Sopenharmony_ci * @driver: target device driver 958c2ecf20Sopenharmony_ci * @buf: buffer for scanning device ID data 968c2ecf20Sopenharmony_ci * @count: input size 978c2ecf20Sopenharmony_ci * 988c2ecf20Sopenharmony_ci * Allow PCI IDs to be added to an existing driver via sysfs. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_cistatic ssize_t new_id_store(struct device_driver *driver, const char *buf, 1018c2ecf20Sopenharmony_ci size_t count) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci struct pci_driver *pdrv = to_pci_driver(driver); 1048c2ecf20Sopenharmony_ci const struct pci_device_id *ids = pdrv->id_table; 1058c2ecf20Sopenharmony_ci u32 vendor, device, subvendor = PCI_ANY_ID, 1068c2ecf20Sopenharmony_ci subdevice = PCI_ANY_ID, class = 0, class_mask = 0; 1078c2ecf20Sopenharmony_ci unsigned long driver_data = 0; 1088c2ecf20Sopenharmony_ci int fields = 0; 1098c2ecf20Sopenharmony_ci int retval = 0; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci fields = sscanf(buf, "%x %x %x %x %x %x %lx", 1128c2ecf20Sopenharmony_ci &vendor, &device, &subvendor, &subdevice, 1138c2ecf20Sopenharmony_ci &class, &class_mask, &driver_data); 1148c2ecf20Sopenharmony_ci if (fields < 2) 1158c2ecf20Sopenharmony_ci return -EINVAL; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci if (fields != 7) { 1188c2ecf20Sopenharmony_ci struct pci_dev *pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); 1198c2ecf20Sopenharmony_ci if (!pdev) 1208c2ecf20Sopenharmony_ci return -ENOMEM; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci pdev->vendor = vendor; 1238c2ecf20Sopenharmony_ci pdev->device = device; 1248c2ecf20Sopenharmony_ci pdev->subsystem_vendor = subvendor; 1258c2ecf20Sopenharmony_ci pdev->subsystem_device = subdevice; 1268c2ecf20Sopenharmony_ci pdev->class = class; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (pci_match_id(pdrv->id_table, pdev)) 1298c2ecf20Sopenharmony_ci retval = -EEXIST; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci kfree(pdev); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (retval) 1348c2ecf20Sopenharmony_ci return retval; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* Only accept driver_data values that match an existing id_table 1388c2ecf20Sopenharmony_ci entry */ 1398c2ecf20Sopenharmony_ci if (ids) { 1408c2ecf20Sopenharmony_ci retval = -EINVAL; 1418c2ecf20Sopenharmony_ci while (ids->vendor || ids->subvendor || ids->class_mask) { 1428c2ecf20Sopenharmony_ci if (driver_data == ids->driver_data) { 1438c2ecf20Sopenharmony_ci retval = 0; 1448c2ecf20Sopenharmony_ci break; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci ids++; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci if (retval) /* No match */ 1498c2ecf20Sopenharmony_ci return retval; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci retval = pci_add_dynid(pdrv, vendor, device, subvendor, subdevice, 1538c2ecf20Sopenharmony_ci class, class_mask, driver_data); 1548c2ecf20Sopenharmony_ci if (retval) 1558c2ecf20Sopenharmony_ci return retval; 1568c2ecf20Sopenharmony_ci return count; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_cistatic DRIVER_ATTR_WO(new_id); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/** 1618c2ecf20Sopenharmony_ci * store_remove_id - remove a PCI device ID from this driver 1628c2ecf20Sopenharmony_ci * @driver: target device driver 1638c2ecf20Sopenharmony_ci * @buf: buffer for scanning device ID data 1648c2ecf20Sopenharmony_ci * @count: input size 1658c2ecf20Sopenharmony_ci * 1668c2ecf20Sopenharmony_ci * Removes a dynamic pci device ID to this driver. 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_cistatic ssize_t remove_id_store(struct device_driver *driver, const char *buf, 1698c2ecf20Sopenharmony_ci size_t count) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci struct pci_dynid *dynid, *n; 1728c2ecf20Sopenharmony_ci struct pci_driver *pdrv = to_pci_driver(driver); 1738c2ecf20Sopenharmony_ci u32 vendor, device, subvendor = PCI_ANY_ID, 1748c2ecf20Sopenharmony_ci subdevice = PCI_ANY_ID, class = 0, class_mask = 0; 1758c2ecf20Sopenharmony_ci int fields = 0; 1768c2ecf20Sopenharmony_ci size_t retval = -ENODEV; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci fields = sscanf(buf, "%x %x %x %x %x %x", 1798c2ecf20Sopenharmony_ci &vendor, &device, &subvendor, &subdevice, 1808c2ecf20Sopenharmony_ci &class, &class_mask); 1818c2ecf20Sopenharmony_ci if (fields < 2) 1828c2ecf20Sopenharmony_ci return -EINVAL; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci spin_lock(&pdrv->dynids.lock); 1858c2ecf20Sopenharmony_ci list_for_each_entry_safe(dynid, n, &pdrv->dynids.list, node) { 1868c2ecf20Sopenharmony_ci struct pci_device_id *id = &dynid->id; 1878c2ecf20Sopenharmony_ci if ((id->vendor == vendor) && 1888c2ecf20Sopenharmony_ci (id->device == device) && 1898c2ecf20Sopenharmony_ci (subvendor == PCI_ANY_ID || id->subvendor == subvendor) && 1908c2ecf20Sopenharmony_ci (subdevice == PCI_ANY_ID || id->subdevice == subdevice) && 1918c2ecf20Sopenharmony_ci !((id->class ^ class) & class_mask)) { 1928c2ecf20Sopenharmony_ci list_del(&dynid->node); 1938c2ecf20Sopenharmony_ci kfree(dynid); 1948c2ecf20Sopenharmony_ci retval = count; 1958c2ecf20Sopenharmony_ci break; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci spin_unlock(&pdrv->dynids.lock); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci return retval; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_cistatic DRIVER_ATTR_WO(remove_id); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic struct attribute *pci_drv_attrs[] = { 2058c2ecf20Sopenharmony_ci &driver_attr_new_id.attr, 2068c2ecf20Sopenharmony_ci &driver_attr_remove_id.attr, 2078c2ecf20Sopenharmony_ci NULL, 2088c2ecf20Sopenharmony_ci}; 2098c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(pci_drv); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/** 2128c2ecf20Sopenharmony_ci * pci_match_id - See if a pci device matches a given pci_id table 2138c2ecf20Sopenharmony_ci * @ids: array of PCI device id structures to search in 2148c2ecf20Sopenharmony_ci * @dev: the PCI device structure to match against. 2158c2ecf20Sopenharmony_ci * 2168c2ecf20Sopenharmony_ci * Used by a driver to check whether a PCI device present in the 2178c2ecf20Sopenharmony_ci * system is in its list of supported devices. Returns the matching 2188c2ecf20Sopenharmony_ci * pci_device_id structure or %NULL if there is no match. 2198c2ecf20Sopenharmony_ci * 2208c2ecf20Sopenharmony_ci * Deprecated, don't use this as it will not catch any dynamic ids 2218c2ecf20Sopenharmony_ci * that a driver might want to check for. 2228c2ecf20Sopenharmony_ci */ 2238c2ecf20Sopenharmony_ciconst struct pci_device_id *pci_match_id(const struct pci_device_id *ids, 2248c2ecf20Sopenharmony_ci struct pci_dev *dev) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci if (ids) { 2278c2ecf20Sopenharmony_ci while (ids->vendor || ids->subvendor || ids->class_mask) { 2288c2ecf20Sopenharmony_ci if (pci_match_one_device(ids, dev)) 2298c2ecf20Sopenharmony_ci return ids; 2308c2ecf20Sopenharmony_ci ids++; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci return NULL; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pci_match_id); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic const struct pci_device_id pci_device_id_any = { 2388c2ecf20Sopenharmony_ci .vendor = PCI_ANY_ID, 2398c2ecf20Sopenharmony_ci .device = PCI_ANY_ID, 2408c2ecf20Sopenharmony_ci .subvendor = PCI_ANY_ID, 2418c2ecf20Sopenharmony_ci .subdevice = PCI_ANY_ID, 2428c2ecf20Sopenharmony_ci}; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci/** 2458c2ecf20Sopenharmony_ci * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure 2468c2ecf20Sopenharmony_ci * @drv: the PCI driver to match against 2478c2ecf20Sopenharmony_ci * @dev: the PCI device structure to match against 2488c2ecf20Sopenharmony_ci * 2498c2ecf20Sopenharmony_ci * Used by a driver to check whether a PCI device present in the 2508c2ecf20Sopenharmony_ci * system is in its list of supported devices. Returns the matching 2518c2ecf20Sopenharmony_ci * pci_device_id structure or %NULL if there is no match. 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_cistatic const struct pci_device_id *pci_match_device(struct pci_driver *drv, 2548c2ecf20Sopenharmony_ci struct pci_dev *dev) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci struct pci_dynid *dynid; 2578c2ecf20Sopenharmony_ci const struct pci_device_id *found_id = NULL; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* When driver_override is set, only bind to the matching driver */ 2608c2ecf20Sopenharmony_ci if (dev->driver_override && strcmp(dev->driver_override, drv->name)) 2618c2ecf20Sopenharmony_ci return NULL; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* Look at the dynamic ids first, before the static ones */ 2648c2ecf20Sopenharmony_ci spin_lock(&drv->dynids.lock); 2658c2ecf20Sopenharmony_ci list_for_each_entry(dynid, &drv->dynids.list, node) { 2668c2ecf20Sopenharmony_ci if (pci_match_one_device(&dynid->id, dev)) { 2678c2ecf20Sopenharmony_ci found_id = &dynid->id; 2688c2ecf20Sopenharmony_ci break; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci spin_unlock(&drv->dynids.lock); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (!found_id) 2748c2ecf20Sopenharmony_ci found_id = pci_match_id(drv->id_table, dev); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* driver_override will always match, send a dummy id */ 2778c2ecf20Sopenharmony_ci if (!found_id && dev->driver_override) 2788c2ecf20Sopenharmony_ci found_id = &pci_device_id_any; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci return found_id; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistruct drv_dev_and_id { 2848c2ecf20Sopenharmony_ci struct pci_driver *drv; 2858c2ecf20Sopenharmony_ci struct pci_dev *dev; 2868c2ecf20Sopenharmony_ci const struct pci_device_id *id; 2878c2ecf20Sopenharmony_ci}; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic long local_pci_probe(void *_ddi) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci struct drv_dev_and_id *ddi = _ddi; 2928c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = ddi->dev; 2938c2ecf20Sopenharmony_ci struct pci_driver *pci_drv = ddi->drv; 2948c2ecf20Sopenharmony_ci struct device *dev = &pci_dev->dev; 2958c2ecf20Sopenharmony_ci int rc; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* 2988c2ecf20Sopenharmony_ci * Unbound PCI devices are always put in D0, regardless of 2998c2ecf20Sopenharmony_ci * runtime PM status. During probe, the device is set to 3008c2ecf20Sopenharmony_ci * active and the usage count is incremented. If the driver 3018c2ecf20Sopenharmony_ci * supports runtime PM, it should call pm_runtime_put_noidle(), 3028c2ecf20Sopenharmony_ci * or any other runtime PM helper function decrementing the usage 3038c2ecf20Sopenharmony_ci * count, in its probe routine and pm_runtime_get_noresume() in 3048c2ecf20Sopenharmony_ci * its remove routine. 3058c2ecf20Sopenharmony_ci */ 3068c2ecf20Sopenharmony_ci pm_runtime_get_sync(dev); 3078c2ecf20Sopenharmony_ci pci_dev->driver = pci_drv; 3088c2ecf20Sopenharmony_ci rc = pci_drv->probe(pci_dev, ddi->id); 3098c2ecf20Sopenharmony_ci if (!rc) 3108c2ecf20Sopenharmony_ci return rc; 3118c2ecf20Sopenharmony_ci if (rc < 0) { 3128c2ecf20Sopenharmony_ci pci_dev->driver = NULL; 3138c2ecf20Sopenharmony_ci pm_runtime_put_sync(dev); 3148c2ecf20Sopenharmony_ci return rc; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci /* 3178c2ecf20Sopenharmony_ci * Probe function should return < 0 for failure, 0 for success 3188c2ecf20Sopenharmony_ci * Treat values > 0 as success, but warn. 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_ci pci_warn(pci_dev, "Driver probe function unexpectedly returned %d\n", 3218c2ecf20Sopenharmony_ci rc); 3228c2ecf20Sopenharmony_ci return 0; 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic bool pci_physfn_is_probed(struct pci_dev *dev) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 3288c2ecf20Sopenharmony_ci return dev->is_virtfn && dev->physfn->is_probed; 3298c2ecf20Sopenharmony_ci#else 3308c2ecf20Sopenharmony_ci return false; 3318c2ecf20Sopenharmony_ci#endif 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, 3358c2ecf20Sopenharmony_ci const struct pci_device_id *id) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci int error, node, cpu; 3388c2ecf20Sopenharmony_ci int hk_flags = HK_FLAG_DOMAIN | HK_FLAG_WQ; 3398c2ecf20Sopenharmony_ci struct drv_dev_and_id ddi = { drv, dev, id }; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* 3428c2ecf20Sopenharmony_ci * Execute driver initialization on node where the device is 3438c2ecf20Sopenharmony_ci * attached. This way the driver likely allocates its local memory 3448c2ecf20Sopenharmony_ci * on the right node. 3458c2ecf20Sopenharmony_ci */ 3468c2ecf20Sopenharmony_ci node = dev_to_node(&dev->dev); 3478c2ecf20Sopenharmony_ci dev->is_probed = 1; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci cpu_hotplug_disable(); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* 3528c2ecf20Sopenharmony_ci * Prevent nesting work_on_cpu() for the case where a Virtual Function 3538c2ecf20Sopenharmony_ci * device is probed from work_on_cpu() of the Physical device. 3548c2ecf20Sopenharmony_ci */ 3558c2ecf20Sopenharmony_ci if (node < 0 || node >= MAX_NUMNODES || !node_online(node) || 3568c2ecf20Sopenharmony_ci pci_physfn_is_probed(dev)) 3578c2ecf20Sopenharmony_ci cpu = nr_cpu_ids; 3588c2ecf20Sopenharmony_ci else 3598c2ecf20Sopenharmony_ci cpu = cpumask_any_and(cpumask_of_node(node), 3608c2ecf20Sopenharmony_ci housekeeping_cpumask(hk_flags)); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci if (cpu < nr_cpu_ids) 3638c2ecf20Sopenharmony_ci error = work_on_cpu(cpu, local_pci_probe, &ddi); 3648c2ecf20Sopenharmony_ci else 3658c2ecf20Sopenharmony_ci error = local_pci_probe(&ddi); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci dev->is_probed = 0; 3688c2ecf20Sopenharmony_ci cpu_hotplug_enable(); 3698c2ecf20Sopenharmony_ci return error; 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci/** 3738c2ecf20Sopenharmony_ci * __pci_device_probe - check if a driver wants to claim a specific PCI device 3748c2ecf20Sopenharmony_ci * @drv: driver to call to check if it wants the PCI device 3758c2ecf20Sopenharmony_ci * @pci_dev: PCI device being probed 3768c2ecf20Sopenharmony_ci * 3778c2ecf20Sopenharmony_ci * returns 0 on success, else error. 3788c2ecf20Sopenharmony_ci * side-effect: pci_dev->driver is set to drv when drv claims pci_dev. 3798c2ecf20Sopenharmony_ci */ 3808c2ecf20Sopenharmony_cistatic int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci const struct pci_device_id *id; 3838c2ecf20Sopenharmony_ci int error = 0; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (!pci_dev->driver && drv->probe) { 3868c2ecf20Sopenharmony_ci error = -ENODEV; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci id = pci_match_device(drv, pci_dev); 3898c2ecf20Sopenharmony_ci if (id) 3908c2ecf20Sopenharmony_ci error = pci_call_probe(drv, pci_dev, id); 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci return error; 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ciint __weak pcibios_alloc_irq(struct pci_dev *dev) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci return 0; 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_civoid __weak pcibios_free_irq(struct pci_dev *dev) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci} 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 4058c2ecf20Sopenharmony_cistatic inline bool pci_device_can_probe(struct pci_dev *pdev) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci return (!pdev->is_virtfn || pdev->physfn->sriov->drivers_autoprobe || 4088c2ecf20Sopenharmony_ci pdev->driver_override); 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci#else 4118c2ecf20Sopenharmony_cistatic inline bool pci_device_can_probe(struct pci_dev *pdev) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci return true; 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci#endif 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cistatic int pci_device_probe(struct device *dev) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci int error; 4208c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 4218c2ecf20Sopenharmony_ci struct pci_driver *drv = to_pci_driver(dev->driver); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci if (!pci_device_can_probe(pci_dev)) 4248c2ecf20Sopenharmony_ci return -ENODEV; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci pci_assign_irq(pci_dev); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci error = pcibios_alloc_irq(pci_dev); 4298c2ecf20Sopenharmony_ci if (error < 0) 4308c2ecf20Sopenharmony_ci return error; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci pci_dev_get(pci_dev); 4338c2ecf20Sopenharmony_ci error = __pci_device_probe(drv, pci_dev); 4348c2ecf20Sopenharmony_ci if (error) { 4358c2ecf20Sopenharmony_ci pcibios_free_irq(pci_dev); 4368c2ecf20Sopenharmony_ci pci_dev_put(pci_dev); 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci return error; 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic int pci_device_remove(struct device *dev) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 4458c2ecf20Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci if (drv->remove) { 4488c2ecf20Sopenharmony_ci pm_runtime_get_sync(dev); 4498c2ecf20Sopenharmony_ci /* 4508c2ecf20Sopenharmony_ci * If the driver provides a .runtime_idle() callback and it has 4518c2ecf20Sopenharmony_ci * started to run already, it may continue to run in parallel 4528c2ecf20Sopenharmony_ci * with the code below, so wait until all of the runtime PM 4538c2ecf20Sopenharmony_ci * activity has completed. 4548c2ecf20Sopenharmony_ci */ 4558c2ecf20Sopenharmony_ci pm_runtime_barrier(dev); 4568c2ecf20Sopenharmony_ci drv->remove(pci_dev); 4578c2ecf20Sopenharmony_ci pm_runtime_put_noidle(dev); 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci pcibios_free_irq(pci_dev); 4608c2ecf20Sopenharmony_ci pci_dev->driver = NULL; 4618c2ecf20Sopenharmony_ci pci_iov_remove(pci_dev); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci /* Undo the runtime PM settings in local_pci_probe() */ 4648c2ecf20Sopenharmony_ci pm_runtime_put_sync(dev); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci /* 4678c2ecf20Sopenharmony_ci * If the device is still on, set the power state as "unknown", 4688c2ecf20Sopenharmony_ci * since it might change by the next time we load the driver. 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_ci if (pci_dev->current_state == PCI_D0) 4718c2ecf20Sopenharmony_ci pci_dev->current_state = PCI_UNKNOWN; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci /* 4748c2ecf20Sopenharmony_ci * We would love to complain here if pci_dev->is_enabled is set, that 4758c2ecf20Sopenharmony_ci * the driver should have called pci_disable_device(), but the 4768c2ecf20Sopenharmony_ci * unfortunate fact is there are too many odd BIOS and bridge setups 4778c2ecf20Sopenharmony_ci * that don't like drivers doing that all of the time. 4788c2ecf20Sopenharmony_ci * Oh well, we can dream of sane hardware when we sleep, no matter how 4798c2ecf20Sopenharmony_ci * horrible the crap we have to deal with is when we are awake... 4808c2ecf20Sopenharmony_ci */ 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci pci_dev_put(pci_dev); 4838c2ecf20Sopenharmony_ci return 0; 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic void pci_device_shutdown(struct device *dev) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 4898c2ecf20Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci pm_runtime_resume(dev); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci if (drv && drv->shutdown) 4948c2ecf20Sopenharmony_ci drv->shutdown(pci_dev); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci /* 4978c2ecf20Sopenharmony_ci * If this is a kexec reboot, turn off Bus Master bit on the 4988c2ecf20Sopenharmony_ci * device to tell it to not continue to do DMA. Don't touch 4998c2ecf20Sopenharmony_ci * devices in D3cold or unknown states. 5008c2ecf20Sopenharmony_ci * If it is not a kexec reboot, firmware will hit the PCI 5018c2ecf20Sopenharmony_ci * devices with big hammer and stop their DMA any way. 5028c2ecf20Sopenharmony_ci */ 5038c2ecf20Sopenharmony_ci if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot)) 5048c2ecf20Sopenharmony_ci pci_clear_master(pci_dev); 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci/* Auxiliary functions used for system resume and run-time resume. */ 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci/** 5128c2ecf20Sopenharmony_ci * pci_restore_standard_config - restore standard config registers of PCI device 5138c2ecf20Sopenharmony_ci * @pci_dev: PCI device to handle 5148c2ecf20Sopenharmony_ci */ 5158c2ecf20Sopenharmony_cistatic int pci_restore_standard_config(struct pci_dev *pci_dev) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci pci_update_current_state(pci_dev, PCI_UNKNOWN); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if (pci_dev->current_state != PCI_D0) { 5208c2ecf20Sopenharmony_ci int error = pci_set_power_state(pci_dev, PCI_D0); 5218c2ecf20Sopenharmony_ci if (error) 5228c2ecf20Sopenharmony_ci return error; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci pci_restore_state(pci_dev); 5268c2ecf20Sopenharmony_ci pci_pme_restore(pci_dev); 5278c2ecf20Sopenharmony_ci return 0; 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic void pci_pm_default_resume(struct pci_dev *pci_dev) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_resume, pci_dev); 5338c2ecf20Sopenharmony_ci pci_enable_wake(pci_dev, PCI_D0, false); 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci#endif 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_cistatic void pci_pm_default_resume_early(struct pci_dev *pci_dev) 5418c2ecf20Sopenharmony_ci{ 5428c2ecf20Sopenharmony_ci pci_power_up(pci_dev); 5438c2ecf20Sopenharmony_ci pci_update_current_state(pci_dev, PCI_D0); 5448c2ecf20Sopenharmony_ci pci_restore_state(pci_dev); 5458c2ecf20Sopenharmony_ci pci_pme_restore(pci_dev); 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci/* 5498c2ecf20Sopenharmony_ci * Default "suspend" method for devices that have no driver provided suspend, 5508c2ecf20Sopenharmony_ci * or not even a driver at all (second part). 5518c2ecf20Sopenharmony_ci */ 5528c2ecf20Sopenharmony_cistatic void pci_pm_set_unknown_state(struct pci_dev *pci_dev) 5538c2ecf20Sopenharmony_ci{ 5548c2ecf20Sopenharmony_ci /* 5558c2ecf20Sopenharmony_ci * mark its power state as "unknown", since we don't know if 5568c2ecf20Sopenharmony_ci * e.g. the BIOS will change its device state when we suspend. 5578c2ecf20Sopenharmony_ci */ 5588c2ecf20Sopenharmony_ci if (pci_dev->current_state == PCI_D0) 5598c2ecf20Sopenharmony_ci pci_dev->current_state = PCI_UNKNOWN; 5608c2ecf20Sopenharmony_ci} 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci/* 5638c2ecf20Sopenharmony_ci * Default "resume" method for devices that have no driver provided resume, 5648c2ecf20Sopenharmony_ci * or not even a driver at all (second part). 5658c2ecf20Sopenharmony_ci */ 5668c2ecf20Sopenharmony_cistatic int pci_pm_reenable_device(struct pci_dev *pci_dev) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci int retval; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci /* if the device was enabled before suspend, reenable */ 5718c2ecf20Sopenharmony_ci retval = pci_reenable_device(pci_dev); 5728c2ecf20Sopenharmony_ci /* 5738c2ecf20Sopenharmony_ci * if the device was busmaster before the suspend, make it busmaster 5748c2ecf20Sopenharmony_ci * again 5758c2ecf20Sopenharmony_ci */ 5768c2ecf20Sopenharmony_ci if (pci_dev->is_busmaster) 5778c2ecf20Sopenharmony_ci pci_set_master(pci_dev); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci return retval; 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic int pci_legacy_suspend(struct device *dev, pm_message_t state) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 5858c2ecf20Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci if (drv && drv->suspend) { 5888c2ecf20Sopenharmony_ci pci_power_t prev = pci_dev->current_state; 5898c2ecf20Sopenharmony_ci int error; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci error = drv->suspend(pci_dev, state); 5928c2ecf20Sopenharmony_ci suspend_report_result(drv->suspend, error); 5938c2ecf20Sopenharmony_ci if (error) 5948c2ecf20Sopenharmony_ci return error; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 5978c2ecf20Sopenharmony_ci && pci_dev->current_state != PCI_UNKNOWN) { 5988c2ecf20Sopenharmony_ci pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 5998c2ecf20Sopenharmony_ci "PCI PM: Device state not saved by %pS\n", 6008c2ecf20Sopenharmony_ci drv->suspend); 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_suspend, pci_dev); 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci return 0; 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_cistatic int pci_legacy_suspend_late(struct device *dev, pm_message_t state) 6108c2ecf20Sopenharmony_ci{ 6118c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (!pci_dev->state_saved) 6148c2ecf20Sopenharmony_ci pci_save_state(pci_dev); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci pci_pm_set_unknown_state(pci_dev); 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_suspend_late, pci_dev); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci return 0; 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_cistatic int pci_legacy_resume(struct device *dev) 6248c2ecf20Sopenharmony_ci{ 6258c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 6268c2ecf20Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_resume, pci_dev); 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci return drv && drv->resume ? 6318c2ecf20Sopenharmony_ci drv->resume(pci_dev) : pci_pm_reenable_device(pci_dev); 6328c2ecf20Sopenharmony_ci} 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci/* Auxiliary functions used by the new power management framework */ 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic void pci_pm_default_suspend(struct pci_dev *pci_dev) 6378c2ecf20Sopenharmony_ci{ 6388c2ecf20Sopenharmony_ci /* Disable non-bridge devices without PM support */ 6398c2ecf20Sopenharmony_ci if (!pci_has_subordinate(pci_dev)) 6408c2ecf20Sopenharmony_ci pci_disable_enabled_device(pci_dev); 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_cistatic bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) 6448c2ecf20Sopenharmony_ci{ 6458c2ecf20Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 6468c2ecf20Sopenharmony_ci bool ret = drv && (drv->suspend || drv->resume); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci /* 6498c2ecf20Sopenharmony_ci * Legacy PM support is used by default, so warn if the new framework is 6508c2ecf20Sopenharmony_ci * supported as well. Drivers are supposed to support either the 6518c2ecf20Sopenharmony_ci * former, or the latter, but not both at the same time. 6528c2ecf20Sopenharmony_ci */ 6538c2ecf20Sopenharmony_ci pci_WARN(pci_dev, ret && drv->driver.pm, "device %04x:%04x\n", 6548c2ecf20Sopenharmony_ci pci_dev->vendor, pci_dev->device); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci return ret; 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci/* New power management framework */ 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_cistatic int pci_pm_prepare(struct device *dev) 6628c2ecf20Sopenharmony_ci{ 6638c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 6648c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci if (pm && pm->prepare) { 6678c2ecf20Sopenharmony_ci int error = pm->prepare(dev); 6688c2ecf20Sopenharmony_ci if (error < 0) 6698c2ecf20Sopenharmony_ci return error; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci if (!error && dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_PREPARE)) 6728c2ecf20Sopenharmony_ci return 0; 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci if (pci_dev_need_resume(pci_dev)) 6758c2ecf20Sopenharmony_ci return 0; 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci /* 6788c2ecf20Sopenharmony_ci * The PME setting needs to be adjusted here in case the direct-complete 6798c2ecf20Sopenharmony_ci * optimization is used with respect to this device. 6808c2ecf20Sopenharmony_ci */ 6818c2ecf20Sopenharmony_ci pci_dev_adjust_pme(pci_dev); 6828c2ecf20Sopenharmony_ci return 1; 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic void pci_pm_complete(struct device *dev) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci pci_dev_complete_resume(pci_dev); 6908c2ecf20Sopenharmony_ci pm_generic_complete(dev); 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci /* Resume device if platform firmware has put it in reset-power-on */ 6938c2ecf20Sopenharmony_ci if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) { 6948c2ecf20Sopenharmony_ci pci_power_t pre_sleep_state = pci_dev->current_state; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci pci_refresh_power_state(pci_dev); 6978c2ecf20Sopenharmony_ci /* 6988c2ecf20Sopenharmony_ci * On platforms with ACPI this check may also trigger for 6998c2ecf20Sopenharmony_ci * devices sharing power resources if one of those power 7008c2ecf20Sopenharmony_ci * resources has been activated as a result of a change of the 7018c2ecf20Sopenharmony_ci * power state of another device sharing it. However, in that 7028c2ecf20Sopenharmony_ci * case it is also better to resume the device, in general. 7038c2ecf20Sopenharmony_ci */ 7048c2ecf20Sopenharmony_ci if (pci_dev->current_state < pre_sleep_state) 7058c2ecf20Sopenharmony_ci pm_request_resume(dev); 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci#else /* !CONFIG_PM_SLEEP */ 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci#define pci_pm_prepare NULL 7128c2ecf20Sopenharmony_ci#define pci_pm_complete NULL 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci#endif /* !CONFIG_PM_SLEEP */ 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci#ifdef CONFIG_SUSPEND 7178c2ecf20Sopenharmony_cistatic void pcie_pme_root_status_cleanup(struct pci_dev *pci_dev) 7188c2ecf20Sopenharmony_ci{ 7198c2ecf20Sopenharmony_ci /* 7208c2ecf20Sopenharmony_ci * Some BIOSes forget to clear Root PME Status bits after system 7218c2ecf20Sopenharmony_ci * wakeup, which breaks ACPI-based runtime wakeup on PCI Express. 7228c2ecf20Sopenharmony_ci * Clear those bits now just in case (shouldn't hurt). 7238c2ecf20Sopenharmony_ci */ 7248c2ecf20Sopenharmony_ci if (pci_is_pcie(pci_dev) && 7258c2ecf20Sopenharmony_ci (pci_pcie_type(pci_dev) == PCI_EXP_TYPE_ROOT_PORT || 7268c2ecf20Sopenharmony_ci pci_pcie_type(pci_dev) == PCI_EXP_TYPE_RC_EC)) 7278c2ecf20Sopenharmony_ci pcie_clear_root_pme_status(pci_dev); 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_cistatic int pci_pm_suspend(struct device *dev) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 7338c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci pci_dev->skip_bus_pm = false; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 7388c2ecf20Sopenharmony_ci return pci_legacy_suspend(dev, PMSG_SUSPEND); 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci if (!pm) { 7418c2ecf20Sopenharmony_ci pci_pm_default_suspend(pci_dev); 7428c2ecf20Sopenharmony_ci return 0; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* 7468c2ecf20Sopenharmony_ci * PCI devices suspended at run time may need to be resumed at this 7478c2ecf20Sopenharmony_ci * point, because in general it may be necessary to reconfigure them for 7488c2ecf20Sopenharmony_ci * system suspend. Namely, if the device is expected to wake up the 7498c2ecf20Sopenharmony_ci * system from the sleep state, it may have to be reconfigured for this 7508c2ecf20Sopenharmony_ci * purpose, or if the device is not expected to wake up the system from 7518c2ecf20Sopenharmony_ci * the sleep state, it should be prevented from signaling wakeup events 7528c2ecf20Sopenharmony_ci * going forward. 7538c2ecf20Sopenharmony_ci * 7548c2ecf20Sopenharmony_ci * Also if the driver of the device does not indicate that its system 7558c2ecf20Sopenharmony_ci * suspend callbacks can cope with runtime-suspended devices, it is 7568c2ecf20Sopenharmony_ci * better to resume the device from runtime suspend here. 7578c2ecf20Sopenharmony_ci */ 7588c2ecf20Sopenharmony_ci if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || 7598c2ecf20Sopenharmony_ci pci_dev_need_resume(pci_dev)) { 7608c2ecf20Sopenharmony_ci pm_runtime_resume(dev); 7618c2ecf20Sopenharmony_ci pci_dev->state_saved = false; 7628c2ecf20Sopenharmony_ci } else { 7638c2ecf20Sopenharmony_ci pci_dev_adjust_pme(pci_dev); 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci if (pm->suspend) { 7678c2ecf20Sopenharmony_ci pci_power_t prev = pci_dev->current_state; 7688c2ecf20Sopenharmony_ci int error; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci error = pm->suspend(dev); 7718c2ecf20Sopenharmony_ci suspend_report_result(pm->suspend, error); 7728c2ecf20Sopenharmony_ci if (error) 7738c2ecf20Sopenharmony_ci return error; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 7768c2ecf20Sopenharmony_ci && pci_dev->current_state != PCI_UNKNOWN) { 7778c2ecf20Sopenharmony_ci pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 7788c2ecf20Sopenharmony_ci "PCI PM: State of device not saved by %pS\n", 7798c2ecf20Sopenharmony_ci pm->suspend); 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci return 0; 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_cistatic int pci_pm_suspend_late(struct device *dev) 7878c2ecf20Sopenharmony_ci{ 7888c2ecf20Sopenharmony_ci if (dev_pm_skip_suspend(dev)) 7898c2ecf20Sopenharmony_ci return 0; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev)); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci return pm_generic_suspend_late(dev); 7948c2ecf20Sopenharmony_ci} 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_cistatic int pci_pm_suspend_noirq(struct device *dev) 7978c2ecf20Sopenharmony_ci{ 7988c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 7998c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (dev_pm_skip_suspend(dev)) 8028c2ecf20Sopenharmony_ci return 0; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 8058c2ecf20Sopenharmony_ci return pci_legacy_suspend_late(dev, PMSG_SUSPEND); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (!pm) { 8088c2ecf20Sopenharmony_ci pci_save_state(pci_dev); 8098c2ecf20Sopenharmony_ci goto Fixup; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci if (pm->suspend_noirq) { 8138c2ecf20Sopenharmony_ci pci_power_t prev = pci_dev->current_state; 8148c2ecf20Sopenharmony_ci int error; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci error = pm->suspend_noirq(dev); 8178c2ecf20Sopenharmony_ci suspend_report_result(pm->suspend_noirq, error); 8188c2ecf20Sopenharmony_ci if (error) 8198c2ecf20Sopenharmony_ci return error; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 8228c2ecf20Sopenharmony_ci && pci_dev->current_state != PCI_UNKNOWN) { 8238c2ecf20Sopenharmony_ci pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 8248c2ecf20Sopenharmony_ci "PCI PM: State of device not saved by %pS\n", 8258c2ecf20Sopenharmony_ci pm->suspend_noirq); 8268c2ecf20Sopenharmony_ci goto Fixup; 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci if (pci_dev->skip_bus_pm) { 8318c2ecf20Sopenharmony_ci /* 8328c2ecf20Sopenharmony_ci * Either the device is a bridge with a child in D0 below it, or 8338c2ecf20Sopenharmony_ci * the function is running for the second time in a row without 8348c2ecf20Sopenharmony_ci * going through full resume, which is possible only during 8358c2ecf20Sopenharmony_ci * suspend-to-idle in a spurious wakeup case. The device should 8368c2ecf20Sopenharmony_ci * be in D0 at this point, but if it is a bridge, it may be 8378c2ecf20Sopenharmony_ci * necessary to save its state. 8388c2ecf20Sopenharmony_ci */ 8398c2ecf20Sopenharmony_ci if (!pci_dev->state_saved) 8408c2ecf20Sopenharmony_ci pci_save_state(pci_dev); 8418c2ecf20Sopenharmony_ci } else if (!pci_dev->state_saved) { 8428c2ecf20Sopenharmony_ci pci_save_state(pci_dev); 8438c2ecf20Sopenharmony_ci if (pci_power_manageable(pci_dev)) 8448c2ecf20Sopenharmony_ci pci_prepare_to_sleep(pci_dev); 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci pci_dbg(pci_dev, "PCI PM: Suspend power state: %s\n", 8488c2ecf20Sopenharmony_ci pci_power_name(pci_dev->current_state)); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci if (pci_dev->current_state == PCI_D0) { 8518c2ecf20Sopenharmony_ci pci_dev->skip_bus_pm = true; 8528c2ecf20Sopenharmony_ci /* 8538c2ecf20Sopenharmony_ci * Per PCI PM r1.2, table 6-1, a bridge must be in D0 if any 8548c2ecf20Sopenharmony_ci * downstream device is in D0, so avoid changing the power state 8558c2ecf20Sopenharmony_ci * of the parent bridge by setting the skip_bus_pm flag for it. 8568c2ecf20Sopenharmony_ci */ 8578c2ecf20Sopenharmony_ci if (pci_dev->bus->self) 8588c2ecf20Sopenharmony_ci pci_dev->bus->self->skip_bus_pm = true; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci if (pci_dev->skip_bus_pm && pm_suspend_no_platform()) { 8628c2ecf20Sopenharmony_ci pci_dbg(pci_dev, "PCI PM: Skipped\n"); 8638c2ecf20Sopenharmony_ci goto Fixup; 8648c2ecf20Sopenharmony_ci } 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci pci_pm_set_unknown_state(pci_dev); 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci /* 8698c2ecf20Sopenharmony_ci * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's 8708c2ecf20Sopenharmony_ci * PCI COMMAND register isn't 0, the BIOS assumes that the controller 8718c2ecf20Sopenharmony_ci * hasn't been quiesced and tries to turn it off. If the controller 8728c2ecf20Sopenharmony_ci * is already in D3, this can hang or cause memory corruption. 8738c2ecf20Sopenharmony_ci * 8748c2ecf20Sopenharmony_ci * Since the value of the COMMAND register doesn't matter once the 8758c2ecf20Sopenharmony_ci * device has been suspended, we can safely set it to 0 here. 8768c2ecf20Sopenharmony_ci */ 8778c2ecf20Sopenharmony_ci if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) 8788c2ecf20Sopenharmony_ci pci_write_config_word(pci_dev, PCI_COMMAND, 0); 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ciFixup: 8818c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_suspend_late, pci_dev); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci /* 8848c2ecf20Sopenharmony_ci * If the target system sleep state is suspend-to-idle, it is sufficient 8858c2ecf20Sopenharmony_ci * to check whether or not the device's wakeup settings are good for 8868c2ecf20Sopenharmony_ci * runtime PM. Otherwise, the pm_resume_via_firmware() check will cause 8878c2ecf20Sopenharmony_ci * pci_pm_complete() to take care of fixing up the device's state 8888c2ecf20Sopenharmony_ci * anyway, if need be. 8898c2ecf20Sopenharmony_ci */ 8908c2ecf20Sopenharmony_ci if (device_can_wakeup(dev) && !device_may_wakeup(dev)) 8918c2ecf20Sopenharmony_ci dev->power.may_skip_resume = false; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci return 0; 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_cistatic int pci_pm_resume_noirq(struct device *dev) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 8998c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 9008c2ecf20Sopenharmony_ci pci_power_t prev_state = pci_dev->current_state; 9018c2ecf20Sopenharmony_ci bool skip_bus_pm = pci_dev->skip_bus_pm; 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci if (dev_pm_skip_resume(dev)) 9048c2ecf20Sopenharmony_ci return 0; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci /* 9078c2ecf20Sopenharmony_ci * In the suspend-to-idle case, devices left in D0 during suspend will 9088c2ecf20Sopenharmony_ci * stay in D0, so it is not necessary to restore or update their 9098c2ecf20Sopenharmony_ci * configuration here and attempting to put them into D0 again is 9108c2ecf20Sopenharmony_ci * pointless, so avoid doing that. 9118c2ecf20Sopenharmony_ci */ 9128c2ecf20Sopenharmony_ci if (!(skip_bus_pm && pm_suspend_no_platform())) 9138c2ecf20Sopenharmony_ci pci_pm_default_resume_early(pci_dev); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_resume_early, pci_dev); 9168c2ecf20Sopenharmony_ci pcie_pme_root_status_cleanup(pci_dev); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci if (!skip_bus_pm && prev_state == PCI_D3cold) 9198c2ecf20Sopenharmony_ci pci_bridge_wait_for_secondary_bus(pci_dev, "resume", PCI_RESET_WAIT); 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 9228c2ecf20Sopenharmony_ci return 0; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci if (pm && pm->resume_noirq) 9258c2ecf20Sopenharmony_ci return pm->resume_noirq(dev); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci return 0; 9288c2ecf20Sopenharmony_ci} 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_cistatic int pci_pm_resume_early(struct device *dev) 9318c2ecf20Sopenharmony_ci{ 9328c2ecf20Sopenharmony_ci if (dev_pm_skip_resume(dev)) 9338c2ecf20Sopenharmony_ci return 0; 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci return pm_generic_resume_early(dev); 9368c2ecf20Sopenharmony_ci} 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_cistatic int pci_pm_resume(struct device *dev) 9398c2ecf20Sopenharmony_ci{ 9408c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 9418c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci /* 9448c2ecf20Sopenharmony_ci * This is necessary for the suspend error path in which resume is 9458c2ecf20Sopenharmony_ci * called without restoring the standard config registers of the device. 9468c2ecf20Sopenharmony_ci */ 9478c2ecf20Sopenharmony_ci if (pci_dev->state_saved) 9488c2ecf20Sopenharmony_ci pci_restore_standard_config(pci_dev); 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 9518c2ecf20Sopenharmony_ci return pci_legacy_resume(dev); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci pci_pm_default_resume(pci_dev); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (pm) { 9568c2ecf20Sopenharmony_ci if (pm->resume) 9578c2ecf20Sopenharmony_ci return pm->resume(dev); 9588c2ecf20Sopenharmony_ci } else { 9598c2ecf20Sopenharmony_ci pci_pm_reenable_device(pci_dev); 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci return 0; 9638c2ecf20Sopenharmony_ci} 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci#else /* !CONFIG_SUSPEND */ 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci#define pci_pm_suspend NULL 9688c2ecf20Sopenharmony_ci#define pci_pm_suspend_late NULL 9698c2ecf20Sopenharmony_ci#define pci_pm_suspend_noirq NULL 9708c2ecf20Sopenharmony_ci#define pci_pm_resume NULL 9718c2ecf20Sopenharmony_ci#define pci_pm_resume_early NULL 9728c2ecf20Sopenharmony_ci#define pci_pm_resume_noirq NULL 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci#endif /* !CONFIG_SUSPEND */ 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci#ifdef CONFIG_HIBERNATE_CALLBACKS 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_cistatic int pci_pm_freeze(struct device *dev) 9798c2ecf20Sopenharmony_ci{ 9808c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 9818c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 9848c2ecf20Sopenharmony_ci return pci_legacy_suspend(dev, PMSG_FREEZE); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci if (!pm) { 9878c2ecf20Sopenharmony_ci pci_pm_default_suspend(pci_dev); 9888c2ecf20Sopenharmony_ci return 0; 9898c2ecf20Sopenharmony_ci } 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci /* 9928c2ecf20Sopenharmony_ci * Resume all runtime-suspended devices before creating a snapshot 9938c2ecf20Sopenharmony_ci * image of system memory, because the restore kernel generally cannot 9948c2ecf20Sopenharmony_ci * be expected to always handle them consistently and they need to be 9958c2ecf20Sopenharmony_ci * put into the runtime-active metastate during system resume anyway, 9968c2ecf20Sopenharmony_ci * so it is better to ensure that the state saved in the image will be 9978c2ecf20Sopenharmony_ci * always consistent with that. 9988c2ecf20Sopenharmony_ci */ 9998c2ecf20Sopenharmony_ci pm_runtime_resume(dev); 10008c2ecf20Sopenharmony_ci pci_dev->state_saved = false; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci if (pm->freeze) { 10038c2ecf20Sopenharmony_ci int error; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci error = pm->freeze(dev); 10068c2ecf20Sopenharmony_ci suspend_report_result(pm->freeze, error); 10078c2ecf20Sopenharmony_ci if (error) 10088c2ecf20Sopenharmony_ci return error; 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci return 0; 10128c2ecf20Sopenharmony_ci} 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_cistatic int pci_pm_freeze_noirq(struct device *dev) 10158c2ecf20Sopenharmony_ci{ 10168c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 10178c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 10208c2ecf20Sopenharmony_ci return pci_legacy_suspend_late(dev, PMSG_FREEZE); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci if (pm && pm->freeze_noirq) { 10238c2ecf20Sopenharmony_ci int error; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci error = pm->freeze_noirq(dev); 10268c2ecf20Sopenharmony_ci suspend_report_result(pm->freeze_noirq, error); 10278c2ecf20Sopenharmony_ci if (error) 10288c2ecf20Sopenharmony_ci return error; 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci if (!pci_dev->state_saved) 10328c2ecf20Sopenharmony_ci pci_save_state(pci_dev); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci pci_pm_set_unknown_state(pci_dev); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci return 0; 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_cistatic int pci_pm_thaw_noirq(struct device *dev) 10408c2ecf20Sopenharmony_ci{ 10418c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 10428c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci /* 10458c2ecf20Sopenharmony_ci * The pm->thaw_noirq() callback assumes the device has been 10468c2ecf20Sopenharmony_ci * returned to D0 and its config state has been restored. 10478c2ecf20Sopenharmony_ci * 10488c2ecf20Sopenharmony_ci * In addition, pci_restore_state() restores MSI-X state in MMIO 10498c2ecf20Sopenharmony_ci * space, which requires the device to be in D0, so return it to D0 10508c2ecf20Sopenharmony_ci * in case the driver's "freeze" callbacks put it into a low-power 10518c2ecf20Sopenharmony_ci * state. 10528c2ecf20Sopenharmony_ci */ 10538c2ecf20Sopenharmony_ci pci_set_power_state(pci_dev, PCI_D0); 10548c2ecf20Sopenharmony_ci pci_restore_state(pci_dev); 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 10578c2ecf20Sopenharmony_ci return 0; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci if (pm && pm->thaw_noirq) 10608c2ecf20Sopenharmony_ci return pm->thaw_noirq(dev); 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci return 0; 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_cistatic int pci_pm_thaw(struct device *dev) 10668c2ecf20Sopenharmony_ci{ 10678c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 10688c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 10698c2ecf20Sopenharmony_ci int error = 0; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 10728c2ecf20Sopenharmony_ci return pci_legacy_resume(dev); 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci if (pm) { 10758c2ecf20Sopenharmony_ci if (pm->thaw) 10768c2ecf20Sopenharmony_ci error = pm->thaw(dev); 10778c2ecf20Sopenharmony_ci } else { 10788c2ecf20Sopenharmony_ci pci_pm_reenable_device(pci_dev); 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci pci_dev->state_saved = false; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci return error; 10848c2ecf20Sopenharmony_ci} 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_cistatic int pci_pm_poweroff(struct device *dev) 10878c2ecf20Sopenharmony_ci{ 10888c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 10898c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 10928c2ecf20Sopenharmony_ci return pci_legacy_suspend(dev, PMSG_HIBERNATE); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci if (!pm) { 10958c2ecf20Sopenharmony_ci pci_pm_default_suspend(pci_dev); 10968c2ecf20Sopenharmony_ci return 0; 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci /* The reason to do that is the same as in pci_pm_suspend(). */ 11008c2ecf20Sopenharmony_ci if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || 11018c2ecf20Sopenharmony_ci pci_dev_need_resume(pci_dev)) { 11028c2ecf20Sopenharmony_ci pm_runtime_resume(dev); 11038c2ecf20Sopenharmony_ci pci_dev->state_saved = false; 11048c2ecf20Sopenharmony_ci } else { 11058c2ecf20Sopenharmony_ci pci_dev_adjust_pme(pci_dev); 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci if (pm->poweroff) { 11098c2ecf20Sopenharmony_ci int error; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci error = pm->poweroff(dev); 11128c2ecf20Sopenharmony_ci suspend_report_result(pm->poweroff, error); 11138c2ecf20Sopenharmony_ci if (error) 11148c2ecf20Sopenharmony_ci return error; 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci return 0; 11188c2ecf20Sopenharmony_ci} 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_cistatic int pci_pm_poweroff_late(struct device *dev) 11218c2ecf20Sopenharmony_ci{ 11228c2ecf20Sopenharmony_ci if (dev_pm_skip_suspend(dev)) 11238c2ecf20Sopenharmony_ci return 0; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev)); 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci return pm_generic_poweroff_late(dev); 11288c2ecf20Sopenharmony_ci} 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_cistatic int pci_pm_poweroff_noirq(struct device *dev) 11318c2ecf20Sopenharmony_ci{ 11328c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 11338c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci if (dev_pm_skip_suspend(dev)) 11368c2ecf20Sopenharmony_ci return 0; 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 11398c2ecf20Sopenharmony_ci return pci_legacy_suspend_late(dev, PMSG_HIBERNATE); 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci if (!pm) { 11428c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_suspend_late, pci_dev); 11438c2ecf20Sopenharmony_ci return 0; 11448c2ecf20Sopenharmony_ci } 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci if (pm->poweroff_noirq) { 11478c2ecf20Sopenharmony_ci int error; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci error = pm->poweroff_noirq(dev); 11508c2ecf20Sopenharmony_ci suspend_report_result(pm->poweroff_noirq, error); 11518c2ecf20Sopenharmony_ci if (error) 11528c2ecf20Sopenharmony_ci return error; 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci if (!pci_dev->state_saved && !pci_has_subordinate(pci_dev)) 11568c2ecf20Sopenharmony_ci pci_prepare_to_sleep(pci_dev); 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci /* 11598c2ecf20Sopenharmony_ci * The reason for doing this here is the same as for the analogous code 11608c2ecf20Sopenharmony_ci * in pci_pm_suspend_noirq(). 11618c2ecf20Sopenharmony_ci */ 11628c2ecf20Sopenharmony_ci if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) 11638c2ecf20Sopenharmony_ci pci_write_config_word(pci_dev, PCI_COMMAND, 0); 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_suspend_late, pci_dev); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci return 0; 11688c2ecf20Sopenharmony_ci} 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_cistatic int pci_pm_restore_noirq(struct device *dev) 11718c2ecf20Sopenharmony_ci{ 11728c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 11738c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci pci_pm_default_resume_early(pci_dev); 11768c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_resume_early, pci_dev); 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 11798c2ecf20Sopenharmony_ci return 0; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci if (pm && pm->restore_noirq) 11828c2ecf20Sopenharmony_ci return pm->restore_noirq(dev); 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci return 0; 11858c2ecf20Sopenharmony_ci} 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_cistatic int pci_pm_restore(struct device *dev) 11888c2ecf20Sopenharmony_ci{ 11898c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 11908c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci /* 11938c2ecf20Sopenharmony_ci * This is necessary for the hibernation error path in which restore is 11948c2ecf20Sopenharmony_ci * called without restoring the standard config registers of the device. 11958c2ecf20Sopenharmony_ci */ 11968c2ecf20Sopenharmony_ci if (pci_dev->state_saved) 11978c2ecf20Sopenharmony_ci pci_restore_standard_config(pci_dev); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 12008c2ecf20Sopenharmony_ci return pci_legacy_resume(dev); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci pci_pm_default_resume(pci_dev); 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci if (pm) { 12058c2ecf20Sopenharmony_ci if (pm->restore) 12068c2ecf20Sopenharmony_ci return pm->restore(dev); 12078c2ecf20Sopenharmony_ci } else { 12088c2ecf20Sopenharmony_ci pci_pm_reenable_device(pci_dev); 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci return 0; 12128c2ecf20Sopenharmony_ci} 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci#else /* !CONFIG_HIBERNATE_CALLBACKS */ 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci#define pci_pm_freeze NULL 12178c2ecf20Sopenharmony_ci#define pci_pm_freeze_noirq NULL 12188c2ecf20Sopenharmony_ci#define pci_pm_thaw NULL 12198c2ecf20Sopenharmony_ci#define pci_pm_thaw_noirq NULL 12208c2ecf20Sopenharmony_ci#define pci_pm_poweroff NULL 12218c2ecf20Sopenharmony_ci#define pci_pm_poweroff_late NULL 12228c2ecf20Sopenharmony_ci#define pci_pm_poweroff_noirq NULL 12238c2ecf20Sopenharmony_ci#define pci_pm_restore NULL 12248c2ecf20Sopenharmony_ci#define pci_pm_restore_noirq NULL 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci#endif /* !CONFIG_HIBERNATE_CALLBACKS */ 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_cistatic int pci_pm_runtime_suspend(struct device *dev) 12318c2ecf20Sopenharmony_ci{ 12328c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 12338c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 12348c2ecf20Sopenharmony_ci pci_power_t prev = pci_dev->current_state; 12358c2ecf20Sopenharmony_ci int error; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* 12388c2ecf20Sopenharmony_ci * If pci_dev->driver is not set (unbound), we leave the device in D0, 12398c2ecf20Sopenharmony_ci * but it may go to D3cold when the bridge above it runtime suspends. 12408c2ecf20Sopenharmony_ci * Save its config space in case that happens. 12418c2ecf20Sopenharmony_ci */ 12428c2ecf20Sopenharmony_ci if (!pci_dev->driver) { 12438c2ecf20Sopenharmony_ci pci_save_state(pci_dev); 12448c2ecf20Sopenharmony_ci return 0; 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci pci_dev->state_saved = false; 12488c2ecf20Sopenharmony_ci if (pm && pm->runtime_suspend) { 12498c2ecf20Sopenharmony_ci error = pm->runtime_suspend(dev); 12508c2ecf20Sopenharmony_ci /* 12518c2ecf20Sopenharmony_ci * -EBUSY and -EAGAIN is used to request the runtime PM core 12528c2ecf20Sopenharmony_ci * to schedule a new suspend, so log the event only with debug 12538c2ecf20Sopenharmony_ci * log level. 12548c2ecf20Sopenharmony_ci */ 12558c2ecf20Sopenharmony_ci if (error == -EBUSY || error == -EAGAIN) { 12568c2ecf20Sopenharmony_ci pci_dbg(pci_dev, "can't suspend now (%ps returned %d)\n", 12578c2ecf20Sopenharmony_ci pm->runtime_suspend, error); 12588c2ecf20Sopenharmony_ci return error; 12598c2ecf20Sopenharmony_ci } else if (error) { 12608c2ecf20Sopenharmony_ci pci_err(pci_dev, "can't suspend (%ps returned %d)\n", 12618c2ecf20Sopenharmony_ci pm->runtime_suspend, error); 12628c2ecf20Sopenharmony_ci return error; 12638c2ecf20Sopenharmony_ci } 12648c2ecf20Sopenharmony_ci } 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_suspend, pci_dev); 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci if (pm && pm->runtime_suspend 12698c2ecf20Sopenharmony_ci && !pci_dev->state_saved && pci_dev->current_state != PCI_D0 12708c2ecf20Sopenharmony_ci && pci_dev->current_state != PCI_UNKNOWN) { 12718c2ecf20Sopenharmony_ci pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 12728c2ecf20Sopenharmony_ci "PCI PM: State of device not saved by %pS\n", 12738c2ecf20Sopenharmony_ci pm->runtime_suspend); 12748c2ecf20Sopenharmony_ci return 0; 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci if (!pci_dev->state_saved) { 12788c2ecf20Sopenharmony_ci pci_save_state(pci_dev); 12798c2ecf20Sopenharmony_ci pci_finish_runtime_suspend(pci_dev); 12808c2ecf20Sopenharmony_ci } 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci return 0; 12838c2ecf20Sopenharmony_ci} 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_cistatic int pci_pm_runtime_resume(struct device *dev) 12868c2ecf20Sopenharmony_ci{ 12878c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 12888c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 12898c2ecf20Sopenharmony_ci pci_power_t prev_state = pci_dev->current_state; 12908c2ecf20Sopenharmony_ci int error = 0; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci /* 12938c2ecf20Sopenharmony_ci * Restoring config space is necessary even if the device is not bound 12948c2ecf20Sopenharmony_ci * to a driver because although we left it in D0, it may have gone to 12958c2ecf20Sopenharmony_ci * D3cold when the bridge above it runtime suspended. 12968c2ecf20Sopenharmony_ci */ 12978c2ecf20Sopenharmony_ci pci_restore_standard_config(pci_dev); 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci if (!pci_dev->driver) 13008c2ecf20Sopenharmony_ci return 0; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci pci_fixup_device(pci_fixup_resume_early, pci_dev); 13038c2ecf20Sopenharmony_ci pci_pm_default_resume(pci_dev); 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci if (prev_state == PCI_D3cold) 13068c2ecf20Sopenharmony_ci pci_bridge_wait_for_secondary_bus(pci_dev, "resume", PCI_RESET_WAIT); 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (pm && pm->runtime_resume) 13098c2ecf20Sopenharmony_ci error = pm->runtime_resume(dev); 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci pci_dev->runtime_d3cold = false; 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci return error; 13148c2ecf20Sopenharmony_ci} 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_cistatic int pci_pm_runtime_idle(struct device *dev) 13178c2ecf20Sopenharmony_ci{ 13188c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 13198c2ecf20Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci /* 13228c2ecf20Sopenharmony_ci * If pci_dev->driver is not set (unbound), the device should 13238c2ecf20Sopenharmony_ci * always remain in D0 regardless of the runtime PM status 13248c2ecf20Sopenharmony_ci */ 13258c2ecf20Sopenharmony_ci if (!pci_dev->driver) 13268c2ecf20Sopenharmony_ci return 0; 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci if (!pm) 13298c2ecf20Sopenharmony_ci return -ENOSYS; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci if (pm->runtime_idle) 13328c2ecf20Sopenharmony_ci return pm->runtime_idle(dev); 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci return 0; 13358c2ecf20Sopenharmony_ci} 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_cistatic const struct dev_pm_ops pci_dev_pm_ops = { 13388c2ecf20Sopenharmony_ci .prepare = pci_pm_prepare, 13398c2ecf20Sopenharmony_ci .complete = pci_pm_complete, 13408c2ecf20Sopenharmony_ci .suspend = pci_pm_suspend, 13418c2ecf20Sopenharmony_ci .suspend_late = pci_pm_suspend_late, 13428c2ecf20Sopenharmony_ci .resume = pci_pm_resume, 13438c2ecf20Sopenharmony_ci .resume_early = pci_pm_resume_early, 13448c2ecf20Sopenharmony_ci .freeze = pci_pm_freeze, 13458c2ecf20Sopenharmony_ci .thaw = pci_pm_thaw, 13468c2ecf20Sopenharmony_ci .poweroff = pci_pm_poweroff, 13478c2ecf20Sopenharmony_ci .poweroff_late = pci_pm_poweroff_late, 13488c2ecf20Sopenharmony_ci .restore = pci_pm_restore, 13498c2ecf20Sopenharmony_ci .suspend_noirq = pci_pm_suspend_noirq, 13508c2ecf20Sopenharmony_ci .resume_noirq = pci_pm_resume_noirq, 13518c2ecf20Sopenharmony_ci .freeze_noirq = pci_pm_freeze_noirq, 13528c2ecf20Sopenharmony_ci .thaw_noirq = pci_pm_thaw_noirq, 13538c2ecf20Sopenharmony_ci .poweroff_noirq = pci_pm_poweroff_noirq, 13548c2ecf20Sopenharmony_ci .restore_noirq = pci_pm_restore_noirq, 13558c2ecf20Sopenharmony_ci .runtime_suspend = pci_pm_runtime_suspend, 13568c2ecf20Sopenharmony_ci .runtime_resume = pci_pm_runtime_resume, 13578c2ecf20Sopenharmony_ci .runtime_idle = pci_pm_runtime_idle, 13588c2ecf20Sopenharmony_ci}; 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci#define PCI_PM_OPS_PTR (&pci_dev_pm_ops) 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci#else /* !CONFIG_PM */ 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci#define pci_pm_runtime_suspend NULL 13658c2ecf20Sopenharmony_ci#define pci_pm_runtime_resume NULL 13668c2ecf20Sopenharmony_ci#define pci_pm_runtime_idle NULL 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci#define PCI_PM_OPS_PTR NULL 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci#endif /* !CONFIG_PM */ 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci/** 13738c2ecf20Sopenharmony_ci * __pci_register_driver - register a new pci driver 13748c2ecf20Sopenharmony_ci * @drv: the driver structure to register 13758c2ecf20Sopenharmony_ci * @owner: owner module of drv 13768c2ecf20Sopenharmony_ci * @mod_name: module name string 13778c2ecf20Sopenharmony_ci * 13788c2ecf20Sopenharmony_ci * Adds the driver structure to the list of registered drivers. 13798c2ecf20Sopenharmony_ci * Returns a negative value on error, otherwise 0. 13808c2ecf20Sopenharmony_ci * If no error occurred, the driver remains registered even if 13818c2ecf20Sopenharmony_ci * no device was claimed during registration. 13828c2ecf20Sopenharmony_ci */ 13838c2ecf20Sopenharmony_ciint __pci_register_driver(struct pci_driver *drv, struct module *owner, 13848c2ecf20Sopenharmony_ci const char *mod_name) 13858c2ecf20Sopenharmony_ci{ 13868c2ecf20Sopenharmony_ci /* initialize common driver fields */ 13878c2ecf20Sopenharmony_ci drv->driver.name = drv->name; 13888c2ecf20Sopenharmony_ci drv->driver.bus = &pci_bus_type; 13898c2ecf20Sopenharmony_ci drv->driver.owner = owner; 13908c2ecf20Sopenharmony_ci drv->driver.mod_name = mod_name; 13918c2ecf20Sopenharmony_ci drv->driver.groups = drv->groups; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci spin_lock_init(&drv->dynids.lock); 13948c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&drv->dynids.list); 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci /* register with core */ 13978c2ecf20Sopenharmony_ci return driver_register(&drv->driver); 13988c2ecf20Sopenharmony_ci} 13998c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__pci_register_driver); 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci/** 14028c2ecf20Sopenharmony_ci * pci_unregister_driver - unregister a pci driver 14038c2ecf20Sopenharmony_ci * @drv: the driver structure to unregister 14048c2ecf20Sopenharmony_ci * 14058c2ecf20Sopenharmony_ci * Deletes the driver structure from the list of registered PCI drivers, 14068c2ecf20Sopenharmony_ci * gives it a chance to clean up by calling its remove() function for 14078c2ecf20Sopenharmony_ci * each device it was responsible for, and marks those devices as 14088c2ecf20Sopenharmony_ci * driverless. 14098c2ecf20Sopenharmony_ci */ 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_civoid pci_unregister_driver(struct pci_driver *drv) 14128c2ecf20Sopenharmony_ci{ 14138c2ecf20Sopenharmony_ci driver_unregister(&drv->driver); 14148c2ecf20Sopenharmony_ci pci_free_dynids(drv); 14158c2ecf20Sopenharmony_ci} 14168c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pci_unregister_driver); 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_cistatic struct pci_driver pci_compat_driver = { 14198c2ecf20Sopenharmony_ci .name = "compat" 14208c2ecf20Sopenharmony_ci}; 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci/** 14238c2ecf20Sopenharmony_ci * pci_dev_driver - get the pci_driver of a device 14248c2ecf20Sopenharmony_ci * @dev: the device to query 14258c2ecf20Sopenharmony_ci * 14268c2ecf20Sopenharmony_ci * Returns the appropriate pci_driver structure or %NULL if there is no 14278c2ecf20Sopenharmony_ci * registered driver for the device. 14288c2ecf20Sopenharmony_ci */ 14298c2ecf20Sopenharmony_cistruct pci_driver *pci_dev_driver(const struct pci_dev *dev) 14308c2ecf20Sopenharmony_ci{ 14318c2ecf20Sopenharmony_ci if (dev->driver) 14328c2ecf20Sopenharmony_ci return dev->driver; 14338c2ecf20Sopenharmony_ci else { 14348c2ecf20Sopenharmony_ci int i; 14358c2ecf20Sopenharmony_ci for (i = 0; i <= PCI_ROM_RESOURCE; i++) 14368c2ecf20Sopenharmony_ci if (dev->resource[i].flags & IORESOURCE_BUSY) 14378c2ecf20Sopenharmony_ci return &pci_compat_driver; 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci return NULL; 14408c2ecf20Sopenharmony_ci} 14418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pci_dev_driver); 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci/** 14448c2ecf20Sopenharmony_ci * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure 14458c2ecf20Sopenharmony_ci * @dev: the PCI device structure to match against 14468c2ecf20Sopenharmony_ci * @drv: the device driver to search for matching PCI device id structures 14478c2ecf20Sopenharmony_ci * 14488c2ecf20Sopenharmony_ci * Used by a driver to check whether a PCI device present in the 14498c2ecf20Sopenharmony_ci * system is in its list of supported devices. Returns the matching 14508c2ecf20Sopenharmony_ci * pci_device_id structure or %NULL if there is no match. 14518c2ecf20Sopenharmony_ci */ 14528c2ecf20Sopenharmony_cistatic int pci_bus_match(struct device *dev, struct device_driver *drv) 14538c2ecf20Sopenharmony_ci{ 14548c2ecf20Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 14558c2ecf20Sopenharmony_ci struct pci_driver *pci_drv; 14568c2ecf20Sopenharmony_ci const struct pci_device_id *found_id; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci if (!pci_dev->match_driver) 14598c2ecf20Sopenharmony_ci return 0; 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci pci_drv = to_pci_driver(drv); 14628c2ecf20Sopenharmony_ci found_id = pci_match_device(pci_drv, pci_dev); 14638c2ecf20Sopenharmony_ci if (found_id) 14648c2ecf20Sopenharmony_ci return 1; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci return 0; 14678c2ecf20Sopenharmony_ci} 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci/** 14708c2ecf20Sopenharmony_ci * pci_dev_get - increments the reference count of the pci device structure 14718c2ecf20Sopenharmony_ci * @dev: the device being referenced 14728c2ecf20Sopenharmony_ci * 14738c2ecf20Sopenharmony_ci * Each live reference to a device should be refcounted. 14748c2ecf20Sopenharmony_ci * 14758c2ecf20Sopenharmony_ci * Drivers for PCI devices should normally record such references in 14768c2ecf20Sopenharmony_ci * their probe() methods, when they bind to a device, and release 14778c2ecf20Sopenharmony_ci * them by calling pci_dev_put(), in their disconnect() methods. 14788c2ecf20Sopenharmony_ci * 14798c2ecf20Sopenharmony_ci * A pointer to the device with the incremented reference counter is returned. 14808c2ecf20Sopenharmony_ci */ 14818c2ecf20Sopenharmony_cistruct pci_dev *pci_dev_get(struct pci_dev *dev) 14828c2ecf20Sopenharmony_ci{ 14838c2ecf20Sopenharmony_ci if (dev) 14848c2ecf20Sopenharmony_ci get_device(&dev->dev); 14858c2ecf20Sopenharmony_ci return dev; 14868c2ecf20Sopenharmony_ci} 14878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pci_dev_get); 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci/** 14908c2ecf20Sopenharmony_ci * pci_dev_put - release a use of the pci device structure 14918c2ecf20Sopenharmony_ci * @dev: device that's been disconnected 14928c2ecf20Sopenharmony_ci * 14938c2ecf20Sopenharmony_ci * Must be called when a user of a device is finished with it. When the last 14948c2ecf20Sopenharmony_ci * user of the device calls this function, the memory of the device is freed. 14958c2ecf20Sopenharmony_ci */ 14968c2ecf20Sopenharmony_civoid pci_dev_put(struct pci_dev *dev) 14978c2ecf20Sopenharmony_ci{ 14988c2ecf20Sopenharmony_ci if (dev) 14998c2ecf20Sopenharmony_ci put_device(&dev->dev); 15008c2ecf20Sopenharmony_ci} 15018c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pci_dev_put); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_cistatic int pci_uevent(struct device *dev, struct kobj_uevent_env *env) 15048c2ecf20Sopenharmony_ci{ 15058c2ecf20Sopenharmony_ci struct pci_dev *pdev; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci if (!dev) 15088c2ecf20Sopenharmony_ci return -ENODEV; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci pdev = to_pci_dev(dev); 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class)) 15138c2ecf20Sopenharmony_ci return -ENOMEM; 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) 15168c2ecf20Sopenharmony_ci return -ENOMEM; 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, 15198c2ecf20Sopenharmony_ci pdev->subsystem_device)) 15208c2ecf20Sopenharmony_ci return -ENOMEM; 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_ci if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev))) 15238c2ecf20Sopenharmony_ci return -ENOMEM; 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X", 15268c2ecf20Sopenharmony_ci pdev->vendor, pdev->device, 15278c2ecf20Sopenharmony_ci pdev->subsystem_vendor, pdev->subsystem_device, 15288c2ecf20Sopenharmony_ci (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), 15298c2ecf20Sopenharmony_ci (u8)(pdev->class))) 15308c2ecf20Sopenharmony_ci return -ENOMEM; 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci return 0; 15338c2ecf20Sopenharmony_ci} 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci#if defined(CONFIG_PCIEPORTBUS) || defined(CONFIG_EEH) 15368c2ecf20Sopenharmony_ci/** 15378c2ecf20Sopenharmony_ci * pci_uevent_ers - emit a uevent during recovery path of PCI device 15388c2ecf20Sopenharmony_ci * @pdev: PCI device undergoing error recovery 15398c2ecf20Sopenharmony_ci * @err_type: type of error event 15408c2ecf20Sopenharmony_ci */ 15418c2ecf20Sopenharmony_civoid pci_uevent_ers(struct pci_dev *pdev, enum pci_ers_result err_type) 15428c2ecf20Sopenharmony_ci{ 15438c2ecf20Sopenharmony_ci int idx = 0; 15448c2ecf20Sopenharmony_ci char *envp[3]; 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci switch (err_type) { 15478c2ecf20Sopenharmony_ci case PCI_ERS_RESULT_NONE: 15488c2ecf20Sopenharmony_ci case PCI_ERS_RESULT_CAN_RECOVER: 15498c2ecf20Sopenharmony_ci envp[idx++] = "ERROR_EVENT=BEGIN_RECOVERY"; 15508c2ecf20Sopenharmony_ci envp[idx++] = "DEVICE_ONLINE=0"; 15518c2ecf20Sopenharmony_ci break; 15528c2ecf20Sopenharmony_ci case PCI_ERS_RESULT_RECOVERED: 15538c2ecf20Sopenharmony_ci envp[idx++] = "ERROR_EVENT=SUCCESSFUL_RECOVERY"; 15548c2ecf20Sopenharmony_ci envp[idx++] = "DEVICE_ONLINE=1"; 15558c2ecf20Sopenharmony_ci break; 15568c2ecf20Sopenharmony_ci case PCI_ERS_RESULT_DISCONNECT: 15578c2ecf20Sopenharmony_ci envp[idx++] = "ERROR_EVENT=FAILED_RECOVERY"; 15588c2ecf20Sopenharmony_ci envp[idx++] = "DEVICE_ONLINE=0"; 15598c2ecf20Sopenharmony_ci break; 15608c2ecf20Sopenharmony_ci default: 15618c2ecf20Sopenharmony_ci break; 15628c2ecf20Sopenharmony_ci } 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci if (idx > 0) { 15658c2ecf20Sopenharmony_ci envp[idx++] = NULL; 15668c2ecf20Sopenharmony_ci kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp); 15678c2ecf20Sopenharmony_ci } 15688c2ecf20Sopenharmony_ci} 15698c2ecf20Sopenharmony_ci#endif 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_cistatic int pci_bus_num_vf(struct device *dev) 15728c2ecf20Sopenharmony_ci{ 15738c2ecf20Sopenharmony_ci return pci_num_vf(to_pci_dev(dev)); 15748c2ecf20Sopenharmony_ci} 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci/** 15778c2ecf20Sopenharmony_ci * pci_dma_configure - Setup DMA configuration 15788c2ecf20Sopenharmony_ci * @dev: ptr to dev structure 15798c2ecf20Sopenharmony_ci * 15808c2ecf20Sopenharmony_ci * Function to update PCI devices's DMA configuration using the same 15818c2ecf20Sopenharmony_ci * info from the OF node or ACPI node of host bridge's parent (if any). 15828c2ecf20Sopenharmony_ci */ 15838c2ecf20Sopenharmony_cistatic int pci_dma_configure(struct device *dev) 15848c2ecf20Sopenharmony_ci{ 15858c2ecf20Sopenharmony_ci struct device *bridge; 15868c2ecf20Sopenharmony_ci int ret = 0; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci bridge = pci_get_host_bridge_device(to_pci_dev(dev)); 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_OF) && bridge->parent && 15918c2ecf20Sopenharmony_ci bridge->parent->of_node) { 15928c2ecf20Sopenharmony_ci ret = of_dma_configure(dev, bridge->parent->of_node, true); 15938c2ecf20Sopenharmony_ci } else if (has_acpi_companion(bridge)) { 15948c2ecf20Sopenharmony_ci struct acpi_device *adev = to_acpi_device_node(bridge->fwnode); 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci ret = acpi_dma_configure(dev, acpi_get_dma_attr(adev)); 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci pci_put_host_bridge_device(bridge); 16008c2ecf20Sopenharmony_ci return ret; 16018c2ecf20Sopenharmony_ci} 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_cistruct bus_type pci_bus_type = { 16048c2ecf20Sopenharmony_ci .name = "pci", 16058c2ecf20Sopenharmony_ci .match = pci_bus_match, 16068c2ecf20Sopenharmony_ci .uevent = pci_uevent, 16078c2ecf20Sopenharmony_ci .probe = pci_device_probe, 16088c2ecf20Sopenharmony_ci .remove = pci_device_remove, 16098c2ecf20Sopenharmony_ci .shutdown = pci_device_shutdown, 16108c2ecf20Sopenharmony_ci .dev_groups = pci_dev_groups, 16118c2ecf20Sopenharmony_ci .bus_groups = pci_bus_groups, 16128c2ecf20Sopenharmony_ci .drv_groups = pci_drv_groups, 16138c2ecf20Sopenharmony_ci .pm = PCI_PM_OPS_PTR, 16148c2ecf20Sopenharmony_ci .num_vf = pci_bus_num_vf, 16158c2ecf20Sopenharmony_ci .dma_configure = pci_dma_configure, 16168c2ecf20Sopenharmony_ci}; 16178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pci_bus_type); 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci#ifdef CONFIG_PCIEPORTBUS 16208c2ecf20Sopenharmony_cistatic int pcie_port_bus_match(struct device *dev, struct device_driver *drv) 16218c2ecf20Sopenharmony_ci{ 16228c2ecf20Sopenharmony_ci struct pcie_device *pciedev; 16238c2ecf20Sopenharmony_ci struct pcie_port_service_driver *driver; 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) 16268c2ecf20Sopenharmony_ci return 0; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci pciedev = to_pcie_device(dev); 16298c2ecf20Sopenharmony_ci driver = to_service_driver(drv); 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci if (driver->service != pciedev->service) 16328c2ecf20Sopenharmony_ci return 0; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci if (driver->port_type != PCIE_ANY_PORT && 16358c2ecf20Sopenharmony_ci driver->port_type != pci_pcie_type(pciedev->port)) 16368c2ecf20Sopenharmony_ci return 0; 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci return 1; 16398c2ecf20Sopenharmony_ci} 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_cistruct bus_type pcie_port_bus_type = { 16428c2ecf20Sopenharmony_ci .name = "pci_express", 16438c2ecf20Sopenharmony_ci .match = pcie_port_bus_match, 16448c2ecf20Sopenharmony_ci}; 16458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pcie_port_bus_type); 16468c2ecf20Sopenharmony_ci#endif 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_cistatic int __init pci_driver_init(void) 16498c2ecf20Sopenharmony_ci{ 16508c2ecf20Sopenharmony_ci int ret; 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci ret = bus_register(&pci_bus_type); 16538c2ecf20Sopenharmony_ci if (ret) 16548c2ecf20Sopenharmony_ci return ret; 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci#ifdef CONFIG_PCIEPORTBUS 16578c2ecf20Sopenharmony_ci ret = bus_register(&pcie_port_bus_type); 16588c2ecf20Sopenharmony_ci if (ret) 16598c2ecf20Sopenharmony_ci return ret; 16608c2ecf20Sopenharmony_ci#endif 16618c2ecf20Sopenharmony_ci dma_debug_add_bus(&pci_bus_type); 16628c2ecf20Sopenharmony_ci return 0; 16638c2ecf20Sopenharmony_ci} 16648c2ecf20Sopenharmony_cipostcore_initcall(pci_driver_init); 1665