162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * (C) Copyright 2002-2004, 2007 Greg Kroah-Hartman <greg@kroah.com> 462306a36Sopenharmony_ci * (C) Copyright 2007 Novell Inc. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/pci.h> 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/init.h> 1062306a36Sopenharmony_ci#include <linux/device.h> 1162306a36Sopenharmony_ci#include <linux/mempolicy.h> 1262306a36Sopenharmony_ci#include <linux/string.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/sched.h> 1562306a36Sopenharmony_ci#include <linux/sched/isolation.h> 1662306a36Sopenharmony_ci#include <linux/cpu.h> 1762306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1862306a36Sopenharmony_ci#include <linux/suspend.h> 1962306a36Sopenharmony_ci#include <linux/kexec.h> 2062306a36Sopenharmony_ci#include <linux/of_device.h> 2162306a36Sopenharmony_ci#include <linux/acpi.h> 2262306a36Sopenharmony_ci#include <linux/dma-map-ops.h> 2362306a36Sopenharmony_ci#include <linux/iommu.h> 2462306a36Sopenharmony_ci#include "pci.h" 2562306a36Sopenharmony_ci#include "pcie/portdrv.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistruct pci_dynid { 2862306a36Sopenharmony_ci struct list_head node; 2962306a36Sopenharmony_ci struct pci_device_id id; 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/** 3362306a36Sopenharmony_ci * pci_add_dynid - add a new PCI device ID to this driver and re-probe devices 3462306a36Sopenharmony_ci * @drv: target pci driver 3562306a36Sopenharmony_ci * @vendor: PCI vendor ID 3662306a36Sopenharmony_ci * @device: PCI device ID 3762306a36Sopenharmony_ci * @subvendor: PCI subvendor ID 3862306a36Sopenharmony_ci * @subdevice: PCI subdevice ID 3962306a36Sopenharmony_ci * @class: PCI class 4062306a36Sopenharmony_ci * @class_mask: PCI class mask 4162306a36Sopenharmony_ci * @driver_data: private driver data 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * Adds a new dynamic pci device ID to this driver and causes the 4462306a36Sopenharmony_ci * driver to probe for all devices again. @drv must have been 4562306a36Sopenharmony_ci * registered prior to calling this function. 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * CONTEXT: 4862306a36Sopenharmony_ci * Does GFP_KERNEL allocation. 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * RETURNS: 5162306a36Sopenharmony_ci * 0 on success, -errno on failure. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ciint pci_add_dynid(struct pci_driver *drv, 5462306a36Sopenharmony_ci unsigned int vendor, unsigned int device, 5562306a36Sopenharmony_ci unsigned int subvendor, unsigned int subdevice, 5662306a36Sopenharmony_ci unsigned int class, unsigned int class_mask, 5762306a36Sopenharmony_ci unsigned long driver_data) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci struct pci_dynid *dynid; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); 6262306a36Sopenharmony_ci if (!dynid) 6362306a36Sopenharmony_ci return -ENOMEM; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci dynid->id.vendor = vendor; 6662306a36Sopenharmony_ci dynid->id.device = device; 6762306a36Sopenharmony_ci dynid->id.subvendor = subvendor; 6862306a36Sopenharmony_ci dynid->id.subdevice = subdevice; 6962306a36Sopenharmony_ci dynid->id.class = class; 7062306a36Sopenharmony_ci dynid->id.class_mask = class_mask; 7162306a36Sopenharmony_ci dynid->id.driver_data = driver_data; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci spin_lock(&drv->dynids.lock); 7462306a36Sopenharmony_ci list_add_tail(&dynid->node, &drv->dynids.list); 7562306a36Sopenharmony_ci spin_unlock(&drv->dynids.lock); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return driver_attach(&drv->driver); 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pci_add_dynid); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic void pci_free_dynids(struct pci_driver *drv) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci struct pci_dynid *dynid, *n; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci spin_lock(&drv->dynids.lock); 8662306a36Sopenharmony_ci list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { 8762306a36Sopenharmony_ci list_del(&dynid->node); 8862306a36Sopenharmony_ci kfree(dynid); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci spin_unlock(&drv->dynids.lock); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/** 9462306a36Sopenharmony_ci * pci_match_id - See if a PCI device matches a given pci_id table 9562306a36Sopenharmony_ci * @ids: array of PCI device ID structures to search in 9662306a36Sopenharmony_ci * @dev: the PCI device structure to match against. 9762306a36Sopenharmony_ci * 9862306a36Sopenharmony_ci * Used by a driver to check whether a PCI device is in its list of 9962306a36Sopenharmony_ci * supported devices. Returns the matching pci_device_id structure or 10062306a36Sopenharmony_ci * %NULL if there is no match. 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * Deprecated; don't use this as it will not catch any dynamic IDs 10362306a36Sopenharmony_ci * that a driver might want to check for. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ciconst struct pci_device_id *pci_match_id(const struct pci_device_id *ids, 10662306a36Sopenharmony_ci struct pci_dev *dev) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci if (ids) { 10962306a36Sopenharmony_ci while (ids->vendor || ids->subvendor || ids->class_mask) { 11062306a36Sopenharmony_ci if (pci_match_one_device(ids, dev)) 11162306a36Sopenharmony_ci return ids; 11262306a36Sopenharmony_ci ids++; 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci return NULL; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ciEXPORT_SYMBOL(pci_match_id); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic const struct pci_device_id pci_device_id_any = { 12062306a36Sopenharmony_ci .vendor = PCI_ANY_ID, 12162306a36Sopenharmony_ci .device = PCI_ANY_ID, 12262306a36Sopenharmony_ci .subvendor = PCI_ANY_ID, 12362306a36Sopenharmony_ci .subdevice = PCI_ANY_ID, 12462306a36Sopenharmony_ci}; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci/** 12762306a36Sopenharmony_ci * pci_match_device - See if a device matches a driver's list of IDs 12862306a36Sopenharmony_ci * @drv: the PCI driver to match against 12962306a36Sopenharmony_ci * @dev: the PCI device structure to match against 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * Used by a driver to check whether a PCI device is in its list of 13262306a36Sopenharmony_ci * supported devices or in the dynids list, which may have been augmented 13362306a36Sopenharmony_ci * via the sysfs "new_id" file. Returns the matching pci_device_id 13462306a36Sopenharmony_ci * structure or %NULL if there is no match. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_cistatic const struct pci_device_id *pci_match_device(struct pci_driver *drv, 13762306a36Sopenharmony_ci struct pci_dev *dev) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci struct pci_dynid *dynid; 14062306a36Sopenharmony_ci const struct pci_device_id *found_id = NULL, *ids; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* When driver_override is set, only bind to the matching driver */ 14362306a36Sopenharmony_ci if (dev->driver_override && strcmp(dev->driver_override, drv->name)) 14462306a36Sopenharmony_ci return NULL; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* Look at the dynamic ids first, before the static ones */ 14762306a36Sopenharmony_ci spin_lock(&drv->dynids.lock); 14862306a36Sopenharmony_ci list_for_each_entry(dynid, &drv->dynids.list, node) { 14962306a36Sopenharmony_ci if (pci_match_one_device(&dynid->id, dev)) { 15062306a36Sopenharmony_ci found_id = &dynid->id; 15162306a36Sopenharmony_ci break; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci spin_unlock(&drv->dynids.lock); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (found_id) 15762306a36Sopenharmony_ci return found_id; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci for (ids = drv->id_table; (found_id = pci_match_id(ids, dev)); 16062306a36Sopenharmony_ci ids = found_id + 1) { 16162306a36Sopenharmony_ci /* 16262306a36Sopenharmony_ci * The match table is split based on driver_override. 16362306a36Sopenharmony_ci * In case override_only was set, enforce driver_override 16462306a36Sopenharmony_ci * matching. 16562306a36Sopenharmony_ci */ 16662306a36Sopenharmony_ci if (found_id->override_only) { 16762306a36Sopenharmony_ci if (dev->driver_override) 16862306a36Sopenharmony_ci return found_id; 16962306a36Sopenharmony_ci } else { 17062306a36Sopenharmony_ci return found_id; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* driver_override will always match, send a dummy id */ 17562306a36Sopenharmony_ci if (dev->driver_override) 17662306a36Sopenharmony_ci return &pci_device_id_any; 17762306a36Sopenharmony_ci return NULL; 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci/** 18162306a36Sopenharmony_ci * new_id_store - sysfs frontend to pci_add_dynid() 18262306a36Sopenharmony_ci * @driver: target device driver 18362306a36Sopenharmony_ci * @buf: buffer for scanning device ID data 18462306a36Sopenharmony_ci * @count: input size 18562306a36Sopenharmony_ci * 18662306a36Sopenharmony_ci * Allow PCI IDs to be added to an existing driver via sysfs. 18762306a36Sopenharmony_ci */ 18862306a36Sopenharmony_cistatic ssize_t new_id_store(struct device_driver *driver, const char *buf, 18962306a36Sopenharmony_ci size_t count) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci struct pci_driver *pdrv = to_pci_driver(driver); 19262306a36Sopenharmony_ci const struct pci_device_id *ids = pdrv->id_table; 19362306a36Sopenharmony_ci u32 vendor, device, subvendor = PCI_ANY_ID, 19462306a36Sopenharmony_ci subdevice = PCI_ANY_ID, class = 0, class_mask = 0; 19562306a36Sopenharmony_ci unsigned long driver_data = 0; 19662306a36Sopenharmony_ci int fields; 19762306a36Sopenharmony_ci int retval = 0; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci fields = sscanf(buf, "%x %x %x %x %x %x %lx", 20062306a36Sopenharmony_ci &vendor, &device, &subvendor, &subdevice, 20162306a36Sopenharmony_ci &class, &class_mask, &driver_data); 20262306a36Sopenharmony_ci if (fields < 2) 20362306a36Sopenharmony_ci return -EINVAL; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (fields != 7) { 20662306a36Sopenharmony_ci struct pci_dev *pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); 20762306a36Sopenharmony_ci if (!pdev) 20862306a36Sopenharmony_ci return -ENOMEM; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci pdev->vendor = vendor; 21162306a36Sopenharmony_ci pdev->device = device; 21262306a36Sopenharmony_ci pdev->subsystem_vendor = subvendor; 21362306a36Sopenharmony_ci pdev->subsystem_device = subdevice; 21462306a36Sopenharmony_ci pdev->class = class; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (pci_match_device(pdrv, pdev)) 21762306a36Sopenharmony_ci retval = -EEXIST; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci kfree(pdev); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (retval) 22262306a36Sopenharmony_ci return retval; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* Only accept driver_data values that match an existing id_table 22662306a36Sopenharmony_ci entry */ 22762306a36Sopenharmony_ci if (ids) { 22862306a36Sopenharmony_ci retval = -EINVAL; 22962306a36Sopenharmony_ci while (ids->vendor || ids->subvendor || ids->class_mask) { 23062306a36Sopenharmony_ci if (driver_data == ids->driver_data) { 23162306a36Sopenharmony_ci retval = 0; 23262306a36Sopenharmony_ci break; 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci ids++; 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci if (retval) /* No match */ 23762306a36Sopenharmony_ci return retval; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci retval = pci_add_dynid(pdrv, vendor, device, subvendor, subdevice, 24162306a36Sopenharmony_ci class, class_mask, driver_data); 24262306a36Sopenharmony_ci if (retval) 24362306a36Sopenharmony_ci return retval; 24462306a36Sopenharmony_ci return count; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_cistatic DRIVER_ATTR_WO(new_id); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/** 24962306a36Sopenharmony_ci * remove_id_store - remove a PCI device ID from this driver 25062306a36Sopenharmony_ci * @driver: target device driver 25162306a36Sopenharmony_ci * @buf: buffer for scanning device ID data 25262306a36Sopenharmony_ci * @count: input size 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * Removes a dynamic pci device ID to this driver. 25562306a36Sopenharmony_ci */ 25662306a36Sopenharmony_cistatic ssize_t remove_id_store(struct device_driver *driver, const char *buf, 25762306a36Sopenharmony_ci size_t count) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct pci_dynid *dynid, *n; 26062306a36Sopenharmony_ci struct pci_driver *pdrv = to_pci_driver(driver); 26162306a36Sopenharmony_ci u32 vendor, device, subvendor = PCI_ANY_ID, 26262306a36Sopenharmony_ci subdevice = PCI_ANY_ID, class = 0, class_mask = 0; 26362306a36Sopenharmony_ci int fields; 26462306a36Sopenharmony_ci size_t retval = -ENODEV; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci fields = sscanf(buf, "%x %x %x %x %x %x", 26762306a36Sopenharmony_ci &vendor, &device, &subvendor, &subdevice, 26862306a36Sopenharmony_ci &class, &class_mask); 26962306a36Sopenharmony_ci if (fields < 2) 27062306a36Sopenharmony_ci return -EINVAL; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci spin_lock(&pdrv->dynids.lock); 27362306a36Sopenharmony_ci list_for_each_entry_safe(dynid, n, &pdrv->dynids.list, node) { 27462306a36Sopenharmony_ci struct pci_device_id *id = &dynid->id; 27562306a36Sopenharmony_ci if ((id->vendor == vendor) && 27662306a36Sopenharmony_ci (id->device == device) && 27762306a36Sopenharmony_ci (subvendor == PCI_ANY_ID || id->subvendor == subvendor) && 27862306a36Sopenharmony_ci (subdevice == PCI_ANY_ID || id->subdevice == subdevice) && 27962306a36Sopenharmony_ci !((id->class ^ class) & class_mask)) { 28062306a36Sopenharmony_ci list_del(&dynid->node); 28162306a36Sopenharmony_ci kfree(dynid); 28262306a36Sopenharmony_ci retval = count; 28362306a36Sopenharmony_ci break; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci spin_unlock(&pdrv->dynids.lock); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci return retval; 28962306a36Sopenharmony_ci} 29062306a36Sopenharmony_cistatic DRIVER_ATTR_WO(remove_id); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic struct attribute *pci_drv_attrs[] = { 29362306a36Sopenharmony_ci &driver_attr_new_id.attr, 29462306a36Sopenharmony_ci &driver_attr_remove_id.attr, 29562306a36Sopenharmony_ci NULL, 29662306a36Sopenharmony_ci}; 29762306a36Sopenharmony_ciATTRIBUTE_GROUPS(pci_drv); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistruct drv_dev_and_id { 30062306a36Sopenharmony_ci struct pci_driver *drv; 30162306a36Sopenharmony_ci struct pci_dev *dev; 30262306a36Sopenharmony_ci const struct pci_device_id *id; 30362306a36Sopenharmony_ci}; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic long local_pci_probe(void *_ddi) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct drv_dev_and_id *ddi = _ddi; 30862306a36Sopenharmony_ci struct pci_dev *pci_dev = ddi->dev; 30962306a36Sopenharmony_ci struct pci_driver *pci_drv = ddi->drv; 31062306a36Sopenharmony_ci struct device *dev = &pci_dev->dev; 31162306a36Sopenharmony_ci int rc; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* 31462306a36Sopenharmony_ci * Unbound PCI devices are always put in D0, regardless of 31562306a36Sopenharmony_ci * runtime PM status. During probe, the device is set to 31662306a36Sopenharmony_ci * active and the usage count is incremented. If the driver 31762306a36Sopenharmony_ci * supports runtime PM, it should call pm_runtime_put_noidle(), 31862306a36Sopenharmony_ci * or any other runtime PM helper function decrementing the usage 31962306a36Sopenharmony_ci * count, in its probe routine and pm_runtime_get_noresume() in 32062306a36Sopenharmony_ci * its remove routine. 32162306a36Sopenharmony_ci */ 32262306a36Sopenharmony_ci pm_runtime_get_sync(dev); 32362306a36Sopenharmony_ci pci_dev->driver = pci_drv; 32462306a36Sopenharmony_ci rc = pci_drv->probe(pci_dev, ddi->id); 32562306a36Sopenharmony_ci if (!rc) 32662306a36Sopenharmony_ci return rc; 32762306a36Sopenharmony_ci if (rc < 0) { 32862306a36Sopenharmony_ci pci_dev->driver = NULL; 32962306a36Sopenharmony_ci pm_runtime_put_sync(dev); 33062306a36Sopenharmony_ci return rc; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci /* 33362306a36Sopenharmony_ci * Probe function should return < 0 for failure, 0 for success 33462306a36Sopenharmony_ci * Treat values > 0 as success, but warn. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci pci_warn(pci_dev, "Driver probe function unexpectedly returned %d\n", 33762306a36Sopenharmony_ci rc); 33862306a36Sopenharmony_ci return 0; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic bool pci_physfn_is_probed(struct pci_dev *dev) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 34462306a36Sopenharmony_ci return dev->is_virtfn && dev->physfn->is_probed; 34562306a36Sopenharmony_ci#else 34662306a36Sopenharmony_ci return false; 34762306a36Sopenharmony_ci#endif 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, 35162306a36Sopenharmony_ci const struct pci_device_id *id) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci int error, node, cpu; 35462306a36Sopenharmony_ci struct drv_dev_and_id ddi = { drv, dev, id }; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci /* 35762306a36Sopenharmony_ci * Execute driver initialization on node where the device is 35862306a36Sopenharmony_ci * attached. This way the driver likely allocates its local memory 35962306a36Sopenharmony_ci * on the right node. 36062306a36Sopenharmony_ci */ 36162306a36Sopenharmony_ci node = dev_to_node(&dev->dev); 36262306a36Sopenharmony_ci dev->is_probed = 1; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci cpu_hotplug_disable(); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* 36762306a36Sopenharmony_ci * Prevent nesting work_on_cpu() for the case where a Virtual Function 36862306a36Sopenharmony_ci * device is probed from work_on_cpu() of the Physical device. 36962306a36Sopenharmony_ci */ 37062306a36Sopenharmony_ci if (node < 0 || node >= MAX_NUMNODES || !node_online(node) || 37162306a36Sopenharmony_ci pci_physfn_is_probed(dev)) { 37262306a36Sopenharmony_ci cpu = nr_cpu_ids; 37362306a36Sopenharmony_ci } else { 37462306a36Sopenharmony_ci cpumask_var_t wq_domain_mask; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (!zalloc_cpumask_var(&wq_domain_mask, GFP_KERNEL)) { 37762306a36Sopenharmony_ci error = -ENOMEM; 37862306a36Sopenharmony_ci goto out; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci cpumask_and(wq_domain_mask, 38162306a36Sopenharmony_ci housekeeping_cpumask(HK_TYPE_WQ), 38262306a36Sopenharmony_ci housekeeping_cpumask(HK_TYPE_DOMAIN)); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci cpu = cpumask_any_and(cpumask_of_node(node), 38562306a36Sopenharmony_ci wq_domain_mask); 38662306a36Sopenharmony_ci free_cpumask_var(wq_domain_mask); 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (cpu < nr_cpu_ids) 39062306a36Sopenharmony_ci error = work_on_cpu(cpu, local_pci_probe, &ddi); 39162306a36Sopenharmony_ci else 39262306a36Sopenharmony_ci error = local_pci_probe(&ddi); 39362306a36Sopenharmony_ciout: 39462306a36Sopenharmony_ci dev->is_probed = 0; 39562306a36Sopenharmony_ci cpu_hotplug_enable(); 39662306a36Sopenharmony_ci return error; 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci/** 40062306a36Sopenharmony_ci * __pci_device_probe - check if a driver wants to claim a specific PCI device 40162306a36Sopenharmony_ci * @drv: driver to call to check if it wants the PCI device 40262306a36Sopenharmony_ci * @pci_dev: PCI device being probed 40362306a36Sopenharmony_ci * 40462306a36Sopenharmony_ci * returns 0 on success, else error. 40562306a36Sopenharmony_ci * side-effect: pci_dev->driver is set to drv when drv claims pci_dev. 40662306a36Sopenharmony_ci */ 40762306a36Sopenharmony_cistatic int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci const struct pci_device_id *id; 41062306a36Sopenharmony_ci int error = 0; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (drv->probe) { 41362306a36Sopenharmony_ci error = -ENODEV; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci id = pci_match_device(drv, pci_dev); 41662306a36Sopenharmony_ci if (id) 41762306a36Sopenharmony_ci error = pci_call_probe(drv, pci_dev, id); 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci return error; 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ciint __weak pcibios_alloc_irq(struct pci_dev *dev) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci return 0; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_civoid __weak pcibios_free_irq(struct pci_dev *dev) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci#ifdef CONFIG_PCI_IOV 43262306a36Sopenharmony_cistatic inline bool pci_device_can_probe(struct pci_dev *pdev) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci return (!pdev->is_virtfn || pdev->physfn->sriov->drivers_autoprobe || 43562306a36Sopenharmony_ci pdev->driver_override); 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci#else 43862306a36Sopenharmony_cistatic inline bool pci_device_can_probe(struct pci_dev *pdev) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci return true; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci#endif 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic int pci_device_probe(struct device *dev) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci int error; 44762306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 44862306a36Sopenharmony_ci struct pci_driver *drv = to_pci_driver(dev->driver); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci if (!pci_device_can_probe(pci_dev)) 45162306a36Sopenharmony_ci return -ENODEV; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci pci_assign_irq(pci_dev); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci error = pcibios_alloc_irq(pci_dev); 45662306a36Sopenharmony_ci if (error < 0) 45762306a36Sopenharmony_ci return error; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci pci_dev_get(pci_dev); 46062306a36Sopenharmony_ci error = __pci_device_probe(drv, pci_dev); 46162306a36Sopenharmony_ci if (error) { 46262306a36Sopenharmony_ci pcibios_free_irq(pci_dev); 46362306a36Sopenharmony_ci pci_dev_put(pci_dev); 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci return error; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic void pci_device_remove(struct device *dev) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 47262306a36Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci if (drv->remove) { 47562306a36Sopenharmony_ci pm_runtime_get_sync(dev); 47662306a36Sopenharmony_ci /* 47762306a36Sopenharmony_ci * If the driver provides a .runtime_idle() callback and it has 47862306a36Sopenharmony_ci * started to run already, it may continue to run in parallel 47962306a36Sopenharmony_ci * with the code below, so wait until all of the runtime PM 48062306a36Sopenharmony_ci * activity has completed. 48162306a36Sopenharmony_ci */ 48262306a36Sopenharmony_ci pm_runtime_barrier(dev); 48362306a36Sopenharmony_ci drv->remove(pci_dev); 48462306a36Sopenharmony_ci pm_runtime_put_noidle(dev); 48562306a36Sopenharmony_ci } 48662306a36Sopenharmony_ci pcibios_free_irq(pci_dev); 48762306a36Sopenharmony_ci pci_dev->driver = NULL; 48862306a36Sopenharmony_ci pci_iov_remove(pci_dev); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* Undo the runtime PM settings in local_pci_probe() */ 49162306a36Sopenharmony_ci pm_runtime_put_sync(dev); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci /* 49462306a36Sopenharmony_ci * If the device is still on, set the power state as "unknown", 49562306a36Sopenharmony_ci * since it might change by the next time we load the driver. 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_ci if (pci_dev->current_state == PCI_D0) 49862306a36Sopenharmony_ci pci_dev->current_state = PCI_UNKNOWN; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci /* 50162306a36Sopenharmony_ci * We would love to complain here if pci_dev->is_enabled is set, that 50262306a36Sopenharmony_ci * the driver should have called pci_disable_device(), but the 50362306a36Sopenharmony_ci * unfortunate fact is there are too many odd BIOS and bridge setups 50462306a36Sopenharmony_ci * that don't like drivers doing that all of the time. 50562306a36Sopenharmony_ci * Oh well, we can dream of sane hardware when we sleep, no matter how 50662306a36Sopenharmony_ci * horrible the crap we have to deal with is when we are awake... 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci pci_dev_put(pci_dev); 51062306a36Sopenharmony_ci} 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cistatic void pci_device_shutdown(struct device *dev) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 51562306a36Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci pm_runtime_resume(dev); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci if (drv && drv->shutdown) 52062306a36Sopenharmony_ci drv->shutdown(pci_dev); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci /* 52362306a36Sopenharmony_ci * If this is a kexec reboot, turn off Bus Master bit on the 52462306a36Sopenharmony_ci * device to tell it to not continue to do DMA. Don't touch 52562306a36Sopenharmony_ci * devices in D3cold or unknown states. 52662306a36Sopenharmony_ci * If it is not a kexec reboot, firmware will hit the PCI 52762306a36Sopenharmony_ci * devices with big hammer and stop their DMA any way. 52862306a36Sopenharmony_ci */ 52962306a36Sopenharmony_ci if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot)) 53062306a36Sopenharmony_ci pci_clear_master(pci_dev); 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci/* Auxiliary functions used for system resume */ 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/** 53862306a36Sopenharmony_ci * pci_restore_standard_config - restore standard config registers of PCI device 53962306a36Sopenharmony_ci * @pci_dev: PCI device to handle 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_cistatic int pci_restore_standard_config(struct pci_dev *pci_dev) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci pci_update_current_state(pci_dev, PCI_UNKNOWN); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if (pci_dev->current_state != PCI_D0) { 54662306a36Sopenharmony_ci int error = pci_set_power_state(pci_dev, PCI_D0); 54762306a36Sopenharmony_ci if (error) 54862306a36Sopenharmony_ci return error; 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci pci_restore_state(pci_dev); 55262306a36Sopenharmony_ci pci_pme_restore(pci_dev); 55362306a36Sopenharmony_ci return 0; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci#ifdef CONFIG_PM 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci/* Auxiliary functions used for system resume and run-time resume */ 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_cistatic void pci_pm_default_resume(struct pci_dev *pci_dev) 56262306a36Sopenharmony_ci{ 56362306a36Sopenharmony_ci pci_fixup_device(pci_fixup_resume, pci_dev); 56462306a36Sopenharmony_ci pci_enable_wake(pci_dev, PCI_D0, false); 56562306a36Sopenharmony_ci} 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_cistatic void pci_pm_power_up_and_verify_state(struct pci_dev *pci_dev) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci pci_power_up(pci_dev); 57062306a36Sopenharmony_ci pci_update_current_state(pci_dev, PCI_D0); 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cistatic void pci_pm_default_resume_early(struct pci_dev *pci_dev) 57462306a36Sopenharmony_ci{ 57562306a36Sopenharmony_ci pci_pm_power_up_and_verify_state(pci_dev); 57662306a36Sopenharmony_ci pci_restore_state(pci_dev); 57762306a36Sopenharmony_ci pci_pme_restore(pci_dev); 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci int ret; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci ret = pci_bridge_wait_for_secondary_bus(pci_dev, "resume"); 58562306a36Sopenharmony_ci if (ret) { 58662306a36Sopenharmony_ci /* 58762306a36Sopenharmony_ci * The downstream link failed to come up, so mark the 58862306a36Sopenharmony_ci * devices below as disconnected to make sure we don't 58962306a36Sopenharmony_ci * attempt to resume them. 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci pci_walk_bus(pci_dev->subordinate, pci_dev_set_disconnected, 59262306a36Sopenharmony_ci NULL); 59362306a36Sopenharmony_ci return; 59462306a36Sopenharmony_ci } 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci /* 59762306a36Sopenharmony_ci * When powering on a bridge from D3cold, the whole hierarchy may be 59862306a36Sopenharmony_ci * powered on into D0uninitialized state, resume them to give them a 59962306a36Sopenharmony_ci * chance to suspend again 60062306a36Sopenharmony_ci */ 60162306a36Sopenharmony_ci pci_resume_bus(pci_dev->subordinate); 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci#endif /* CONFIG_PM */ 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci/* 60962306a36Sopenharmony_ci * Default "suspend" method for devices that have no driver provided suspend, 61062306a36Sopenharmony_ci * or not even a driver at all (second part). 61162306a36Sopenharmony_ci */ 61262306a36Sopenharmony_cistatic void pci_pm_set_unknown_state(struct pci_dev *pci_dev) 61362306a36Sopenharmony_ci{ 61462306a36Sopenharmony_ci /* 61562306a36Sopenharmony_ci * mark its power state as "unknown", since we don't know if 61662306a36Sopenharmony_ci * e.g. the BIOS will change its device state when we suspend. 61762306a36Sopenharmony_ci */ 61862306a36Sopenharmony_ci if (pci_dev->current_state == PCI_D0) 61962306a36Sopenharmony_ci pci_dev->current_state = PCI_UNKNOWN; 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci/* 62362306a36Sopenharmony_ci * Default "resume" method for devices that have no driver provided resume, 62462306a36Sopenharmony_ci * or not even a driver at all (second part). 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_cistatic int pci_pm_reenable_device(struct pci_dev *pci_dev) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci int retval; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci /* if the device was enabled before suspend, re-enable */ 63162306a36Sopenharmony_ci retval = pci_reenable_device(pci_dev); 63262306a36Sopenharmony_ci /* 63362306a36Sopenharmony_ci * if the device was busmaster before the suspend, make it busmaster 63462306a36Sopenharmony_ci * again 63562306a36Sopenharmony_ci */ 63662306a36Sopenharmony_ci if (pci_dev->is_busmaster) 63762306a36Sopenharmony_ci pci_set_master(pci_dev); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci return retval; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic int pci_legacy_suspend(struct device *dev, pm_message_t state) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 64562306a36Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (drv && drv->suspend) { 64862306a36Sopenharmony_ci pci_power_t prev = pci_dev->current_state; 64962306a36Sopenharmony_ci int error; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci error = drv->suspend(pci_dev, state); 65262306a36Sopenharmony_ci suspend_report_result(dev, drv->suspend, error); 65362306a36Sopenharmony_ci if (error) 65462306a36Sopenharmony_ci return error; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 65762306a36Sopenharmony_ci && pci_dev->current_state != PCI_UNKNOWN) { 65862306a36Sopenharmony_ci pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 65962306a36Sopenharmony_ci "PCI PM: Device state not saved by %pS\n", 66062306a36Sopenharmony_ci drv->suspend); 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci pci_fixup_device(pci_fixup_suspend, pci_dev); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci return 0; 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_cistatic int pci_legacy_suspend_late(struct device *dev) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci if (!pci_dev->state_saved) 67462306a36Sopenharmony_ci pci_save_state(pci_dev); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci pci_pm_set_unknown_state(pci_dev); 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci pci_fixup_device(pci_fixup_suspend_late, pci_dev); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci return 0; 68162306a36Sopenharmony_ci} 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_cistatic int pci_legacy_resume(struct device *dev) 68462306a36Sopenharmony_ci{ 68562306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 68662306a36Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci pci_fixup_device(pci_fixup_resume, pci_dev); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci return drv && drv->resume ? 69162306a36Sopenharmony_ci drv->resume(pci_dev) : pci_pm_reenable_device(pci_dev); 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci/* Auxiliary functions used by the new power management framework */ 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_cistatic void pci_pm_default_suspend(struct pci_dev *pci_dev) 69762306a36Sopenharmony_ci{ 69862306a36Sopenharmony_ci /* Disable non-bridge devices without PM support */ 69962306a36Sopenharmony_ci if (!pci_has_subordinate(pci_dev)) 70062306a36Sopenharmony_ci pci_disable_enabled_device(pci_dev); 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) 70462306a36Sopenharmony_ci{ 70562306a36Sopenharmony_ci struct pci_driver *drv = pci_dev->driver; 70662306a36Sopenharmony_ci bool ret = drv && (drv->suspend || drv->resume); 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci /* 70962306a36Sopenharmony_ci * Legacy PM support is used by default, so warn if the new framework is 71062306a36Sopenharmony_ci * supported as well. Drivers are supposed to support either the 71162306a36Sopenharmony_ci * former, or the latter, but not both at the same time. 71262306a36Sopenharmony_ci */ 71362306a36Sopenharmony_ci pci_WARN(pci_dev, ret && drv->driver.pm, "device %04x:%04x\n", 71462306a36Sopenharmony_ci pci_dev->vendor, pci_dev->device); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci return ret; 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci/* New power management framework */ 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_cistatic int pci_pm_prepare(struct device *dev) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 72462306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci if (pm && pm->prepare) { 72762306a36Sopenharmony_ci int error = pm->prepare(dev); 72862306a36Sopenharmony_ci if (error < 0) 72962306a36Sopenharmony_ci return error; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci if (!error && dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_PREPARE)) 73262306a36Sopenharmony_ci return 0; 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci if (pci_dev_need_resume(pci_dev)) 73562306a36Sopenharmony_ci return 0; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci /* 73862306a36Sopenharmony_ci * The PME setting needs to be adjusted here in case the direct-complete 73962306a36Sopenharmony_ci * optimization is used with respect to this device. 74062306a36Sopenharmony_ci */ 74162306a36Sopenharmony_ci pci_dev_adjust_pme(pci_dev); 74262306a36Sopenharmony_ci return 1; 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic void pci_pm_complete(struct device *dev) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci pci_dev_complete_resume(pci_dev); 75062306a36Sopenharmony_ci pm_generic_complete(dev); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci /* Resume device if platform firmware has put it in reset-power-on */ 75362306a36Sopenharmony_ci if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) { 75462306a36Sopenharmony_ci pci_power_t pre_sleep_state = pci_dev->current_state; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci pci_refresh_power_state(pci_dev); 75762306a36Sopenharmony_ci /* 75862306a36Sopenharmony_ci * On platforms with ACPI this check may also trigger for 75962306a36Sopenharmony_ci * devices sharing power resources if one of those power 76062306a36Sopenharmony_ci * resources has been activated as a result of a change of the 76162306a36Sopenharmony_ci * power state of another device sharing it. However, in that 76262306a36Sopenharmony_ci * case it is also better to resume the device, in general. 76362306a36Sopenharmony_ci */ 76462306a36Sopenharmony_ci if (pci_dev->current_state < pre_sleep_state) 76562306a36Sopenharmony_ci pm_request_resume(dev); 76662306a36Sopenharmony_ci } 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci#else /* !CONFIG_PM_SLEEP */ 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci#define pci_pm_prepare NULL 77262306a36Sopenharmony_ci#define pci_pm_complete NULL 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci#endif /* !CONFIG_PM_SLEEP */ 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci#ifdef CONFIG_SUSPEND 77762306a36Sopenharmony_cistatic void pcie_pme_root_status_cleanup(struct pci_dev *pci_dev) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci /* 78062306a36Sopenharmony_ci * Some BIOSes forget to clear Root PME Status bits after system 78162306a36Sopenharmony_ci * wakeup, which breaks ACPI-based runtime wakeup on PCI Express. 78262306a36Sopenharmony_ci * Clear those bits now just in case (shouldn't hurt). 78362306a36Sopenharmony_ci */ 78462306a36Sopenharmony_ci if (pci_is_pcie(pci_dev) && 78562306a36Sopenharmony_ci (pci_pcie_type(pci_dev) == PCI_EXP_TYPE_ROOT_PORT || 78662306a36Sopenharmony_ci pci_pcie_type(pci_dev) == PCI_EXP_TYPE_RC_EC)) 78762306a36Sopenharmony_ci pcie_clear_root_pme_status(pci_dev); 78862306a36Sopenharmony_ci} 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_cistatic int pci_pm_suspend(struct device *dev) 79162306a36Sopenharmony_ci{ 79262306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 79362306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci pci_dev->skip_bus_pm = false; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci /* 79862306a36Sopenharmony_ci * Disabling PTM allows some systems, e.g., Intel mobile chips 79962306a36Sopenharmony_ci * since Coffee Lake, to enter a lower-power PM state. 80062306a36Sopenharmony_ci */ 80162306a36Sopenharmony_ci pci_suspend_ptm(pci_dev); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 80462306a36Sopenharmony_ci return pci_legacy_suspend(dev, PMSG_SUSPEND); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci if (!pm) { 80762306a36Sopenharmony_ci pci_pm_default_suspend(pci_dev); 80862306a36Sopenharmony_ci return 0; 80962306a36Sopenharmony_ci } 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci /* 81262306a36Sopenharmony_ci * PCI devices suspended at run time may need to be resumed at this 81362306a36Sopenharmony_ci * point, because in general it may be necessary to reconfigure them for 81462306a36Sopenharmony_ci * system suspend. Namely, if the device is expected to wake up the 81562306a36Sopenharmony_ci * system from the sleep state, it may have to be reconfigured for this 81662306a36Sopenharmony_ci * purpose, or if the device is not expected to wake up the system from 81762306a36Sopenharmony_ci * the sleep state, it should be prevented from signaling wakeup events 81862306a36Sopenharmony_ci * going forward. 81962306a36Sopenharmony_ci * 82062306a36Sopenharmony_ci * Also if the driver of the device does not indicate that its system 82162306a36Sopenharmony_ci * suspend callbacks can cope with runtime-suspended devices, it is 82262306a36Sopenharmony_ci * better to resume the device from runtime suspend here. 82362306a36Sopenharmony_ci */ 82462306a36Sopenharmony_ci if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || 82562306a36Sopenharmony_ci pci_dev_need_resume(pci_dev)) { 82662306a36Sopenharmony_ci pm_runtime_resume(dev); 82762306a36Sopenharmony_ci pci_dev->state_saved = false; 82862306a36Sopenharmony_ci } else { 82962306a36Sopenharmony_ci pci_dev_adjust_pme(pci_dev); 83062306a36Sopenharmony_ci } 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci if (pm->suspend) { 83362306a36Sopenharmony_ci pci_power_t prev = pci_dev->current_state; 83462306a36Sopenharmony_ci int error; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci error = pm->suspend(dev); 83762306a36Sopenharmony_ci suspend_report_result(dev, pm->suspend, error); 83862306a36Sopenharmony_ci if (error) 83962306a36Sopenharmony_ci return error; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 84262306a36Sopenharmony_ci && pci_dev->current_state != PCI_UNKNOWN) { 84362306a36Sopenharmony_ci pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 84462306a36Sopenharmony_ci "PCI PM: State of device not saved by %pS\n", 84562306a36Sopenharmony_ci pm->suspend); 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci return 0; 85062306a36Sopenharmony_ci} 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_cistatic int pci_pm_suspend_late(struct device *dev) 85362306a36Sopenharmony_ci{ 85462306a36Sopenharmony_ci if (dev_pm_skip_suspend(dev)) 85562306a36Sopenharmony_ci return 0; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev)); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci return pm_generic_suspend_late(dev); 86062306a36Sopenharmony_ci} 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_cistatic int pci_pm_suspend_noirq(struct device *dev) 86362306a36Sopenharmony_ci{ 86462306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 86562306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci if (dev_pm_skip_suspend(dev)) 86862306a36Sopenharmony_ci return 0; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 87162306a36Sopenharmony_ci return pci_legacy_suspend_late(dev); 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci if (!pm) { 87462306a36Sopenharmony_ci pci_save_state(pci_dev); 87562306a36Sopenharmony_ci goto Fixup; 87662306a36Sopenharmony_ci } 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci if (pm->suspend_noirq) { 87962306a36Sopenharmony_ci pci_power_t prev = pci_dev->current_state; 88062306a36Sopenharmony_ci int error; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci error = pm->suspend_noirq(dev); 88362306a36Sopenharmony_ci suspend_report_result(dev, pm->suspend_noirq, error); 88462306a36Sopenharmony_ci if (error) 88562306a36Sopenharmony_ci return error; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 88862306a36Sopenharmony_ci && pci_dev->current_state != PCI_UNKNOWN) { 88962306a36Sopenharmony_ci pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 89062306a36Sopenharmony_ci "PCI PM: State of device not saved by %pS\n", 89162306a36Sopenharmony_ci pm->suspend_noirq); 89262306a36Sopenharmony_ci goto Fixup; 89362306a36Sopenharmony_ci } 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci if (!pci_dev->state_saved) { 89762306a36Sopenharmony_ci pci_save_state(pci_dev); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci /* 90062306a36Sopenharmony_ci * If the device is a bridge with a child in D0 below it, 90162306a36Sopenharmony_ci * it needs to stay in D0, so check skip_bus_pm to avoid 90262306a36Sopenharmony_ci * putting it into a low-power state in that case. 90362306a36Sopenharmony_ci */ 90462306a36Sopenharmony_ci if (!pci_dev->skip_bus_pm && pci_power_manageable(pci_dev)) 90562306a36Sopenharmony_ci pci_prepare_to_sleep(pci_dev); 90662306a36Sopenharmony_ci } 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci pci_dbg(pci_dev, "PCI PM: Suspend power state: %s\n", 90962306a36Sopenharmony_ci pci_power_name(pci_dev->current_state)); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci if (pci_dev->current_state == PCI_D0) { 91262306a36Sopenharmony_ci pci_dev->skip_bus_pm = true; 91362306a36Sopenharmony_ci /* 91462306a36Sopenharmony_ci * Per PCI PM r1.2, table 6-1, a bridge must be in D0 if any 91562306a36Sopenharmony_ci * downstream device is in D0, so avoid changing the power state 91662306a36Sopenharmony_ci * of the parent bridge by setting the skip_bus_pm flag for it. 91762306a36Sopenharmony_ci */ 91862306a36Sopenharmony_ci if (pci_dev->bus->self) 91962306a36Sopenharmony_ci pci_dev->bus->self->skip_bus_pm = true; 92062306a36Sopenharmony_ci } 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci if (pci_dev->skip_bus_pm && pm_suspend_no_platform()) { 92362306a36Sopenharmony_ci pci_dbg(pci_dev, "PCI PM: Skipped\n"); 92462306a36Sopenharmony_ci goto Fixup; 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci pci_pm_set_unknown_state(pci_dev); 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci /* 93062306a36Sopenharmony_ci * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's 93162306a36Sopenharmony_ci * PCI COMMAND register isn't 0, the BIOS assumes that the controller 93262306a36Sopenharmony_ci * hasn't been quiesced and tries to turn it off. If the controller 93362306a36Sopenharmony_ci * is already in D3, this can hang or cause memory corruption. 93462306a36Sopenharmony_ci * 93562306a36Sopenharmony_ci * Since the value of the COMMAND register doesn't matter once the 93662306a36Sopenharmony_ci * device has been suspended, we can safely set it to 0 here. 93762306a36Sopenharmony_ci */ 93862306a36Sopenharmony_ci if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) 93962306a36Sopenharmony_ci pci_write_config_word(pci_dev, PCI_COMMAND, 0); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ciFixup: 94262306a36Sopenharmony_ci pci_fixup_device(pci_fixup_suspend_late, pci_dev); 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* 94562306a36Sopenharmony_ci * If the target system sleep state is suspend-to-idle, it is sufficient 94662306a36Sopenharmony_ci * to check whether or not the device's wakeup settings are good for 94762306a36Sopenharmony_ci * runtime PM. Otherwise, the pm_resume_via_firmware() check will cause 94862306a36Sopenharmony_ci * pci_pm_complete() to take care of fixing up the device's state 94962306a36Sopenharmony_ci * anyway, if need be. 95062306a36Sopenharmony_ci */ 95162306a36Sopenharmony_ci if (device_can_wakeup(dev) && !device_may_wakeup(dev)) 95262306a36Sopenharmony_ci dev->power.may_skip_resume = false; 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci return 0; 95562306a36Sopenharmony_ci} 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_cistatic int pci_pm_resume_noirq(struct device *dev) 95862306a36Sopenharmony_ci{ 95962306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 96062306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 96162306a36Sopenharmony_ci pci_power_t prev_state = pci_dev->current_state; 96262306a36Sopenharmony_ci bool skip_bus_pm = pci_dev->skip_bus_pm; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci if (dev_pm_skip_resume(dev)) 96562306a36Sopenharmony_ci return 0; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci /* 96862306a36Sopenharmony_ci * In the suspend-to-idle case, devices left in D0 during suspend will 96962306a36Sopenharmony_ci * stay in D0, so it is not necessary to restore or update their 97062306a36Sopenharmony_ci * configuration here and attempting to put them into D0 again is 97162306a36Sopenharmony_ci * pointless, so avoid doing that. 97262306a36Sopenharmony_ci */ 97362306a36Sopenharmony_ci if (!(skip_bus_pm && pm_suspend_no_platform())) 97462306a36Sopenharmony_ci pci_pm_default_resume_early(pci_dev); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci pci_fixup_device(pci_fixup_resume_early, pci_dev); 97762306a36Sopenharmony_ci pcie_pme_root_status_cleanup(pci_dev); 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci if (!skip_bus_pm && prev_state == PCI_D3cold) 98062306a36Sopenharmony_ci pci_pm_bridge_power_up_actions(pci_dev); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 98362306a36Sopenharmony_ci return 0; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci if (pm && pm->resume_noirq) 98662306a36Sopenharmony_ci return pm->resume_noirq(dev); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci return 0; 98962306a36Sopenharmony_ci} 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_cistatic int pci_pm_resume_early(struct device *dev) 99262306a36Sopenharmony_ci{ 99362306a36Sopenharmony_ci if (dev_pm_skip_resume(dev)) 99462306a36Sopenharmony_ci return 0; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci return pm_generic_resume_early(dev); 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_cistatic int pci_pm_resume(struct device *dev) 100062306a36Sopenharmony_ci{ 100162306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 100262306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci /* 100562306a36Sopenharmony_ci * This is necessary for the suspend error path in which resume is 100662306a36Sopenharmony_ci * called without restoring the standard config registers of the device. 100762306a36Sopenharmony_ci */ 100862306a36Sopenharmony_ci if (pci_dev->state_saved) 100962306a36Sopenharmony_ci pci_restore_standard_config(pci_dev); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci pci_resume_ptm(pci_dev); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 101462306a36Sopenharmony_ci return pci_legacy_resume(dev); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci pci_pm_default_resume(pci_dev); 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci if (pm) { 101962306a36Sopenharmony_ci if (pm->resume) 102062306a36Sopenharmony_ci return pm->resume(dev); 102162306a36Sopenharmony_ci } else { 102262306a36Sopenharmony_ci pci_pm_reenable_device(pci_dev); 102362306a36Sopenharmony_ci } 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci return 0; 102662306a36Sopenharmony_ci} 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci#else /* !CONFIG_SUSPEND */ 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci#define pci_pm_suspend NULL 103162306a36Sopenharmony_ci#define pci_pm_suspend_late NULL 103262306a36Sopenharmony_ci#define pci_pm_suspend_noirq NULL 103362306a36Sopenharmony_ci#define pci_pm_resume NULL 103462306a36Sopenharmony_ci#define pci_pm_resume_early NULL 103562306a36Sopenharmony_ci#define pci_pm_resume_noirq NULL 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci#endif /* !CONFIG_SUSPEND */ 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci#ifdef CONFIG_HIBERNATE_CALLBACKS 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_cistatic int pci_pm_freeze(struct device *dev) 104262306a36Sopenharmony_ci{ 104362306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 104462306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 104762306a36Sopenharmony_ci return pci_legacy_suspend(dev, PMSG_FREEZE); 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci if (!pm) { 105062306a36Sopenharmony_ci pci_pm_default_suspend(pci_dev); 105162306a36Sopenharmony_ci return 0; 105262306a36Sopenharmony_ci } 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci /* 105562306a36Sopenharmony_ci * Resume all runtime-suspended devices before creating a snapshot 105662306a36Sopenharmony_ci * image of system memory, because the restore kernel generally cannot 105762306a36Sopenharmony_ci * be expected to always handle them consistently and they need to be 105862306a36Sopenharmony_ci * put into the runtime-active metastate during system resume anyway, 105962306a36Sopenharmony_ci * so it is better to ensure that the state saved in the image will be 106062306a36Sopenharmony_ci * always consistent with that. 106162306a36Sopenharmony_ci */ 106262306a36Sopenharmony_ci pm_runtime_resume(dev); 106362306a36Sopenharmony_ci pci_dev->state_saved = false; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci if (pm->freeze) { 106662306a36Sopenharmony_ci int error; 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci error = pm->freeze(dev); 106962306a36Sopenharmony_ci suspend_report_result(dev, pm->freeze, error); 107062306a36Sopenharmony_ci if (error) 107162306a36Sopenharmony_ci return error; 107262306a36Sopenharmony_ci } 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci return 0; 107562306a36Sopenharmony_ci} 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_cistatic int pci_pm_freeze_noirq(struct device *dev) 107862306a36Sopenharmony_ci{ 107962306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 108062306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 108362306a36Sopenharmony_ci return pci_legacy_suspend_late(dev); 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci if (pm && pm->freeze_noirq) { 108662306a36Sopenharmony_ci int error; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci error = pm->freeze_noirq(dev); 108962306a36Sopenharmony_ci suspend_report_result(dev, pm->freeze_noirq, error); 109062306a36Sopenharmony_ci if (error) 109162306a36Sopenharmony_ci return error; 109262306a36Sopenharmony_ci } 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci if (!pci_dev->state_saved) 109562306a36Sopenharmony_ci pci_save_state(pci_dev); 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci pci_pm_set_unknown_state(pci_dev); 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci return 0; 110062306a36Sopenharmony_ci} 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_cistatic int pci_pm_thaw_noirq(struct device *dev) 110362306a36Sopenharmony_ci{ 110462306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 110562306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci /* 110862306a36Sopenharmony_ci * The pm->thaw_noirq() callback assumes the device has been 110962306a36Sopenharmony_ci * returned to D0 and its config state has been restored. 111062306a36Sopenharmony_ci * 111162306a36Sopenharmony_ci * In addition, pci_restore_state() restores MSI-X state in MMIO 111262306a36Sopenharmony_ci * space, which requires the device to be in D0, so return it to D0 111362306a36Sopenharmony_ci * in case the driver's "freeze" callbacks put it into a low-power 111462306a36Sopenharmony_ci * state. 111562306a36Sopenharmony_ci */ 111662306a36Sopenharmony_ci pci_pm_power_up_and_verify_state(pci_dev); 111762306a36Sopenharmony_ci pci_restore_state(pci_dev); 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 112062306a36Sopenharmony_ci return 0; 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci if (pm && pm->thaw_noirq) 112362306a36Sopenharmony_ci return pm->thaw_noirq(dev); 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci return 0; 112662306a36Sopenharmony_ci} 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_cistatic int pci_pm_thaw(struct device *dev) 112962306a36Sopenharmony_ci{ 113062306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 113162306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 113262306a36Sopenharmony_ci int error = 0; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 113562306a36Sopenharmony_ci return pci_legacy_resume(dev); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci if (pm) { 113862306a36Sopenharmony_ci if (pm->thaw) 113962306a36Sopenharmony_ci error = pm->thaw(dev); 114062306a36Sopenharmony_ci } else { 114162306a36Sopenharmony_ci pci_pm_reenable_device(pci_dev); 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci pci_dev->state_saved = false; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci return error; 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_cistatic int pci_pm_poweroff(struct device *dev) 115062306a36Sopenharmony_ci{ 115162306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 115262306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 115562306a36Sopenharmony_ci return pci_legacy_suspend(dev, PMSG_HIBERNATE); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci if (!pm) { 115862306a36Sopenharmony_ci pci_pm_default_suspend(pci_dev); 115962306a36Sopenharmony_ci return 0; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci /* The reason to do that is the same as in pci_pm_suspend(). */ 116362306a36Sopenharmony_ci if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || 116462306a36Sopenharmony_ci pci_dev_need_resume(pci_dev)) { 116562306a36Sopenharmony_ci pm_runtime_resume(dev); 116662306a36Sopenharmony_ci pci_dev->state_saved = false; 116762306a36Sopenharmony_ci } else { 116862306a36Sopenharmony_ci pci_dev_adjust_pme(pci_dev); 116962306a36Sopenharmony_ci } 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci if (pm->poweroff) { 117262306a36Sopenharmony_ci int error; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci error = pm->poweroff(dev); 117562306a36Sopenharmony_ci suspend_report_result(dev, pm->poweroff, error); 117662306a36Sopenharmony_ci if (error) 117762306a36Sopenharmony_ci return error; 117862306a36Sopenharmony_ci } 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci return 0; 118162306a36Sopenharmony_ci} 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_cistatic int pci_pm_poweroff_late(struct device *dev) 118462306a36Sopenharmony_ci{ 118562306a36Sopenharmony_ci if (dev_pm_skip_suspend(dev)) 118662306a36Sopenharmony_ci return 0; 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev)); 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci return pm_generic_poweroff_late(dev); 119162306a36Sopenharmony_ci} 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cistatic int pci_pm_poweroff_noirq(struct device *dev) 119462306a36Sopenharmony_ci{ 119562306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 119662306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci if (dev_pm_skip_suspend(dev)) 119962306a36Sopenharmony_ci return 0; 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 120262306a36Sopenharmony_ci return pci_legacy_suspend_late(dev); 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci if (!pm) { 120562306a36Sopenharmony_ci pci_fixup_device(pci_fixup_suspend_late, pci_dev); 120662306a36Sopenharmony_ci return 0; 120762306a36Sopenharmony_ci } 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci if (pm->poweroff_noirq) { 121062306a36Sopenharmony_ci int error; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci error = pm->poweroff_noirq(dev); 121362306a36Sopenharmony_ci suspend_report_result(dev, pm->poweroff_noirq, error); 121462306a36Sopenharmony_ci if (error) 121562306a36Sopenharmony_ci return error; 121662306a36Sopenharmony_ci } 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci if (!pci_dev->state_saved && !pci_has_subordinate(pci_dev)) 121962306a36Sopenharmony_ci pci_prepare_to_sleep(pci_dev); 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci /* 122262306a36Sopenharmony_ci * The reason for doing this here is the same as for the analogous code 122362306a36Sopenharmony_ci * in pci_pm_suspend_noirq(). 122462306a36Sopenharmony_ci */ 122562306a36Sopenharmony_ci if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) 122662306a36Sopenharmony_ci pci_write_config_word(pci_dev, PCI_COMMAND, 0); 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci pci_fixup_device(pci_fixup_suspend_late, pci_dev); 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci return 0; 123162306a36Sopenharmony_ci} 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_cistatic int pci_pm_restore_noirq(struct device *dev) 123462306a36Sopenharmony_ci{ 123562306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 123662306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci pci_pm_default_resume_early(pci_dev); 123962306a36Sopenharmony_ci pci_fixup_device(pci_fixup_resume_early, pci_dev); 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 124262306a36Sopenharmony_ci return 0; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci if (pm && pm->restore_noirq) 124562306a36Sopenharmony_ci return pm->restore_noirq(dev); 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci return 0; 124862306a36Sopenharmony_ci} 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_cistatic int pci_pm_restore(struct device *dev) 125162306a36Sopenharmony_ci{ 125262306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 125362306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci /* 125662306a36Sopenharmony_ci * This is necessary for the hibernation error path in which restore is 125762306a36Sopenharmony_ci * called without restoring the standard config registers of the device. 125862306a36Sopenharmony_ci */ 125962306a36Sopenharmony_ci if (pci_dev->state_saved) 126062306a36Sopenharmony_ci pci_restore_standard_config(pci_dev); 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci if (pci_has_legacy_pm_support(pci_dev)) 126362306a36Sopenharmony_ci return pci_legacy_resume(dev); 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci pci_pm_default_resume(pci_dev); 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci if (pm) { 126862306a36Sopenharmony_ci if (pm->restore) 126962306a36Sopenharmony_ci return pm->restore(dev); 127062306a36Sopenharmony_ci } else { 127162306a36Sopenharmony_ci pci_pm_reenable_device(pci_dev); 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci return 0; 127562306a36Sopenharmony_ci} 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci#else /* !CONFIG_HIBERNATE_CALLBACKS */ 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci#define pci_pm_freeze NULL 128062306a36Sopenharmony_ci#define pci_pm_freeze_noirq NULL 128162306a36Sopenharmony_ci#define pci_pm_thaw NULL 128262306a36Sopenharmony_ci#define pci_pm_thaw_noirq NULL 128362306a36Sopenharmony_ci#define pci_pm_poweroff NULL 128462306a36Sopenharmony_ci#define pci_pm_poweroff_late NULL 128562306a36Sopenharmony_ci#define pci_pm_poweroff_noirq NULL 128662306a36Sopenharmony_ci#define pci_pm_restore NULL 128762306a36Sopenharmony_ci#define pci_pm_restore_noirq NULL 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci#endif /* !CONFIG_HIBERNATE_CALLBACKS */ 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci#ifdef CONFIG_PM 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_cistatic int pci_pm_runtime_suspend(struct device *dev) 129462306a36Sopenharmony_ci{ 129562306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 129662306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 129762306a36Sopenharmony_ci pci_power_t prev = pci_dev->current_state; 129862306a36Sopenharmony_ci int error; 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci pci_suspend_ptm(pci_dev); 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci /* 130362306a36Sopenharmony_ci * If pci_dev->driver is not set (unbound), we leave the device in D0, 130462306a36Sopenharmony_ci * but it may go to D3cold when the bridge above it runtime suspends. 130562306a36Sopenharmony_ci * Save its config space in case that happens. 130662306a36Sopenharmony_ci */ 130762306a36Sopenharmony_ci if (!pci_dev->driver) { 130862306a36Sopenharmony_ci pci_save_state(pci_dev); 130962306a36Sopenharmony_ci return 0; 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci pci_dev->state_saved = false; 131362306a36Sopenharmony_ci if (pm && pm->runtime_suspend) { 131462306a36Sopenharmony_ci error = pm->runtime_suspend(dev); 131562306a36Sopenharmony_ci /* 131662306a36Sopenharmony_ci * -EBUSY and -EAGAIN is used to request the runtime PM core 131762306a36Sopenharmony_ci * to schedule a new suspend, so log the event only with debug 131862306a36Sopenharmony_ci * log level. 131962306a36Sopenharmony_ci */ 132062306a36Sopenharmony_ci if (error == -EBUSY || error == -EAGAIN) { 132162306a36Sopenharmony_ci pci_dbg(pci_dev, "can't suspend now (%ps returned %d)\n", 132262306a36Sopenharmony_ci pm->runtime_suspend, error); 132362306a36Sopenharmony_ci return error; 132462306a36Sopenharmony_ci } else if (error) { 132562306a36Sopenharmony_ci pci_err(pci_dev, "can't suspend (%ps returned %d)\n", 132662306a36Sopenharmony_ci pm->runtime_suspend, error); 132762306a36Sopenharmony_ci return error; 132862306a36Sopenharmony_ci } 132962306a36Sopenharmony_ci } 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci pci_fixup_device(pci_fixup_suspend, pci_dev); 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci if (pm && pm->runtime_suspend 133462306a36Sopenharmony_ci && !pci_dev->state_saved && pci_dev->current_state != PCI_D0 133562306a36Sopenharmony_ci && pci_dev->current_state != PCI_UNKNOWN) { 133662306a36Sopenharmony_ci pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 133762306a36Sopenharmony_ci "PCI PM: State of device not saved by %pS\n", 133862306a36Sopenharmony_ci pm->runtime_suspend); 133962306a36Sopenharmony_ci return 0; 134062306a36Sopenharmony_ci } 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci if (!pci_dev->state_saved) { 134362306a36Sopenharmony_ci pci_save_state(pci_dev); 134462306a36Sopenharmony_ci pci_finish_runtime_suspend(pci_dev); 134562306a36Sopenharmony_ci } 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci return 0; 134862306a36Sopenharmony_ci} 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_cistatic int pci_pm_runtime_resume(struct device *dev) 135162306a36Sopenharmony_ci{ 135262306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 135362306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 135462306a36Sopenharmony_ci pci_power_t prev_state = pci_dev->current_state; 135562306a36Sopenharmony_ci int error = 0; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci /* 135862306a36Sopenharmony_ci * Restoring config space is necessary even if the device is not bound 135962306a36Sopenharmony_ci * to a driver because although we left it in D0, it may have gone to 136062306a36Sopenharmony_ci * D3cold when the bridge above it runtime suspended. 136162306a36Sopenharmony_ci */ 136262306a36Sopenharmony_ci pci_pm_default_resume_early(pci_dev); 136362306a36Sopenharmony_ci pci_resume_ptm(pci_dev); 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci if (!pci_dev->driver) 136662306a36Sopenharmony_ci return 0; 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci pci_fixup_device(pci_fixup_resume_early, pci_dev); 136962306a36Sopenharmony_ci pci_pm_default_resume(pci_dev); 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci if (prev_state == PCI_D3cold) 137262306a36Sopenharmony_ci pci_pm_bridge_power_up_actions(pci_dev); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci if (pm && pm->runtime_resume) 137562306a36Sopenharmony_ci error = pm->runtime_resume(dev); 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci return error; 137862306a36Sopenharmony_ci} 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_cistatic int pci_pm_runtime_idle(struct device *dev) 138162306a36Sopenharmony_ci{ 138262306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 138362306a36Sopenharmony_ci const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci /* 138662306a36Sopenharmony_ci * If pci_dev->driver is not set (unbound), the device should 138762306a36Sopenharmony_ci * always remain in D0 regardless of the runtime PM status 138862306a36Sopenharmony_ci */ 138962306a36Sopenharmony_ci if (!pci_dev->driver) 139062306a36Sopenharmony_ci return 0; 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci if (!pm) 139362306a36Sopenharmony_ci return -ENOSYS; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci if (pm->runtime_idle) 139662306a36Sopenharmony_ci return pm->runtime_idle(dev); 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci return 0; 139962306a36Sopenharmony_ci} 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cistatic const struct dev_pm_ops pci_dev_pm_ops = { 140262306a36Sopenharmony_ci .prepare = pci_pm_prepare, 140362306a36Sopenharmony_ci .complete = pci_pm_complete, 140462306a36Sopenharmony_ci .suspend = pci_pm_suspend, 140562306a36Sopenharmony_ci .suspend_late = pci_pm_suspend_late, 140662306a36Sopenharmony_ci .resume = pci_pm_resume, 140762306a36Sopenharmony_ci .resume_early = pci_pm_resume_early, 140862306a36Sopenharmony_ci .freeze = pci_pm_freeze, 140962306a36Sopenharmony_ci .thaw = pci_pm_thaw, 141062306a36Sopenharmony_ci .poweroff = pci_pm_poweroff, 141162306a36Sopenharmony_ci .poweroff_late = pci_pm_poweroff_late, 141262306a36Sopenharmony_ci .restore = pci_pm_restore, 141362306a36Sopenharmony_ci .suspend_noirq = pci_pm_suspend_noirq, 141462306a36Sopenharmony_ci .resume_noirq = pci_pm_resume_noirq, 141562306a36Sopenharmony_ci .freeze_noirq = pci_pm_freeze_noirq, 141662306a36Sopenharmony_ci .thaw_noirq = pci_pm_thaw_noirq, 141762306a36Sopenharmony_ci .poweroff_noirq = pci_pm_poweroff_noirq, 141862306a36Sopenharmony_ci .restore_noirq = pci_pm_restore_noirq, 141962306a36Sopenharmony_ci .runtime_suspend = pci_pm_runtime_suspend, 142062306a36Sopenharmony_ci .runtime_resume = pci_pm_runtime_resume, 142162306a36Sopenharmony_ci .runtime_idle = pci_pm_runtime_idle, 142262306a36Sopenharmony_ci}; 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci#define PCI_PM_OPS_PTR (&pci_dev_pm_ops) 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci#else /* !CONFIG_PM */ 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci#define pci_pm_runtime_suspend NULL 142962306a36Sopenharmony_ci#define pci_pm_runtime_resume NULL 143062306a36Sopenharmony_ci#define pci_pm_runtime_idle NULL 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci#define PCI_PM_OPS_PTR NULL 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci#endif /* !CONFIG_PM */ 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci/** 143762306a36Sopenharmony_ci * __pci_register_driver - register a new pci driver 143862306a36Sopenharmony_ci * @drv: the driver structure to register 143962306a36Sopenharmony_ci * @owner: owner module of drv 144062306a36Sopenharmony_ci * @mod_name: module name string 144162306a36Sopenharmony_ci * 144262306a36Sopenharmony_ci * Adds the driver structure to the list of registered drivers. 144362306a36Sopenharmony_ci * Returns a negative value on error, otherwise 0. 144462306a36Sopenharmony_ci * If no error occurred, the driver remains registered even if 144562306a36Sopenharmony_ci * no device was claimed during registration. 144662306a36Sopenharmony_ci */ 144762306a36Sopenharmony_ciint __pci_register_driver(struct pci_driver *drv, struct module *owner, 144862306a36Sopenharmony_ci const char *mod_name) 144962306a36Sopenharmony_ci{ 145062306a36Sopenharmony_ci /* initialize common driver fields */ 145162306a36Sopenharmony_ci drv->driver.name = drv->name; 145262306a36Sopenharmony_ci drv->driver.bus = &pci_bus_type; 145362306a36Sopenharmony_ci drv->driver.owner = owner; 145462306a36Sopenharmony_ci drv->driver.mod_name = mod_name; 145562306a36Sopenharmony_ci drv->driver.groups = drv->groups; 145662306a36Sopenharmony_ci drv->driver.dev_groups = drv->dev_groups; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci spin_lock_init(&drv->dynids.lock); 145962306a36Sopenharmony_ci INIT_LIST_HEAD(&drv->dynids.list); 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci /* register with core */ 146262306a36Sopenharmony_ci return driver_register(&drv->driver); 146362306a36Sopenharmony_ci} 146462306a36Sopenharmony_ciEXPORT_SYMBOL(__pci_register_driver); 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci/** 146762306a36Sopenharmony_ci * pci_unregister_driver - unregister a pci driver 146862306a36Sopenharmony_ci * @drv: the driver structure to unregister 146962306a36Sopenharmony_ci * 147062306a36Sopenharmony_ci * Deletes the driver structure from the list of registered PCI drivers, 147162306a36Sopenharmony_ci * gives it a chance to clean up by calling its remove() function for 147262306a36Sopenharmony_ci * each device it was responsible for, and marks those devices as 147362306a36Sopenharmony_ci * driverless. 147462306a36Sopenharmony_ci */ 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_civoid pci_unregister_driver(struct pci_driver *drv) 147762306a36Sopenharmony_ci{ 147862306a36Sopenharmony_ci driver_unregister(&drv->driver); 147962306a36Sopenharmony_ci pci_free_dynids(drv); 148062306a36Sopenharmony_ci} 148162306a36Sopenharmony_ciEXPORT_SYMBOL(pci_unregister_driver); 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_cistatic struct pci_driver pci_compat_driver = { 148462306a36Sopenharmony_ci .name = "compat" 148562306a36Sopenharmony_ci}; 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci/** 148862306a36Sopenharmony_ci * pci_dev_driver - get the pci_driver of a device 148962306a36Sopenharmony_ci * @dev: the device to query 149062306a36Sopenharmony_ci * 149162306a36Sopenharmony_ci * Returns the appropriate pci_driver structure or %NULL if there is no 149262306a36Sopenharmony_ci * registered driver for the device. 149362306a36Sopenharmony_ci */ 149462306a36Sopenharmony_cistruct pci_driver *pci_dev_driver(const struct pci_dev *dev) 149562306a36Sopenharmony_ci{ 149662306a36Sopenharmony_ci int i; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci if (dev->driver) 149962306a36Sopenharmony_ci return dev->driver; 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci for (i = 0; i <= PCI_ROM_RESOURCE; i++) 150262306a36Sopenharmony_ci if (dev->resource[i].flags & IORESOURCE_BUSY) 150362306a36Sopenharmony_ci return &pci_compat_driver; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci return NULL; 150662306a36Sopenharmony_ci} 150762306a36Sopenharmony_ciEXPORT_SYMBOL(pci_dev_driver); 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci/** 151062306a36Sopenharmony_ci * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure 151162306a36Sopenharmony_ci * @dev: the PCI device structure to match against 151262306a36Sopenharmony_ci * @drv: the device driver to search for matching PCI device id structures 151362306a36Sopenharmony_ci * 151462306a36Sopenharmony_ci * Used by a driver to check whether a PCI device present in the 151562306a36Sopenharmony_ci * system is in its list of supported devices. Returns the matching 151662306a36Sopenharmony_ci * pci_device_id structure or %NULL if there is no match. 151762306a36Sopenharmony_ci */ 151862306a36Sopenharmony_cistatic int pci_bus_match(struct device *dev, struct device_driver *drv) 151962306a36Sopenharmony_ci{ 152062306a36Sopenharmony_ci struct pci_dev *pci_dev = to_pci_dev(dev); 152162306a36Sopenharmony_ci struct pci_driver *pci_drv; 152262306a36Sopenharmony_ci const struct pci_device_id *found_id; 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci if (!pci_dev->match_driver) 152562306a36Sopenharmony_ci return 0; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci pci_drv = to_pci_driver(drv); 152862306a36Sopenharmony_ci found_id = pci_match_device(pci_drv, pci_dev); 152962306a36Sopenharmony_ci if (found_id) 153062306a36Sopenharmony_ci return 1; 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci return 0; 153362306a36Sopenharmony_ci} 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci/** 153662306a36Sopenharmony_ci * pci_dev_get - increments the reference count of the pci device structure 153762306a36Sopenharmony_ci * @dev: the device being referenced 153862306a36Sopenharmony_ci * 153962306a36Sopenharmony_ci * Each live reference to a device should be refcounted. 154062306a36Sopenharmony_ci * 154162306a36Sopenharmony_ci * Drivers for PCI devices should normally record such references in 154262306a36Sopenharmony_ci * their probe() methods, when they bind to a device, and release 154362306a36Sopenharmony_ci * them by calling pci_dev_put(), in their disconnect() methods. 154462306a36Sopenharmony_ci * 154562306a36Sopenharmony_ci * A pointer to the device with the incremented reference counter is returned. 154662306a36Sopenharmony_ci */ 154762306a36Sopenharmony_cistruct pci_dev *pci_dev_get(struct pci_dev *dev) 154862306a36Sopenharmony_ci{ 154962306a36Sopenharmony_ci if (dev) 155062306a36Sopenharmony_ci get_device(&dev->dev); 155162306a36Sopenharmony_ci return dev; 155262306a36Sopenharmony_ci} 155362306a36Sopenharmony_ciEXPORT_SYMBOL(pci_dev_get); 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci/** 155662306a36Sopenharmony_ci * pci_dev_put - release a use of the pci device structure 155762306a36Sopenharmony_ci * @dev: device that's been disconnected 155862306a36Sopenharmony_ci * 155962306a36Sopenharmony_ci * Must be called when a user of a device is finished with it. When the last 156062306a36Sopenharmony_ci * user of the device calls this function, the memory of the device is freed. 156162306a36Sopenharmony_ci */ 156262306a36Sopenharmony_civoid pci_dev_put(struct pci_dev *dev) 156362306a36Sopenharmony_ci{ 156462306a36Sopenharmony_ci if (dev) 156562306a36Sopenharmony_ci put_device(&dev->dev); 156662306a36Sopenharmony_ci} 156762306a36Sopenharmony_ciEXPORT_SYMBOL(pci_dev_put); 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_cistatic int pci_uevent(const struct device *dev, struct kobj_uevent_env *env) 157062306a36Sopenharmony_ci{ 157162306a36Sopenharmony_ci const struct pci_dev *pdev; 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci if (!dev) 157462306a36Sopenharmony_ci return -ENODEV; 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci pdev = to_pci_dev(dev); 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class)) 157962306a36Sopenharmony_ci return -ENOMEM; 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) 158262306a36Sopenharmony_ci return -ENOMEM; 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, 158562306a36Sopenharmony_ci pdev->subsystem_device)) 158662306a36Sopenharmony_ci return -ENOMEM; 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev))) 158962306a36Sopenharmony_ci return -ENOMEM; 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X", 159262306a36Sopenharmony_ci pdev->vendor, pdev->device, 159362306a36Sopenharmony_ci pdev->subsystem_vendor, pdev->subsystem_device, 159462306a36Sopenharmony_ci (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), 159562306a36Sopenharmony_ci (u8)(pdev->class))) 159662306a36Sopenharmony_ci return -ENOMEM; 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci return 0; 159962306a36Sopenharmony_ci} 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci#if defined(CONFIG_PCIEAER) || defined(CONFIG_EEH) 160262306a36Sopenharmony_ci/** 160362306a36Sopenharmony_ci * pci_uevent_ers - emit a uevent during recovery path of PCI device 160462306a36Sopenharmony_ci * @pdev: PCI device undergoing error recovery 160562306a36Sopenharmony_ci * @err_type: type of error event 160662306a36Sopenharmony_ci */ 160762306a36Sopenharmony_civoid pci_uevent_ers(struct pci_dev *pdev, enum pci_ers_result err_type) 160862306a36Sopenharmony_ci{ 160962306a36Sopenharmony_ci int idx = 0; 161062306a36Sopenharmony_ci char *envp[3]; 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci switch (err_type) { 161362306a36Sopenharmony_ci case PCI_ERS_RESULT_NONE: 161462306a36Sopenharmony_ci case PCI_ERS_RESULT_CAN_RECOVER: 161562306a36Sopenharmony_ci envp[idx++] = "ERROR_EVENT=BEGIN_RECOVERY"; 161662306a36Sopenharmony_ci envp[idx++] = "DEVICE_ONLINE=0"; 161762306a36Sopenharmony_ci break; 161862306a36Sopenharmony_ci case PCI_ERS_RESULT_RECOVERED: 161962306a36Sopenharmony_ci envp[idx++] = "ERROR_EVENT=SUCCESSFUL_RECOVERY"; 162062306a36Sopenharmony_ci envp[idx++] = "DEVICE_ONLINE=1"; 162162306a36Sopenharmony_ci break; 162262306a36Sopenharmony_ci case PCI_ERS_RESULT_DISCONNECT: 162362306a36Sopenharmony_ci envp[idx++] = "ERROR_EVENT=FAILED_RECOVERY"; 162462306a36Sopenharmony_ci envp[idx++] = "DEVICE_ONLINE=0"; 162562306a36Sopenharmony_ci break; 162662306a36Sopenharmony_ci default: 162762306a36Sopenharmony_ci break; 162862306a36Sopenharmony_ci } 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci if (idx > 0) { 163162306a36Sopenharmony_ci envp[idx++] = NULL; 163262306a36Sopenharmony_ci kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp); 163362306a36Sopenharmony_ci } 163462306a36Sopenharmony_ci} 163562306a36Sopenharmony_ci#endif 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_cistatic int pci_bus_num_vf(struct device *dev) 163862306a36Sopenharmony_ci{ 163962306a36Sopenharmony_ci return pci_num_vf(to_pci_dev(dev)); 164062306a36Sopenharmony_ci} 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci/** 164362306a36Sopenharmony_ci * pci_dma_configure - Setup DMA configuration 164462306a36Sopenharmony_ci * @dev: ptr to dev structure 164562306a36Sopenharmony_ci * 164662306a36Sopenharmony_ci * Function to update PCI devices's DMA configuration using the same 164762306a36Sopenharmony_ci * info from the OF node or ACPI node of host bridge's parent (if any). 164862306a36Sopenharmony_ci */ 164962306a36Sopenharmony_cistatic int pci_dma_configure(struct device *dev) 165062306a36Sopenharmony_ci{ 165162306a36Sopenharmony_ci struct pci_driver *driver = to_pci_driver(dev->driver); 165262306a36Sopenharmony_ci struct device *bridge; 165362306a36Sopenharmony_ci int ret = 0; 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci bridge = pci_get_host_bridge_device(to_pci_dev(dev)); 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_OF) && bridge->parent && 165862306a36Sopenharmony_ci bridge->parent->of_node) { 165962306a36Sopenharmony_ci ret = of_dma_configure(dev, bridge->parent->of_node, true); 166062306a36Sopenharmony_ci } else if (has_acpi_companion(bridge)) { 166162306a36Sopenharmony_ci struct acpi_device *adev = to_acpi_device_node(bridge->fwnode); 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci ret = acpi_dma_configure(dev, acpi_get_dma_attr(adev)); 166462306a36Sopenharmony_ci } 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci pci_put_host_bridge_device(bridge); 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci if (!ret && !driver->driver_managed_dma) { 166962306a36Sopenharmony_ci ret = iommu_device_use_default_domain(dev); 167062306a36Sopenharmony_ci if (ret) 167162306a36Sopenharmony_ci arch_teardown_dma_ops(dev); 167262306a36Sopenharmony_ci } 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci return ret; 167562306a36Sopenharmony_ci} 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_cistatic void pci_dma_cleanup(struct device *dev) 167862306a36Sopenharmony_ci{ 167962306a36Sopenharmony_ci struct pci_driver *driver = to_pci_driver(dev->driver); 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci if (!driver->driver_managed_dma) 168262306a36Sopenharmony_ci iommu_device_unuse_default_domain(dev); 168362306a36Sopenharmony_ci} 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_cistruct bus_type pci_bus_type = { 168662306a36Sopenharmony_ci .name = "pci", 168762306a36Sopenharmony_ci .match = pci_bus_match, 168862306a36Sopenharmony_ci .uevent = pci_uevent, 168962306a36Sopenharmony_ci .probe = pci_device_probe, 169062306a36Sopenharmony_ci .remove = pci_device_remove, 169162306a36Sopenharmony_ci .shutdown = pci_device_shutdown, 169262306a36Sopenharmony_ci .dev_groups = pci_dev_groups, 169362306a36Sopenharmony_ci .bus_groups = pci_bus_groups, 169462306a36Sopenharmony_ci .drv_groups = pci_drv_groups, 169562306a36Sopenharmony_ci .pm = PCI_PM_OPS_PTR, 169662306a36Sopenharmony_ci .num_vf = pci_bus_num_vf, 169762306a36Sopenharmony_ci .dma_configure = pci_dma_configure, 169862306a36Sopenharmony_ci .dma_cleanup = pci_dma_cleanup, 169962306a36Sopenharmony_ci}; 170062306a36Sopenharmony_ciEXPORT_SYMBOL(pci_bus_type); 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci#ifdef CONFIG_PCIEPORTBUS 170362306a36Sopenharmony_cistatic int pcie_port_bus_match(struct device *dev, struct device_driver *drv) 170462306a36Sopenharmony_ci{ 170562306a36Sopenharmony_ci struct pcie_device *pciedev; 170662306a36Sopenharmony_ci struct pcie_port_service_driver *driver; 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) 170962306a36Sopenharmony_ci return 0; 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci pciedev = to_pcie_device(dev); 171262306a36Sopenharmony_ci driver = to_service_driver(drv); 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci if (driver->service != pciedev->service) 171562306a36Sopenharmony_ci return 0; 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci if (driver->port_type != PCIE_ANY_PORT && 171862306a36Sopenharmony_ci driver->port_type != pci_pcie_type(pciedev->port)) 171962306a36Sopenharmony_ci return 0; 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci return 1; 172262306a36Sopenharmony_ci} 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_cistruct bus_type pcie_port_bus_type = { 172562306a36Sopenharmony_ci .name = "pci_express", 172662306a36Sopenharmony_ci .match = pcie_port_bus_match, 172762306a36Sopenharmony_ci}; 172862306a36Sopenharmony_ci#endif 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_cistatic int __init pci_driver_init(void) 173162306a36Sopenharmony_ci{ 173262306a36Sopenharmony_ci int ret; 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_ci ret = bus_register(&pci_bus_type); 173562306a36Sopenharmony_ci if (ret) 173662306a36Sopenharmony_ci return ret; 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci#ifdef CONFIG_PCIEPORTBUS 173962306a36Sopenharmony_ci ret = bus_register(&pcie_port_bus_type); 174062306a36Sopenharmony_ci if (ret) 174162306a36Sopenharmony_ci return ret; 174262306a36Sopenharmony_ci#endif 174362306a36Sopenharmony_ci dma_debug_add_bus(&pci_bus_type); 174462306a36Sopenharmony_ci return 0; 174562306a36Sopenharmony_ci} 174662306a36Sopenharmony_cipostcore_initcall(pci_driver_init); 1747