18cfab3cfSBjorn Helgaas // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 32b937303SGreg Kroah-Hartman * (C) Copyright 2002-2004, 2007 Greg Kroah-Hartman <greg@kroah.com> 42b937303SGreg Kroah-Hartman * (C) Copyright 2007 Novell Inc. 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds #include <linux/pci.h> 81da177e4SLinus Torvalds #include <linux/module.h> 91da177e4SLinus Torvalds #include <linux/init.h> 101da177e4SLinus Torvalds #include <linux/device.h> 11d42c6997SAndi Kleen #include <linux/mempolicy.h> 124e57b681STim Schmielau #include <linux/string.h> 134e57b681STim Schmielau #include <linux/slab.h> 148c65b4a6STim Schmielau #include <linux/sched.h> 15873392caSRusty Russell #include <linux/cpu.h> 166cbf8214SRafael J. Wysocki #include <linux/pm_runtime.h> 17eea3fc03SRafael J. Wysocki #include <linux/suspend.h> 184fc9bbf9SKhalid Aziz #include <linux/kexec.h> 1907397df2SNipun Gupta #include <linux/of_device.h> 2007397df2SNipun Gupta #include <linux/acpi.h> 211da177e4SLinus Torvalds #include "pci.h" 22c6c889d9SBjorn Helgaas #include "pcie/portdrv.h" 231da177e4SLinus Torvalds 2475865858SGreg Kroah-Hartman struct pci_dynid { 2575865858SGreg Kroah-Hartman struct list_head node; 2675865858SGreg Kroah-Hartman struct pci_device_id id; 2775865858SGreg Kroah-Hartman }; 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds /** 309dba910eSTejun Heo * pci_add_dynid - add a new PCI device ID to this driver and re-probe devices 319dba910eSTejun Heo * @drv: target pci driver 329dba910eSTejun Heo * @vendor: PCI vendor ID 339dba910eSTejun Heo * @device: PCI device ID 349dba910eSTejun Heo * @subvendor: PCI subvendor ID 359dba910eSTejun Heo * @subdevice: PCI subdevice ID 369dba910eSTejun Heo * @class: PCI class 379dba910eSTejun Heo * @class_mask: PCI class mask 389dba910eSTejun Heo * @driver_data: private driver data 399dba910eSTejun Heo * 409dba910eSTejun Heo * Adds a new dynamic pci device ID to this driver and causes the 419dba910eSTejun Heo * driver to probe for all devices again. @drv must have been 429dba910eSTejun Heo * registered prior to calling this function. 439dba910eSTejun Heo * 449dba910eSTejun Heo * CONTEXT: 459dba910eSTejun Heo * Does GFP_KERNEL allocation. 469dba910eSTejun Heo * 479dba910eSTejun Heo * RETURNS: 489dba910eSTejun Heo * 0 on success, -errno on failure. 499dba910eSTejun Heo */ 509dba910eSTejun Heo int pci_add_dynid(struct pci_driver *drv, 519dba910eSTejun Heo unsigned int vendor, unsigned int device, 529dba910eSTejun Heo unsigned int subvendor, unsigned int subdevice, 539dba910eSTejun Heo unsigned int class, unsigned int class_mask, 549dba910eSTejun Heo unsigned long driver_data) 559dba910eSTejun Heo { 569dba910eSTejun Heo struct pci_dynid *dynid; 579dba910eSTejun Heo 589dba910eSTejun Heo dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); 599dba910eSTejun Heo if (!dynid) 609dba910eSTejun Heo return -ENOMEM; 619dba910eSTejun Heo 629dba910eSTejun Heo dynid->id.vendor = vendor; 639dba910eSTejun Heo dynid->id.device = device; 649dba910eSTejun Heo dynid->id.subvendor = subvendor; 659dba910eSTejun Heo dynid->id.subdevice = subdevice; 669dba910eSTejun Heo dynid->id.class = class; 679dba910eSTejun Heo dynid->id.class_mask = class_mask; 689dba910eSTejun Heo dynid->id.driver_data = driver_data; 699dba910eSTejun Heo 709dba910eSTejun Heo spin_lock(&drv->dynids.lock); 719dba910eSTejun Heo list_add_tail(&dynid->node, &drv->dynids.list); 729dba910eSTejun Heo spin_unlock(&drv->dynids.lock); 739dba910eSTejun Heo 743b7f1016STobias Klauser return driver_attach(&drv->driver); 759dba910eSTejun Heo } 76b7fe9434SRyan Desfosses EXPORT_SYMBOL_GPL(pci_add_dynid); 779dba910eSTejun Heo 789dba910eSTejun Heo static void pci_free_dynids(struct pci_driver *drv) 799dba910eSTejun Heo { 809dba910eSTejun Heo struct pci_dynid *dynid, *n; 819dba910eSTejun Heo 829dba910eSTejun Heo spin_lock(&drv->dynids.lock); 839dba910eSTejun Heo list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { 849dba910eSTejun Heo list_del(&dynid->node); 859dba910eSTejun Heo kfree(dynid); 869dba910eSTejun Heo } 879dba910eSTejun Heo spin_unlock(&drv->dynids.lock); 889dba910eSTejun Heo } 899dba910eSTejun Heo 909dba910eSTejun Heo /** 919dba910eSTejun Heo * store_new_id - sysfs frontend to pci_add_dynid() 928f7020d3SRandy Dunlap * @driver: target device driver 938f7020d3SRandy Dunlap * @buf: buffer for scanning device ID data 948f7020d3SRandy Dunlap * @count: input size 951da177e4SLinus Torvalds * 969dba910eSTejun Heo * Allow PCI IDs to be added to an existing driver via sysfs. 971da177e4SLinus Torvalds */ 98a9427741SGreg Kroah-Hartman static ssize_t new_id_store(struct device_driver *driver, const char *buf, 993c78bc61SRyan Desfosses size_t count) 1001da177e4SLinus Torvalds { 1011da177e4SLinus Torvalds struct pci_driver *pdrv = to_pci_driver(driver); 102b41d6cf3SJean Delvare const struct pci_device_id *ids = pdrv->id_table; 10320a796a9SLogan Gunthorpe u32 vendor, device, subvendor = PCI_ANY_ID, 1041da177e4SLinus Torvalds subdevice = PCI_ANY_ID, class = 0, class_mask = 0; 1051da177e4SLinus Torvalds unsigned long driver_data = 0; 1061da177e4SLinus Torvalds int fields = 0; 1078895d3bcSBandan Das int retval = 0; 1081da177e4SLinus Torvalds 109b41d6cf3SJean Delvare fields = sscanf(buf, "%x %x %x %x %x %x %lx", 1101da177e4SLinus Torvalds &vendor, &device, &subvendor, &subdevice, 1111da177e4SLinus Torvalds &class, &class_mask, &driver_data); 1126ba18636SJean Delvare if (fields < 2) 1131da177e4SLinus Torvalds return -EINVAL; 1141da177e4SLinus Torvalds 1158895d3bcSBandan Das if (fields != 7) { 1168895d3bcSBandan Das struct pci_dev *pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); 1178895d3bcSBandan Das if (!pdev) 1188895d3bcSBandan Das return -ENOMEM; 1198895d3bcSBandan Das 1208895d3bcSBandan Das pdev->vendor = vendor; 1218895d3bcSBandan Das pdev->device = device; 1228895d3bcSBandan Das pdev->subsystem_vendor = subvendor; 1238895d3bcSBandan Das pdev->subsystem_device = subdevice; 1248895d3bcSBandan Das pdev->class = class; 1258895d3bcSBandan Das 1268895d3bcSBandan Das if (pci_match_id(pdrv->id_table, pdev)) 1278895d3bcSBandan Das retval = -EEXIST; 1288895d3bcSBandan Das 1298895d3bcSBandan Das kfree(pdev); 1308895d3bcSBandan Das 1318895d3bcSBandan Das if (retval) 1328895d3bcSBandan Das return retval; 1338895d3bcSBandan Das } 1348895d3bcSBandan Das 135b41d6cf3SJean Delvare /* Only accept driver_data values that match an existing id_table 136b41d6cf3SJean Delvare entry */ 1372debb4d2SChris Wright if (ids) { 138b41d6cf3SJean Delvare retval = -EINVAL; 139b41d6cf3SJean Delvare while (ids->vendor || ids->subvendor || ids->class_mask) { 140b41d6cf3SJean Delvare if (driver_data == ids->driver_data) { 141b41d6cf3SJean Delvare retval = 0; 142b41d6cf3SJean Delvare break; 143b41d6cf3SJean Delvare } 144b41d6cf3SJean Delvare ids++; 145b41d6cf3SJean Delvare } 146b41d6cf3SJean Delvare if (retval) /* No match */ 147b41d6cf3SJean Delvare return retval; 1482debb4d2SChris Wright } 149b41d6cf3SJean Delvare 1509dba910eSTejun Heo retval = pci_add_dynid(pdrv, vendor, device, subvendor, subdevice, 1519dba910eSTejun Heo class, class_mask, driver_data); 152b19441afSGreg Kroah-Hartman if (retval) 153b19441afSGreg Kroah-Hartman return retval; 1541da177e4SLinus Torvalds return count; 1551da177e4SLinus Torvalds } 156a9427741SGreg Kroah-Hartman static DRIVER_ATTR_WO(new_id); 1571da177e4SLinus Torvalds 1580994375eSChris Wright /** 1590994375eSChris Wright * store_remove_id - remove a PCI device ID from this driver 1600994375eSChris Wright * @driver: target device driver 1610994375eSChris Wright * @buf: buffer for scanning device ID data 1620994375eSChris Wright * @count: input size 1630994375eSChris Wright * 1640994375eSChris Wright * Removes a dynamic pci device ID to this driver. 1650994375eSChris Wright */ 166a9427741SGreg Kroah-Hartman static ssize_t remove_id_store(struct device_driver *driver, const char *buf, 1673c78bc61SRyan Desfosses size_t count) 1680994375eSChris Wright { 1690994375eSChris Wright struct pci_dynid *dynid, *n; 1700994375eSChris Wright struct pci_driver *pdrv = to_pci_driver(driver); 17120a796a9SLogan Gunthorpe u32 vendor, device, subvendor = PCI_ANY_ID, 1720994375eSChris Wright subdevice = PCI_ANY_ID, class = 0, class_mask = 0; 1730994375eSChris Wright int fields = 0; 1749222097fSZhen Lei size_t retval = -ENODEV; 1750994375eSChris Wright 1760994375eSChris Wright fields = sscanf(buf, "%x %x %x %x %x %x", 1770994375eSChris Wright &vendor, &device, &subvendor, &subdevice, 1780994375eSChris Wright &class, &class_mask); 1790994375eSChris Wright if (fields < 2) 1800994375eSChris Wright return -EINVAL; 1810994375eSChris Wright 1820994375eSChris Wright spin_lock(&pdrv->dynids.lock); 1830994375eSChris Wright list_for_each_entry_safe(dynid, n, &pdrv->dynids.list, node) { 1840994375eSChris Wright struct pci_device_id *id = &dynid->id; 1850994375eSChris Wright if ((id->vendor == vendor) && 1860994375eSChris Wright (id->device == device) && 1870994375eSChris Wright (subvendor == PCI_ANY_ID || id->subvendor == subvendor) && 1880994375eSChris Wright (subdevice == PCI_ANY_ID || id->subdevice == subdevice) && 1890994375eSChris Wright !((id->class ^ class) & class_mask)) { 1900994375eSChris Wright list_del(&dynid->node); 1910994375eSChris Wright kfree(dynid); 1929222097fSZhen Lei retval = count; 1930994375eSChris Wright break; 1940994375eSChris Wright } 1950994375eSChris Wright } 1960994375eSChris Wright spin_unlock(&pdrv->dynids.lock); 1970994375eSChris Wright 1980994375eSChris Wright return retval; 1990994375eSChris Wright } 200a9427741SGreg Kroah-Hartman static DRIVER_ATTR_WO(remove_id); 2010994375eSChris Wright 2022229c1fbSGreg Kroah-Hartman static struct attribute *pci_drv_attrs[] = { 2032229c1fbSGreg Kroah-Hartman &driver_attr_new_id.attr, 2042229c1fbSGreg Kroah-Hartman &driver_attr_remove_id.attr, 2052229c1fbSGreg Kroah-Hartman NULL, 206bfb09a86SKonstantin Khlebnikov }; 2072229c1fbSGreg Kroah-Hartman ATTRIBUTE_GROUPS(pci_drv); 208ed283e9fSAlan Stern 2091da177e4SLinus Torvalds /** 21075865858SGreg Kroah-Hartman * pci_match_id - See if a pci device matches a given pci_id table 2111da177e4SLinus Torvalds * @ids: array of PCI device id structures to search in 21275865858SGreg Kroah-Hartman * @dev: the PCI device structure to match against. 2131da177e4SLinus Torvalds * 2141da177e4SLinus Torvalds * Used by a driver to check whether a PCI device present in the 2151da177e4SLinus Torvalds * system is in its list of supported devices. Returns the matching 2161da177e4SLinus Torvalds * pci_device_id structure or %NULL if there is no match. 21775865858SGreg Kroah-Hartman * 2188b60756aSRandy Dunlap * Deprecated, don't use this as it will not catch any dynamic ids 21975865858SGreg Kroah-Hartman * that a driver might want to check for. 2201da177e4SLinus Torvalds */ 22175865858SGreg Kroah-Hartman const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, 22275865858SGreg Kroah-Hartman struct pci_dev *dev) 2231da177e4SLinus Torvalds { 22475865858SGreg Kroah-Hartman if (ids) { 2251da177e4SLinus Torvalds while (ids->vendor || ids->subvendor || ids->class_mask) { 2261da177e4SLinus Torvalds if (pci_match_one_device(ids, dev)) 2271da177e4SLinus Torvalds return ids; 2281da177e4SLinus Torvalds ids++; 2291da177e4SLinus Torvalds } 23075865858SGreg Kroah-Hartman } 2311da177e4SLinus Torvalds return NULL; 2321da177e4SLinus Torvalds } 233b7fe9434SRyan Desfosses EXPORT_SYMBOL(pci_match_id); 2341da177e4SLinus Torvalds 235782a985dSAlex Williamson static const struct pci_device_id pci_device_id_any = { 236782a985dSAlex Williamson .vendor = PCI_ANY_ID, 237782a985dSAlex Williamson .device = PCI_ANY_ID, 238782a985dSAlex Williamson .subvendor = PCI_ANY_ID, 239782a985dSAlex Williamson .subdevice = PCI_ANY_ID, 240782a985dSAlex Williamson }; 241782a985dSAlex Williamson 2421da177e4SLinus Torvalds /** 243ae9608afSRandy Dunlap * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure 24475865858SGreg Kroah-Hartman * @drv: the PCI driver to match against 24539ba487fSHenrik Kretzschmar * @dev: the PCI device structure to match against 2461da177e4SLinus Torvalds * 24775865858SGreg Kroah-Hartman * Used by a driver to check whether a PCI device present in the 24875865858SGreg Kroah-Hartman * system is in its list of supported devices. Returns the matching 24975865858SGreg Kroah-Hartman * pci_device_id structure or %NULL if there is no match. 2501da177e4SLinus Torvalds */ 251d73460d7SAdrian Bunk static const struct pci_device_id *pci_match_device(struct pci_driver *drv, 25275865858SGreg Kroah-Hartman struct pci_dev *dev) 2531da177e4SLinus Torvalds { 25475865858SGreg Kroah-Hartman struct pci_dynid *dynid; 255782a985dSAlex Williamson const struct pci_device_id *found_id = NULL; 256782a985dSAlex Williamson 257782a985dSAlex Williamson /* When driver_override is set, only bind to the matching driver */ 258782a985dSAlex Williamson if (dev->driver_override && strcmp(dev->driver_override, drv->name)) 259782a985dSAlex Williamson return NULL; 2601da177e4SLinus Torvalds 2617461b60aSRussell King /* Look at the dynamic ids first, before the static ones */ 26275865858SGreg Kroah-Hartman spin_lock(&drv->dynids.lock); 26375865858SGreg Kroah-Hartman list_for_each_entry(dynid, &drv->dynids.list, node) { 26475865858SGreg Kroah-Hartman if (pci_match_one_device(&dynid->id, dev)) { 265782a985dSAlex Williamson found_id = &dynid->id; 266782a985dSAlex Williamson break; 2671da177e4SLinus Torvalds } 26875865858SGreg Kroah-Hartman } 26975865858SGreg Kroah-Hartman spin_unlock(&drv->dynids.lock); 2707461b60aSRussell King 271782a985dSAlex Williamson if (!found_id) 272782a985dSAlex Williamson found_id = pci_match_id(drv->id_table, dev); 273782a985dSAlex Williamson 274782a985dSAlex Williamson /* driver_override will always match, send a dummy id */ 275782a985dSAlex Williamson if (!found_id && dev->driver_override) 276782a985dSAlex Williamson found_id = &pci_device_id_any; 277782a985dSAlex Williamson 278782a985dSAlex Williamson return found_id; 2791da177e4SLinus Torvalds } 2801da177e4SLinus Torvalds 281873392caSRusty Russell struct drv_dev_and_id { 282873392caSRusty Russell struct pci_driver *drv; 283873392caSRusty Russell struct pci_dev *dev; 284873392caSRusty Russell const struct pci_device_id *id; 285873392caSRusty Russell }; 286873392caSRusty Russell 287873392caSRusty Russell static long local_pci_probe(void *_ddi) 288873392caSRusty Russell { 289873392caSRusty Russell struct drv_dev_and_id *ddi = _ddi; 290967577b0SHuang Ying struct pci_dev *pci_dev = ddi->dev; 291967577b0SHuang Ying struct pci_driver *pci_drv = ddi->drv; 292967577b0SHuang Ying struct device *dev = &pci_dev->dev; 293f3ec4f87SAlan Stern int rc; 294873392caSRusty Russell 295967577b0SHuang Ying /* 296967577b0SHuang Ying * Unbound PCI devices are always put in D0, regardless of 297967577b0SHuang Ying * runtime PM status. During probe, the device is set to 298967577b0SHuang Ying * active and the usage count is incremented. If the driver 299a8360062SRafael J. Wysocki * supports runtime PM, it should call pm_runtime_put_noidle(), 300a8360062SRafael J. Wysocki * or any other runtime PM helper function decrementing the usage 301a8360062SRafael J. Wysocki * count, in its probe routine and pm_runtime_get_noresume() in 302a8360062SRafael J. Wysocki * its remove routine. 303f3ec4f87SAlan Stern */ 304967577b0SHuang Ying pm_runtime_get_sync(dev); 305967577b0SHuang Ying pci_dev->driver = pci_drv; 306967577b0SHuang Ying rc = pci_drv->probe(pci_dev, ddi->id); 307f92d74c1SStephen M. Cameron if (!rc) 308f92d74c1SStephen M. Cameron return rc; 309f92d74c1SStephen M. Cameron if (rc < 0) { 310967577b0SHuang Ying pci_dev->driver = NULL; 311967577b0SHuang Ying pm_runtime_put_sync(dev); 312f3ec4f87SAlan Stern return rc; 313873392caSRusty Russell } 314f92d74c1SStephen M. Cameron /* 315f92d74c1SStephen M. Cameron * Probe function should return < 0 for failure, 0 for success 316f92d74c1SStephen M. Cameron * Treat values > 0 as success, but warn. 317f92d74c1SStephen M. Cameron */ 3186941a0c2SBjorn Helgaas pci_warn(pci_dev, "Driver probe function unexpectedly returned %d\n", 3196941a0c2SBjorn Helgaas rc); 320f92d74c1SStephen M. Cameron return 0; 321f92d74c1SStephen M. Cameron } 322873392caSRusty Russell 3230b2c2a71SThomas Gleixner static bool pci_physfn_is_probed(struct pci_dev *dev) 3240b2c2a71SThomas Gleixner { 3250b2c2a71SThomas Gleixner #ifdef CONFIG_PCI_IOV 3260b2c2a71SThomas Gleixner return dev->is_virtfn && dev->physfn->is_probed; 3270b2c2a71SThomas Gleixner #else 3280b2c2a71SThomas Gleixner return false; 3290b2c2a71SThomas Gleixner #endif 3300b2c2a71SThomas Gleixner } 3310b2c2a71SThomas Gleixner 332d42c6997SAndi Kleen static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, 333d42c6997SAndi Kleen const struct pci_device_id *id) 334d42c6997SAndi Kleen { 3350b2c2a71SThomas Gleixner int error, node, cpu; 336873392caSRusty Russell struct drv_dev_and_id ddi = { drv, dev, id }; 337f70316daSMike Travis 33812c3156fSAlexander Duyck /* 33912c3156fSAlexander Duyck * Execute driver initialization on node where the device is 34012c3156fSAlexander Duyck * attached. This way the driver likely allocates its local memory 34112c3156fSAlexander Duyck * on the right node. 34212c3156fSAlexander Duyck */ 343873392caSRusty Russell node = dev_to_node(&dev->dev); 3440b2c2a71SThomas Gleixner dev->is_probed = 1; 345873392caSRusty Russell 3461ddd45f8SThomas Gleixner cpu_hotplug_disable(); 3470b2c2a71SThomas Gleixner 3480b2c2a71SThomas Gleixner /* 3490b2c2a71SThomas Gleixner * Prevent nesting work_on_cpu() for the case where a Virtual Function 3500b2c2a71SThomas Gleixner * device is probed from work_on_cpu() of the Physical device. 3510b2c2a71SThomas Gleixner */ 3520b2c2a71SThomas Gleixner if (node < 0 || node >= MAX_NUMNODES || !node_online(node) || 3530b2c2a71SThomas Gleixner pci_physfn_is_probed(dev)) 3540b2c2a71SThomas Gleixner cpu = nr_cpu_ids; 3550b2c2a71SThomas Gleixner else 356a70f7302SRusty Russell cpu = cpumask_any_and(cpumask_of_node(node), cpu_online_mask); 3570b2c2a71SThomas Gleixner 358873392caSRusty Russell if (cpu < nr_cpu_ids) 359873392caSRusty Russell error = work_on_cpu(cpu, local_pci_probe, &ddi); 360873392caSRusty Russell else 361873392caSRusty Russell error = local_pci_probe(&ddi); 36212c3156fSAlexander Duyck 3630b2c2a71SThomas Gleixner dev->is_probed = 0; 3640b2c2a71SThomas Gleixner cpu_hotplug_enable(); 365d42c6997SAndi Kleen return error; 366d42c6997SAndi Kleen } 367d42c6997SAndi Kleen 3681da177e4SLinus Torvalds /** 36923ea3793SRandy Dunlap * __pci_device_probe - check if a driver wants to claim a specific PCI device 3708f7020d3SRandy Dunlap * @drv: driver to call to check if it wants the PCI device 3718f7020d3SRandy Dunlap * @pci_dev: PCI device being probed 3721da177e4SLinus Torvalds * 3731da177e4SLinus Torvalds * returns 0 on success, else error. 3741da177e4SLinus Torvalds * side-effect: pci_dev->driver is set to drv when drv claims pci_dev. 3751da177e4SLinus Torvalds */ 3763c78bc61SRyan Desfosses static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) 3771da177e4SLinus Torvalds { 37875865858SGreg Kroah-Hartman const struct pci_device_id *id; 3791da177e4SLinus Torvalds int error = 0; 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds if (!pci_dev->driver && drv->probe) { 38275865858SGreg Kroah-Hartman error = -ENODEV; 38375865858SGreg Kroah-Hartman 38475865858SGreg Kroah-Hartman id = pci_match_device(drv, pci_dev); 38575865858SGreg Kroah-Hartman if (id) 386d42c6997SAndi Kleen error = pci_call_probe(drv, pci_dev, id); 38775865858SGreg Kroah-Hartman } 3881da177e4SLinus Torvalds return error; 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds 391890e4847SJiang Liu int __weak pcibios_alloc_irq(struct pci_dev *dev) 392890e4847SJiang Liu { 393890e4847SJiang Liu return 0; 394890e4847SJiang Liu } 395890e4847SJiang Liu 396890e4847SJiang Liu void __weak pcibios_free_irq(struct pci_dev *dev) 397890e4847SJiang Liu { 398890e4847SJiang Liu } 399890e4847SJiang Liu 4000e7df224SBodong Wang #ifdef CONFIG_PCI_IOV 4010e7df224SBodong Wang static inline bool pci_device_can_probe(struct pci_dev *pdev) 4020e7df224SBodong Wang { 4032d2f4273SAlex Williamson return (!pdev->is_virtfn || pdev->physfn->sriov->drivers_autoprobe || 4042d2f4273SAlex Williamson pdev->driver_override); 4050e7df224SBodong Wang } 4060e7df224SBodong Wang #else 4070e7df224SBodong Wang static inline bool pci_device_can_probe(struct pci_dev *pdev) 4080e7df224SBodong Wang { 4090e7df224SBodong Wang return true; 4100e7df224SBodong Wang } 4110e7df224SBodong Wang #endif 4120e7df224SBodong Wang 4131da177e4SLinus Torvalds static int pci_device_probe(struct device *dev) 4141da177e4SLinus Torvalds { 415890e4847SJiang Liu int error; 416890e4847SJiang Liu struct pci_dev *pci_dev = to_pci_dev(dev); 417890e4847SJiang Liu struct pci_driver *drv = to_pci_driver(dev->driver); 4181da177e4SLinus Torvalds 41976002d8bSAlex Williamson if (!pci_device_can_probe(pci_dev)) 42076002d8bSAlex Williamson return -ENODEV; 42176002d8bSAlex Williamson 42230fdfb92SMatthew Minter pci_assign_irq(pci_dev); 42330fdfb92SMatthew Minter 424890e4847SJiang Liu error = pcibios_alloc_irq(pci_dev); 425890e4847SJiang Liu if (error < 0) 426890e4847SJiang Liu return error; 427890e4847SJiang Liu 4281da177e4SLinus Torvalds pci_dev_get(pci_dev); 4291da177e4SLinus Torvalds error = __pci_device_probe(drv, pci_dev); 430890e4847SJiang Liu if (error) { 431890e4847SJiang Liu pcibios_free_irq(pci_dev); 4321da177e4SLinus Torvalds pci_dev_put(pci_dev); 433890e4847SJiang Liu } 4341da177e4SLinus Torvalds 4351da177e4SLinus Torvalds return error; 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds 4381da177e4SLinus Torvalds static int pci_device_remove(struct device *dev) 4391da177e4SLinus Torvalds { 4401da177e4SLinus Torvalds struct pci_dev *pci_dev = to_pci_dev(dev); 4411da177e4SLinus Torvalds struct pci_driver *drv = pci_dev->driver; 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds if (drv) { 444f3ec4f87SAlan Stern if (drv->remove) { 445f3ec4f87SAlan Stern pm_runtime_get_sync(dev); 4461da177e4SLinus Torvalds drv->remove(pci_dev); 447f3ec4f87SAlan Stern pm_runtime_put_noidle(dev); 448f3ec4f87SAlan Stern } 449890e4847SJiang Liu pcibios_free_irq(pci_dev); 4501da177e4SLinus Torvalds pci_dev->driver = NULL; 45138972375SJakub Kicinski pci_iov_remove(pci_dev); 4521da177e4SLinus Torvalds } 4531da177e4SLinus Torvalds 454f3ec4f87SAlan Stern /* Undo the runtime PM settings in local_pci_probe() */ 455967577b0SHuang Ying pm_runtime_put_sync(dev); 456f3ec4f87SAlan Stern 4571da177e4SLinus Torvalds /* 4582449e06aSShaohua Li * If the device is still on, set the power state as "unknown", 4592449e06aSShaohua Li * since it might change by the next time we load the driver. 4602449e06aSShaohua Li */ 4612449e06aSShaohua Li if (pci_dev->current_state == PCI_D0) 4622449e06aSShaohua Li pci_dev->current_state = PCI_UNKNOWN; 4632449e06aSShaohua Li 4642449e06aSShaohua Li /* 4651da177e4SLinus Torvalds * We would love to complain here if pci_dev->is_enabled is set, that 4661da177e4SLinus Torvalds * the driver should have called pci_disable_device(), but the 4671da177e4SLinus Torvalds * unfortunate fact is there are too many odd BIOS and bridge setups 4681da177e4SLinus Torvalds * that don't like drivers doing that all of the time. 4691da177e4SLinus Torvalds * Oh well, we can dream of sane hardware when we sleep, no matter how 4701da177e4SLinus Torvalds * horrible the crap we have to deal with is when we are awake... 4711da177e4SLinus Torvalds */ 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds pci_dev_put(pci_dev); 4741da177e4SLinus Torvalds return 0; 4751da177e4SLinus Torvalds } 4761da177e4SLinus Torvalds 477bbb44d9fSRafael J. Wysocki static void pci_device_shutdown(struct device *dev) 4781da177e4SLinus Torvalds { 4791da177e4SLinus Torvalds struct pci_dev *pci_dev = to_pci_dev(dev); 4801da177e4SLinus Torvalds struct pci_driver *drv = pci_dev->driver; 4811da177e4SLinus Torvalds 4823ff2de9bSHuang Ying pm_runtime_resume(dev); 4833ff2de9bSHuang Ying 484bbb44d9fSRafael J. Wysocki if (drv && drv->shutdown) 485bbb44d9fSRafael J. Wysocki drv->shutdown(pci_dev); 4865b415f1eSRafael J. Wysocki 4875b415f1eSRafael J. Wysocki /* 4884fc9bbf9SKhalid Aziz * If this is a kexec reboot, turn off Bus Master bit on the 4894fc9bbf9SKhalid Aziz * device to tell it to not continue to do DMA. Don't touch 4904fc9bbf9SKhalid Aziz * devices in D3cold or unknown states. 4914fc9bbf9SKhalid Aziz * If it is not a kexec reboot, firmware will hit the PCI 4924fc9bbf9SKhalid Aziz * devices with big hammer and stop their DMA any way. 493b566a22cSKhalid Aziz */ 4944fc9bbf9SKhalid Aziz if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot)) 4957897e602SKonstantin Khlebnikov pci_clear_master(pci_dev); 496bbb44d9fSRafael J. Wysocki } 497bbb44d9fSRafael J. Wysocki 498aa338601SRafael J. Wysocki #ifdef CONFIG_PM 4996cbf8214SRafael J. Wysocki 5006cbf8214SRafael J. Wysocki /* Auxiliary functions used for system resume and run-time resume. */ 5016cbf8214SRafael J. Wysocki 5026cbf8214SRafael J. Wysocki /** 5036cbf8214SRafael J. Wysocki * pci_restore_standard_config - restore standard config registers of PCI device 5046cbf8214SRafael J. Wysocki * @pci_dev: PCI device to handle 5056cbf8214SRafael J. Wysocki */ 5066cbf8214SRafael J. Wysocki static int pci_restore_standard_config(struct pci_dev *pci_dev) 5076cbf8214SRafael J. Wysocki { 5086cbf8214SRafael J. Wysocki pci_update_current_state(pci_dev, PCI_UNKNOWN); 5096cbf8214SRafael J. Wysocki 5106cbf8214SRafael J. Wysocki if (pci_dev->current_state != PCI_D0) { 5116cbf8214SRafael J. Wysocki int error = pci_set_power_state(pci_dev, PCI_D0); 5126cbf8214SRafael J. Wysocki if (error) 5136cbf8214SRafael J. Wysocki return error; 5146cbf8214SRafael J. Wysocki } 5156cbf8214SRafael J. Wysocki 5161d3c16a8SJon Mason pci_restore_state(pci_dev); 5170ce3fcafSRafael J. Wysocki pci_pme_restore(pci_dev); 5181d3c16a8SJon Mason return 0; 5196cbf8214SRafael J. Wysocki } 5206cbf8214SRafael J. Wysocki 521f7b32a86SBjorn Helgaas static void pci_pm_default_resume(struct pci_dev *pci_dev) 522f7b32a86SBjorn Helgaas { 523f7b32a86SBjorn Helgaas pci_fixup_device(pci_fixup_resume, pci_dev); 524f7b32a86SBjorn Helgaas pci_enable_wake(pci_dev, PCI_D0, false); 525f7b32a86SBjorn Helgaas } 526f7b32a86SBjorn Helgaas 5276cbf8214SRafael J. Wysocki #endif 5286cbf8214SRafael J. Wysocki 529bbb44d9fSRafael J. Wysocki #ifdef CONFIG_PM_SLEEP 530bbb44d9fSRafael J. Wysocki 531db288c9cSRafael J. Wysocki static void pci_pm_default_resume_early(struct pci_dev *pci_dev) 532db288c9cSRafael J. Wysocki { 533db288c9cSRafael J. Wysocki pci_power_up(pci_dev); 534db288c9cSRafael J. Wysocki pci_restore_state(pci_dev); 5350ce3fcafSRafael J. Wysocki pci_pme_restore(pci_dev); 536db288c9cSRafael J. Wysocki } 537db288c9cSRafael J. Wysocki 538bbb44d9fSRafael J. Wysocki /* 539bbb44d9fSRafael J. Wysocki * Default "suspend" method for devices that have no driver provided suspend, 540fa58d305SRafael J. Wysocki * or not even a driver at all (second part). 541fa58d305SRafael J. Wysocki */ 542bb808945SRafael J. Wysocki static void pci_pm_set_unknown_state(struct pci_dev *pci_dev) 543bbb44d9fSRafael J. Wysocki { 5442449e06aSShaohua Li /* 5452449e06aSShaohua Li * mark its power state as "unknown", since we don't know if 5462449e06aSShaohua Li * e.g. the BIOS will change its device state when we suspend. 5472449e06aSShaohua Li */ 5482449e06aSShaohua Li if (pci_dev->current_state == PCI_D0) 5492449e06aSShaohua Li pci_dev->current_state = PCI_UNKNOWN; 55002669492SAndrew Morton } 551e1a2a51eSRafael J. Wysocki 552bbb44d9fSRafael J. Wysocki /* 553bbb44d9fSRafael J. Wysocki * Default "resume" method for devices that have no driver provided resume, 554355a72d7SRafael J. Wysocki * or not even a driver at all (second part). 555355a72d7SRafael J. Wysocki */ 556bb808945SRafael J. Wysocki static int pci_pm_reenable_device(struct pci_dev *pci_dev) 557355a72d7SRafael J. Wysocki { 558355a72d7SRafael J. Wysocki int retval; 559355a72d7SRafael J. Wysocki 560bbb44d9fSRafael J. Wysocki /* if the device was enabled before suspend, reenable */ 561bbb44d9fSRafael J. Wysocki retval = pci_reenable_device(pci_dev); 562bbb44d9fSRafael J. Wysocki /* 563bbb44d9fSRafael J. Wysocki * if the device was busmaster before the suspend, make it busmaster 564bbb44d9fSRafael J. Wysocki * again 565bbb44d9fSRafael J. Wysocki */ 566bbb44d9fSRafael J. Wysocki if (pci_dev->is_busmaster) 567bbb44d9fSRafael J. Wysocki pci_set_master(pci_dev); 568bbb44d9fSRafael J. Wysocki 569bbb44d9fSRafael J. Wysocki return retval; 570bbb44d9fSRafael J. Wysocki } 571bbb44d9fSRafael J. Wysocki 572bbb44d9fSRafael J. Wysocki static int pci_legacy_suspend(struct device *dev, pm_message_t state) 5731da177e4SLinus Torvalds { 5741da177e4SLinus Torvalds struct pci_dev *pci_dev = to_pci_dev(dev); 5751da177e4SLinus Torvalds struct pci_driver *drv = pci_dev->driver; 57646939f8bSRafael J. Wysocki 5771da177e4SLinus Torvalds if (drv && drv->suspend) { 57899dadce8SRafael J. Wysocki pci_power_t prev = pci_dev->current_state; 57946939f8bSRafael J. Wysocki int error; 580aa8c6c93SRafael J. Wysocki 58157ef8026SFrans Pop error = drv->suspend(pci_dev, state); 58257ef8026SFrans Pop suspend_report_result(drv->suspend, error); 58357ef8026SFrans Pop if (error) 58457ef8026SFrans Pop return error; 585aa8c6c93SRafael J. Wysocki 58646939f8bSRafael J. Wysocki if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 58799dadce8SRafael J. Wysocki && pci_dev->current_state != PCI_UNKNOWN) { 58812bcae44SBjorn Helgaas pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 589d75f773cSSakari Ailus "PCI PM: Device state not saved by %pS\n", 59099dadce8SRafael J. Wysocki drv->suspend); 5911da177e4SLinus Torvalds } 59299dadce8SRafael J. Wysocki } 593ad8cfa1dSRafael J. Wysocki 594ad8cfa1dSRafael J. Wysocki pci_fixup_device(pci_fixup_suspend, pci_dev); 595ad8cfa1dSRafael J. Wysocki 59646939f8bSRafael J. Wysocki return 0; 5971da177e4SLinus Torvalds } 5981da177e4SLinus Torvalds 599bbb44d9fSRafael J. Wysocki static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) 600cbd69dbbSLinus Torvalds { 601cbd69dbbSLinus Torvalds struct pci_dev *pci_dev = to_pci_dev(dev); 602cbd69dbbSLinus Torvalds struct pci_driver *drv = pci_dev->driver; 603cbd69dbbSLinus Torvalds 604cbd69dbbSLinus Torvalds if (drv && drv->suspend_late) { 60546939f8bSRafael J. Wysocki pci_power_t prev = pci_dev->current_state; 60646939f8bSRafael J. Wysocki int error; 60746939f8bSRafael J. Wysocki 60857ef8026SFrans Pop error = drv->suspend_late(pci_dev, state); 60957ef8026SFrans Pop suspend_report_result(drv->suspend_late, error); 61046939f8bSRafael J. Wysocki if (error) 61157ef8026SFrans Pop return error; 61246939f8bSRafael J. Wysocki 61346939f8bSRafael J. Wysocki if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 61446939f8bSRafael J. Wysocki && pci_dev->current_state != PCI_UNKNOWN) { 61512bcae44SBjorn Helgaas pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 616d75f773cSSakari Ailus "PCI PM: Device state not saved by %pS\n", 61746939f8bSRafael J. Wysocki drv->suspend_late); 6187d2a01b8SAndreas Noever goto Fixup; 61946939f8bSRafael J. Wysocki } 62046939f8bSRafael J. Wysocki } 62146939f8bSRafael J. Wysocki 62246939f8bSRafael J. Wysocki if (!pci_dev->state_saved) 62346939f8bSRafael J. Wysocki pci_save_state(pci_dev); 62446939f8bSRafael J. Wysocki 62546939f8bSRafael J. Wysocki pci_pm_set_unknown_state(pci_dev); 62646939f8bSRafael J. Wysocki 6277d2a01b8SAndreas Noever Fixup: 6287d2a01b8SAndreas Noever pci_fixup_device(pci_fixup_suspend_late, pci_dev); 6297d2a01b8SAndreas Noever 63046939f8bSRafael J. Wysocki return 0; 631cbd69dbbSLinus Torvalds } 6321da177e4SLinus Torvalds 633bbb44d9fSRafael J. Wysocki static int pci_legacy_resume(struct device *dev) 6341da177e4SLinus Torvalds { 6351da177e4SLinus Torvalds struct pci_dev *pci_dev = to_pci_dev(dev); 6361da177e4SLinus Torvalds struct pci_driver *drv = pci_dev->driver; 6371da177e4SLinus Torvalds 638ad8cfa1dSRafael J. Wysocki pci_fixup_device(pci_fixup_resume, pci_dev); 639ad8cfa1dSRafael J. Wysocki 640aa8c6c93SRafael J. Wysocki return drv && drv->resume ? 641aa8c6c93SRafael J. Wysocki drv->resume(pci_dev) : pci_pm_reenable_device(pci_dev); 6421da177e4SLinus Torvalds } 6431da177e4SLinus Torvalds 644571ff758SRafael J. Wysocki /* Auxiliary functions used by the new power management framework */ 645571ff758SRafael J. Wysocki 6465294e256SRafael J. Wysocki static void pci_pm_default_suspend(struct pci_dev *pci_dev) 64773410429SRafael J. Wysocki { 6485294e256SRafael J. Wysocki /* Disable non-bridge devices without PM support */ 649326c1cdaSYijing Wang if (!pci_has_subordinate(pci_dev)) 65073410429SRafael J. Wysocki pci_disable_enabled_device(pci_dev); 65173410429SRafael J. Wysocki } 65273410429SRafael J. Wysocki 65307e836e8SRafael J. Wysocki static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) 65407e836e8SRafael J. Wysocki { 65507e836e8SRafael J. Wysocki struct pci_driver *drv = pci_dev->driver; 656*89cdbc35SBjorn Helgaas bool ret = drv && (drv->suspend || drv->suspend_late || drv->resume); 657bb808945SRafael J. Wysocki 658bb808945SRafael J. Wysocki /* 659bb808945SRafael J. Wysocki * Legacy PM support is used by default, so warn if the new framework is 660bb808945SRafael J. Wysocki * supported as well. Drivers are supposed to support either the 661bb808945SRafael J. Wysocki * former, or the latter, but not both at the same time. 662bb808945SRafael J. Wysocki */ 66312bcae44SBjorn Helgaas pci_WARN(pci_dev, ret && drv->driver.pm, "device %04x:%04x\n", 66412bcae44SBjorn Helgaas pci_dev->vendor, pci_dev->device); 665bb808945SRafael J. Wysocki 666bb808945SRafael J. Wysocki return ret; 66707e836e8SRafael J. Wysocki } 66807e836e8SRafael J. Wysocki 669571ff758SRafael J. Wysocki /* New power management framework */ 670571ff758SRafael J. Wysocki 671bbb44d9fSRafael J. Wysocki static int pci_pm_prepare(struct device *dev) 672bbb44d9fSRafael J. Wysocki { 6730c7376adSRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 6746da2f2ccSBjorn Helgaas const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 675bbb44d9fSRafael J. Wysocki 6766da2f2ccSBjorn Helgaas if (pm && pm->prepare) { 6776da2f2ccSBjorn Helgaas int error = pm->prepare(dev); 67808810a41SRafael J. Wysocki if (error < 0) 679bbb44d9fSRafael J. Wysocki return error; 68008810a41SRafael J. Wysocki 68108810a41SRafael J. Wysocki if (!error && dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_PREPARE)) 68208810a41SRafael J. Wysocki return 0; 683bbb44d9fSRafael J. Wysocki } 6840c7376adSRafael J. Wysocki if (pci_dev_need_resume(pci_dev)) 6850c7376adSRafael J. Wysocki return 0; 6860c7376adSRafael J. Wysocki 6870c7376adSRafael J. Wysocki /* 6880c7376adSRafael J. Wysocki * The PME setting needs to be adjusted here in case the direct-complete 6890c7376adSRafael J. Wysocki * optimization is used with respect to this device. 6900c7376adSRafael J. Wysocki */ 6910c7376adSRafael J. Wysocki pci_dev_adjust_pme(pci_dev); 6920c7376adSRafael J. Wysocki return 1; 693bac2a909SRafael J. Wysocki } 694bbb44d9fSRafael J. Wysocki 6952cef548aSRafael J. Wysocki static void pci_pm_complete(struct device *dev) 6962cef548aSRafael J. Wysocki { 697a0d2a959SLukas Wunner struct pci_dev *pci_dev = to_pci_dev(dev); 698a0d2a959SLukas Wunner 699a0d2a959SLukas Wunner pci_dev_complete_resume(pci_dev); 700a0d2a959SLukas Wunner pm_generic_complete(dev); 701a0d2a959SLukas Wunner 702a0d2a959SLukas Wunner /* Resume device if platform firmware has put it in reset-power-on */ 703bd755d77SRafael J. Wysocki if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) { 704a0d2a959SLukas Wunner pci_power_t pre_sleep_state = pci_dev->current_state; 705a0d2a959SLukas Wunner 706b51033e0SRafael J. Wysocki pci_refresh_power_state(pci_dev); 707b51033e0SRafael J. Wysocki /* 708b51033e0SRafael J. Wysocki * On platforms with ACPI this check may also trigger for 709b51033e0SRafael J. Wysocki * devices sharing power resources if one of those power 710b51033e0SRafael J. Wysocki * resources has been activated as a result of a change of the 711b51033e0SRafael J. Wysocki * power state of another device sharing it. However, in that 712b51033e0SRafael J. Wysocki * case it is also better to resume the device, in general. 713b51033e0SRafael J. Wysocki */ 714a0d2a959SLukas Wunner if (pci_dev->current_state < pre_sleep_state) 715a0d2a959SLukas Wunner pm_request_resume(dev); 716a0d2a959SLukas Wunner } 7172cef548aSRafael J. Wysocki } 718bbb44d9fSRafael J. Wysocki 7196cbf8214SRafael J. Wysocki #else /* !CONFIG_PM_SLEEP */ 7206cbf8214SRafael J. Wysocki 7216cbf8214SRafael J. Wysocki #define pci_pm_prepare NULL 7222cef548aSRafael J. Wysocki #define pci_pm_complete NULL 7236cbf8214SRafael J. Wysocki 7246cbf8214SRafael J. Wysocki #endif /* !CONFIG_PM_SLEEP */ 7256cbf8214SRafael J. Wysocki 726bbb44d9fSRafael J. Wysocki #ifdef CONFIG_SUSPEND 727a39bd851SBjorn Helgaas static void pcie_pme_root_status_cleanup(struct pci_dev *pci_dev) 728a39bd851SBjorn Helgaas { 729a39bd851SBjorn Helgaas /* 730a39bd851SBjorn Helgaas * Some BIOSes forget to clear Root PME Status bits after system 731a39bd851SBjorn Helgaas * wakeup, which breaks ACPI-based runtime wakeup on PCI Express. 732a39bd851SBjorn Helgaas * Clear those bits now just in case (shouldn't hurt). 733a39bd851SBjorn Helgaas */ 734a39bd851SBjorn Helgaas if (pci_is_pcie(pci_dev) && 7353620c714SBjorn Helgaas (pci_pcie_type(pci_dev) == PCI_EXP_TYPE_ROOT_PORT || 7363620c714SBjorn Helgaas pci_pcie_type(pci_dev) == PCI_EXP_TYPE_RC_EC)) 737a39bd851SBjorn Helgaas pcie_clear_root_pme_status(pci_dev); 738a39bd851SBjorn Helgaas } 739bbb44d9fSRafael J. Wysocki 740bbb44d9fSRafael J. Wysocki static int pci_pm_suspend(struct device *dev) 741bbb44d9fSRafael J. Wysocki { 742bbb44d9fSRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 7438150f32bSDmitry Torokhov const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 744bbb44d9fSRafael J. Wysocki 745d491f2b7SRafael J. Wysocki pci_dev->skip_bus_pm = false; 746d491f2b7SRafael J. Wysocki 747ad8cfa1dSRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 748ad8cfa1dSRafael J. Wysocki return pci_legacy_suspend(dev, PMSG_SUSPEND); 749bb808945SRafael J. Wysocki 7505294e256SRafael J. Wysocki if (!pm) { 7515294e256SRafael J. Wysocki pci_pm_default_suspend(pci_dev); 752c4b65157SRafael J. Wysocki return 0; 753bbb44d9fSRafael J. Wysocki } 754fa58d305SRafael J. Wysocki 7557cd0602dSRafael J. Wysocki /* 756c4b65157SRafael J. Wysocki * PCI devices suspended at run time may need to be resumed at this 757c4b65157SRafael J. Wysocki * point, because in general it may be necessary to reconfigure them for 758c4b65157SRafael J. Wysocki * system suspend. Namely, if the device is expected to wake up the 759c4b65157SRafael J. Wysocki * system from the sleep state, it may have to be reconfigured for this 760c4b65157SRafael J. Wysocki * purpose, or if the device is not expected to wake up the system from 761c4b65157SRafael J. Wysocki * the sleep state, it should be prevented from signaling wakeup events 762c4b65157SRafael J. Wysocki * going forward. 763c4b65157SRafael J. Wysocki * 764c4b65157SRafael J. Wysocki * Also if the driver of the device does not indicate that its system 765c4b65157SRafael J. Wysocki * suspend callbacks can cope with runtime-suspended devices, it is 766c4b65157SRafael J. Wysocki * better to resume the device from runtime suspend here. 7677cd0602dSRafael J. Wysocki */ 768c4b65157SRafael J. Wysocki if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || 7690c7376adSRafael J. Wysocki pci_dev_need_resume(pci_dev)) { 7707cd0602dSRafael J. Wysocki pm_runtime_resume(dev); 77182fee4d6SRafael J. Wysocki pci_dev->state_saved = false; 7720c7376adSRafael J. Wysocki } else { 7730c7376adSRafael J. Wysocki pci_dev_adjust_pme(pci_dev); 774656088aaSRafael J. Wysocki } 775656088aaSRafael J. Wysocki 7765294e256SRafael J. Wysocki if (pm->suspend) { 7775294e256SRafael J. Wysocki pci_power_t prev = pci_dev->current_state; 7785294e256SRafael J. Wysocki int error; 7795294e256SRafael J. Wysocki 7805294e256SRafael J. Wysocki error = pm->suspend(dev); 7815294e256SRafael J. Wysocki suspend_report_result(pm->suspend, error); 7825294e256SRafael J. Wysocki if (error) 783bbb44d9fSRafael J. Wysocki return error; 7845294e256SRafael J. Wysocki 78546939f8bSRafael J. Wysocki if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 7865294e256SRafael J. Wysocki && pci_dev->current_state != PCI_UNKNOWN) { 78712bcae44SBjorn Helgaas pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 788d75f773cSSakari Ailus "PCI PM: State of device not saved by %pS\n", 7895294e256SRafael J. Wysocki pm->suspend); 7905294e256SRafael J. Wysocki } 7915294e256SRafael J. Wysocki } 7925294e256SRafael J. Wysocki 7935294e256SRafael J. Wysocki return 0; 794bbb44d9fSRafael J. Wysocki } 795bbb44d9fSRafael J. Wysocki 796c4b65157SRafael J. Wysocki static int pci_pm_suspend_late(struct device *dev) 797c4b65157SRafael J. Wysocki { 798c4b65157SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) 799c4b65157SRafael J. Wysocki return 0; 800c4b65157SRafael J. Wysocki 801c4b65157SRafael J. Wysocki pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev)); 802c4b65157SRafael J. Wysocki 803c4b65157SRafael J. Wysocki return pm_generic_suspend_late(dev); 804c4b65157SRafael J. Wysocki } 805c4b65157SRafael J. Wysocki 806bbb44d9fSRafael J. Wysocki static int pci_pm_suspend_noirq(struct device *dev) 807c8958177SGreg KH { 808355a72d7SRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 8098150f32bSDmitry Torokhov const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 810c8958177SGreg KH 811bd755d77SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) { 812bd755d77SRafael J. Wysocki dev->power.may_skip_resume = true; 813c4b65157SRafael J. Wysocki return 0; 814bd755d77SRafael J. Wysocki } 815c4b65157SRafael J. Wysocki 816bb808945SRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 817bb808945SRafael J. Wysocki return pci_legacy_suspend_late(dev, PMSG_SUSPEND); 818bb808945SRafael J. Wysocki 819931ff68aSRafael J. Wysocki if (!pm) { 820931ff68aSRafael J. Wysocki pci_save_state(pci_dev); 8217d2a01b8SAndreas Noever goto Fixup; 822931ff68aSRafael J. Wysocki } 82346939f8bSRafael J. Wysocki 82446939f8bSRafael J. Wysocki if (pm->suspend_noirq) { 82546939f8bSRafael J. Wysocki pci_power_t prev = pci_dev->current_state; 82646939f8bSRafael J. Wysocki int error; 82746939f8bSRafael J. Wysocki 82846939f8bSRafael J. Wysocki error = pm->suspend_noirq(dev); 82946939f8bSRafael J. Wysocki suspend_report_result(pm->suspend_noirq, error); 83046939f8bSRafael J. Wysocki if (error) 83146939f8bSRafael J. Wysocki return error; 83246939f8bSRafael J. Wysocki 83346939f8bSRafael J. Wysocki if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 83446939f8bSRafael J. Wysocki && pci_dev->current_state != PCI_UNKNOWN) { 83512bcae44SBjorn Helgaas pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 836d75f773cSSakari Ailus "PCI PM: State of device not saved by %pS\n", 83746939f8bSRafael J. Wysocki pm->suspend_noirq); 8387d2a01b8SAndreas Noever goto Fixup; 83946939f8bSRafael J. Wysocki } 840c8958177SGreg KH } 841d67e37d7SRafael J. Wysocki 842d491f2b7SRafael J. Wysocki if (pci_dev->skip_bus_pm) { 843d491f2b7SRafael J. Wysocki /* 8443e26c5feSRafael J. Wysocki * Either the device is a bridge with a child in D0 below it, or 8453e26c5feSRafael J. Wysocki * the function is running for the second time in a row without 846d491f2b7SRafael J. Wysocki * going through full resume, which is possible only during 8473e26c5feSRafael J. Wysocki * suspend-to-idle in a spurious wakeup case. The device should 8483e26c5feSRafael J. Wysocki * be in D0 at this point, but if it is a bridge, it may be 8493e26c5feSRafael J. Wysocki * necessary to save its state. 850d491f2b7SRafael J. Wysocki */ 8513e26c5feSRafael J. Wysocki if (!pci_dev->state_saved) 8523e26c5feSRafael J. Wysocki pci_save_state(pci_dev); 8533e26c5feSRafael J. Wysocki } else if (!pci_dev->state_saved) { 85446939f8bSRafael J. Wysocki pci_save_state(pci_dev); 8559d26d3a8SMika Westerberg if (pci_power_manageable(pci_dev)) 85646939f8bSRafael J. Wysocki pci_prepare_to_sleep(pci_dev); 85746939f8bSRafael J. Wysocki } 85846939f8bSRafael J. Wysocki 8596941a0c2SBjorn Helgaas pci_dbg(pci_dev, "PCI PM: Suspend power state: %s\n", 860ca67ab5cSRafael J. Wysocki pci_power_name(pci_dev->current_state)); 861ca67ab5cSRafael J. Wysocki 8623e26c5feSRafael J. Wysocki if (pci_dev->current_state == PCI_D0) { 8633e26c5feSRafael J. Wysocki pci_dev->skip_bus_pm = true; 8643e26c5feSRafael J. Wysocki /* 8653e26c5feSRafael J. Wysocki * Per PCI PM r1.2, table 6-1, a bridge must be in D0 if any 8663e26c5feSRafael J. Wysocki * downstream device is in D0, so avoid changing the power state 8673e26c5feSRafael J. Wysocki * of the parent bridge by setting the skip_bus_pm flag for it. 8683e26c5feSRafael J. Wysocki */ 8693e26c5feSRafael J. Wysocki if (pci_dev->bus->self) 8703e26c5feSRafael J. Wysocki pci_dev->bus->self->skip_bus_pm = true; 8713e26c5feSRafael J. Wysocki } 8723e26c5feSRafael J. Wysocki 873471a739aSRafael J. Wysocki if (pci_dev->skip_bus_pm && pm_suspend_no_platform()) { 8746941a0c2SBjorn Helgaas pci_dbg(pci_dev, "PCI PM: Skipped\n"); 8753e26c5feSRafael J. Wysocki goto Fixup; 8763e26c5feSRafael J. Wysocki } 8773e26c5feSRafael J. Wysocki 878bb808945SRafael J. Wysocki pci_pm_set_unknown_state(pci_dev); 879bbb44d9fSRafael J. Wysocki 880dbf0e4c7SAlan Stern /* 881dbf0e4c7SAlan Stern * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's 882dbf0e4c7SAlan Stern * PCI COMMAND register isn't 0, the BIOS assumes that the controller 883dbf0e4c7SAlan Stern * hasn't been quiesced and tries to turn it off. If the controller 884dbf0e4c7SAlan Stern * is already in D3, this can hang or cause memory corruption. 885dbf0e4c7SAlan Stern * 886dbf0e4c7SAlan Stern * Since the value of the COMMAND register doesn't matter once the 887dbf0e4c7SAlan Stern * device has been suspended, we can safely set it to 0 here. 888dbf0e4c7SAlan Stern */ 889dbf0e4c7SAlan Stern if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) 890dbf0e4c7SAlan Stern pci_write_config_word(pci_dev, PCI_COMMAND, 0); 891dbf0e4c7SAlan Stern 8927d2a01b8SAndreas Noever Fixup: 8937d2a01b8SAndreas Noever pci_fixup_device(pci_fixup_suspend_late, pci_dev); 8947d2a01b8SAndreas Noever 895bd755d77SRafael J. Wysocki /* 896bd755d77SRafael J. Wysocki * If the target system sleep state is suspend-to-idle, it is sufficient 897bd755d77SRafael J. Wysocki * to check whether or not the device's wakeup settings are good for 898bd755d77SRafael J. Wysocki * runtime PM. Otherwise, the pm_resume_via_firmware() check will cause 899bd755d77SRafael J. Wysocki * pci_pm_complete() to take care of fixing up the device's state 900bd755d77SRafael J. Wysocki * anyway, if need be. 901bd755d77SRafael J. Wysocki */ 902bd755d77SRafael J. Wysocki dev->power.may_skip_resume = device_may_wakeup(dev) || 903bd755d77SRafael J. Wysocki !device_can_wakeup(dev); 904bd755d77SRafael J. Wysocki 90546939f8bSRafael J. Wysocki return 0; 906bbb44d9fSRafael J. Wysocki } 907bbb44d9fSRafael J. Wysocki 908bbb44d9fSRafael J. Wysocki static int pci_pm_resume_noirq(struct device *dev) 909bbb44d9fSRafael J. Wysocki { 910355a72d7SRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 9116da2f2ccSBjorn Helgaas const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 912bbb44d9fSRafael J. Wysocki 913bd755d77SRafael J. Wysocki if (dev_pm_may_skip_resume(dev)) 914bd755d77SRafael J. Wysocki return 0; 915bd755d77SRafael J. Wysocki 916c4b65157SRafael J. Wysocki /* 917c4b65157SRafael J. Wysocki * Devices with DPM_FLAG_SMART_SUSPEND may be left in runtime suspend 918c4b65157SRafael J. Wysocki * during system suspend, so update their runtime PM status to "active" 919c4b65157SRafael J. Wysocki * as they are going to be put into D0 shortly. 920c4b65157SRafael J. Wysocki */ 921c4b65157SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) 922c4b65157SRafael J. Wysocki pm_runtime_set_active(dev); 923c4b65157SRafael J. Wysocki 9243e26c5feSRafael J. Wysocki /* 9253e26c5feSRafael J. Wysocki * In the suspend-to-idle case, devices left in D0 during suspend will 9263e26c5feSRafael J. Wysocki * stay in D0, so it is not necessary to restore or update their 927471a739aSRafael J. Wysocki * configuration here and attempting to put them into D0 again is 928471a739aSRafael J. Wysocki * pointless, so avoid doing that. 9293e26c5feSRafael J. Wysocki */ 930471a739aSRafael J. Wysocki if (!(pci_dev->skip_bus_pm && pm_suspend_no_platform())) 9316cbf8214SRafael J. Wysocki pci_pm_default_resume_early(pci_dev); 932aa8c6c93SRafael J. Wysocki 9333e26c5feSRafael J. Wysocki pci_fixup_device(pci_fixup_resume_early, pci_dev); 934ec6a75efSBjorn Helgaas pcie_pme_root_status_cleanup(pci_dev); 9353e26c5feSRafael J. Wysocki 936ad8cfa1dSRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 937*89cdbc35SBjorn Helgaas return 0; 938bb808945SRafael J. Wysocki 9396da2f2ccSBjorn Helgaas if (pm && pm->resume_noirq) 9406da2f2ccSBjorn Helgaas return pm->resume_noirq(dev); 941bbb44d9fSRafael J. Wysocki 9426da2f2ccSBjorn Helgaas return 0; 943bbb44d9fSRafael J. Wysocki } 944bbb44d9fSRafael J. Wysocki 945f6dc1e5eSRafael J. Wysocki static int pci_pm_resume(struct device *dev) 946f6dc1e5eSRafael J. Wysocki { 947f6dc1e5eSRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 9488150f32bSDmitry Torokhov const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 949f6dc1e5eSRafael J. Wysocki 950418e4da3SRafael J. Wysocki /* 951418e4da3SRafael J. Wysocki * This is necessary for the suspend error path in which resume is 952418e4da3SRafael J. Wysocki * called without restoring the standard config registers of the device. 953418e4da3SRafael J. Wysocki */ 954418e4da3SRafael J. Wysocki if (pci_dev->state_saved) 955418e4da3SRafael J. Wysocki pci_restore_standard_config(pci_dev); 956418e4da3SRafael J. Wysocki 957f6dc1e5eSRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 958f6dc1e5eSRafael J. Wysocki return pci_legacy_resume(dev); 959f6dc1e5eSRafael J. Wysocki 9605294e256SRafael J. Wysocki pci_pm_default_resume(pci_dev); 961f6dc1e5eSRafael J. Wysocki 9625294e256SRafael J. Wysocki if (pm) { 9635294e256SRafael J. Wysocki if (pm->resume) 9646da2f2ccSBjorn Helgaas return pm->resume(dev); 9655294e256SRafael J. Wysocki } else { 9665294e256SRafael J. Wysocki pci_pm_reenable_device(pci_dev); 9675294e256SRafael J. Wysocki } 968f6dc1e5eSRafael J. Wysocki 9696da2f2ccSBjorn Helgaas return 0; 970f6dc1e5eSRafael J. Wysocki } 971f6dc1e5eSRafael J. Wysocki 972bbb44d9fSRafael J. Wysocki #else /* !CONFIG_SUSPEND */ 973bbb44d9fSRafael J. Wysocki 974bbb44d9fSRafael J. Wysocki #define pci_pm_suspend NULL 975c4b65157SRafael J. Wysocki #define pci_pm_suspend_late NULL 976bbb44d9fSRafael J. Wysocki #define pci_pm_suspend_noirq NULL 977bbb44d9fSRafael J. Wysocki #define pci_pm_resume NULL 978bbb44d9fSRafael J. Wysocki #define pci_pm_resume_noirq NULL 979bbb44d9fSRafael J. Wysocki 980bbb44d9fSRafael J. Wysocki #endif /* !CONFIG_SUSPEND */ 981bbb44d9fSRafael J. Wysocki 9821f112ceeSRafael J. Wysocki #ifdef CONFIG_HIBERNATE_CALLBACKS 983bbb44d9fSRafael J. Wysocki 984699c1985SSebastian Ott /* 985699c1985SSebastian Ott * pcibios_pm_ops - provide arch-specific hooks when a PCI device is doing 986699c1985SSebastian Ott * a hibernate transition 987699c1985SSebastian Ott */ 988699c1985SSebastian Ott struct dev_pm_ops __weak pcibios_pm_ops; 989699c1985SSebastian Ott 990bbb44d9fSRafael J. Wysocki static int pci_pm_freeze(struct device *dev) 991bbb44d9fSRafael J. Wysocki { 992bbb44d9fSRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 9938150f32bSDmitry Torokhov const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 994bbb44d9fSRafael J. Wysocki 995ad8cfa1dSRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 996ad8cfa1dSRafael J. Wysocki return pci_legacy_suspend(dev, PMSG_FREEZE); 997bb808945SRafael J. Wysocki 9985294e256SRafael J. Wysocki if (!pm) { 9995294e256SRafael J. Wysocki pci_pm_default_suspend(pci_dev); 10005294e256SRafael J. Wysocki return 0; 1001bbb44d9fSRafael J. Wysocki } 1002d67e37d7SRafael J. Wysocki 10037cd0602dSRafael J. Wysocki /* 1004501debd4SRafael J. Wysocki * Resume all runtime-suspended devices before creating a snapshot 1005501debd4SRafael J. Wysocki * image of system memory, because the restore kernel generally cannot 1006501debd4SRafael J. Wysocki * be expected to always handle them consistently and they need to be 1007501debd4SRafael J. Wysocki * put into the runtime-active metastate during system resume anyway, 1008501debd4SRafael J. Wysocki * so it is better to ensure that the state saved in the image will be 1009501debd4SRafael J. Wysocki * always consistent with that. 10107cd0602dSRafael J. Wysocki */ 10117cd0602dSRafael J. Wysocki pm_runtime_resume(dev); 101282fee4d6SRafael J. Wysocki pci_dev->state_saved = false; 1013ae860a19SMika Westerberg 10145294e256SRafael J. Wysocki if (pm->freeze) { 10155294e256SRafael J. Wysocki int error; 10165294e256SRafael J. Wysocki 10175294e256SRafael J. Wysocki error = pm->freeze(dev); 10185294e256SRafael J. Wysocki suspend_report_result(pm->freeze, error); 10195294e256SRafael J. Wysocki if (error) 1020bbb44d9fSRafael J. Wysocki return error; 1021bbb44d9fSRafael J. Wysocki } 1022bbb44d9fSRafael J. Wysocki 10235294e256SRafael J. Wysocki return 0; 10245294e256SRafael J. Wysocki } 10255294e256SRafael J. Wysocki 1026bbb44d9fSRafael J. Wysocki static int pci_pm_freeze_noirq(struct device *dev) 1027bbb44d9fSRafael J. Wysocki { 1028355a72d7SRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 10296da2f2ccSBjorn Helgaas const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 1030bbb44d9fSRafael J. Wysocki 1031bb808945SRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 1032bb808945SRafael J. Wysocki return pci_legacy_suspend_late(dev, PMSG_FREEZE); 1033bb808945SRafael J. Wysocki 10346da2f2ccSBjorn Helgaas if (pm && pm->freeze_noirq) { 103546939f8bSRafael J. Wysocki int error; 103646939f8bSRafael J. Wysocki 10376da2f2ccSBjorn Helgaas error = pm->freeze_noirq(dev); 10386da2f2ccSBjorn Helgaas suspend_report_result(pm->freeze_noirq, error); 103946939f8bSRafael J. Wysocki if (error) 104046939f8bSRafael J. Wysocki return error; 1041bbb44d9fSRafael J. Wysocki } 1042d67e37d7SRafael J. Wysocki 104346939f8bSRafael J. Wysocki if (!pci_dev->state_saved) 104446939f8bSRafael J. Wysocki pci_save_state(pci_dev); 104546939f8bSRafael J. Wysocki 1046bb808945SRafael J. Wysocki pci_pm_set_unknown_state(pci_dev); 1047bbb44d9fSRafael J. Wysocki 1048699c1985SSebastian Ott if (pcibios_pm_ops.freeze_noirq) 1049699c1985SSebastian Ott return pcibios_pm_ops.freeze_noirq(dev); 1050699c1985SSebastian Ott 105146939f8bSRafael J. Wysocki return 0; 1052bbb44d9fSRafael J. Wysocki } 1053bbb44d9fSRafael J. Wysocki 1054bbb44d9fSRafael J. Wysocki static int pci_pm_thaw_noirq(struct device *dev) 1055bbb44d9fSRafael J. Wysocki { 1056355a72d7SRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 10576da2f2ccSBjorn Helgaas const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 10586da2f2ccSBjorn Helgaas int error; 1059bbb44d9fSRafael J. Wysocki 1060699c1985SSebastian Ott if (pcibios_pm_ops.thaw_noirq) { 1061699c1985SSebastian Ott error = pcibios_pm_ops.thaw_noirq(dev); 1062699c1985SSebastian Ott if (error) 1063699c1985SSebastian Ott return error; 1064699c1985SSebastian Ott } 1065699c1985SSebastian Ott 10665839ee73SRafael J. Wysocki /* 1067*89cdbc35SBjorn Helgaas * The pm->thaw_noirq() callback assumes the device has been 1068*89cdbc35SBjorn Helgaas * returned to D0 and its config state has been restored. 1069f2c33ccaSDexuan Cui * 1070f2c33ccaSDexuan Cui * In addition, pci_restore_state() restores MSI-X state in MMIO 1071f2c33ccaSDexuan Cui * space, which requires the device to be in D0, so return it to D0 1072f2c33ccaSDexuan Cui * in case the driver's "freeze" callbacks put it into a low-power 1073f2c33ccaSDexuan Cui * state. 10745839ee73SRafael J. Wysocki */ 10755839ee73SRafael J. Wysocki pci_set_power_state(pci_dev, PCI_D0); 1076e60514bdSChen Yu pci_restore_state(pci_dev); 1077d67e37d7SRafael J. Wysocki 1078f2c33ccaSDexuan Cui if (pci_has_legacy_pm_support(pci_dev)) 1079*89cdbc35SBjorn Helgaas return 0; 1080f2c33ccaSDexuan Cui 10816da2f2ccSBjorn Helgaas if (pm && pm->thaw_noirq) 10826da2f2ccSBjorn Helgaas return pm->thaw_noirq(dev); 1083bbb44d9fSRafael J. Wysocki 10846da2f2ccSBjorn Helgaas return 0; 1085bbb44d9fSRafael J. Wysocki } 1086bbb44d9fSRafael J. Wysocki 1087f6dc1e5eSRafael J. Wysocki static int pci_pm_thaw(struct device *dev) 1088f6dc1e5eSRafael J. Wysocki { 1089f6dc1e5eSRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 10908150f32bSDmitry Torokhov const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 1091f6dc1e5eSRafael J. Wysocki int error = 0; 1092f6dc1e5eSRafael J. Wysocki 1093f6dc1e5eSRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 1094f6dc1e5eSRafael J. Wysocki return pci_legacy_resume(dev); 1095f6dc1e5eSRafael J. Wysocki 10965294e256SRafael J. Wysocki if (pm) { 10975294e256SRafael J. Wysocki if (pm->thaw) 10985294e256SRafael J. Wysocki error = pm->thaw(dev); 10995294e256SRafael J. Wysocki } else { 1100f6dc1e5eSRafael J. Wysocki pci_pm_reenable_device(pci_dev); 11015294e256SRafael J. Wysocki } 1102f6dc1e5eSRafael J. Wysocki 11034b77b0a2SRafael J. Wysocki pci_dev->state_saved = false; 11044b77b0a2SRafael J. Wysocki 1105f6dc1e5eSRafael J. Wysocki return error; 1106f6dc1e5eSRafael J. Wysocki } 1107f6dc1e5eSRafael J. Wysocki 1108bbb44d9fSRafael J. Wysocki static int pci_pm_poweroff(struct device *dev) 1109bbb44d9fSRafael J. Wysocki { 1110355a72d7SRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 11118150f32bSDmitry Torokhov const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 1112bbb44d9fSRafael J. Wysocki 1113ad8cfa1dSRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 1114ad8cfa1dSRafael J. Wysocki return pci_legacy_suspend(dev, PMSG_HIBERNATE); 1115bb808945SRafael J. Wysocki 11165294e256SRafael J. Wysocki if (!pm) { 11175294e256SRafael J. Wysocki pci_pm_default_suspend(pci_dev); 1118c4b65157SRafael J. Wysocki return 0; 11195294e256SRafael J. Wysocki } 11205294e256SRafael J. Wysocki 11217cd0602dSRafael J. Wysocki /* The reason to do that is the same as in pci_pm_suspend(). */ 1122c4b65157SRafael J. Wysocki if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) || 11230c7376adSRafael J. Wysocki pci_dev_need_resume(pci_dev)) { 11247cd0602dSRafael J. Wysocki pm_runtime_resume(dev); 112582fee4d6SRafael J. Wysocki pci_dev->state_saved = false; 11260c7376adSRafael J. Wysocki } else { 11270c7376adSRafael J. Wysocki pci_dev_adjust_pme(pci_dev); 11280c7376adSRafael J. Wysocki } 11290c7376adSRafael J. Wysocki 11305294e256SRafael J. Wysocki if (pm->poweroff) { 113146939f8bSRafael J. Wysocki int error; 113246939f8bSRafael J. Wysocki 1133ddb7c9d2SRafael J. Wysocki error = pm->poweroff(dev); 1134ddb7c9d2SRafael J. Wysocki suspend_report_result(pm->poweroff, error); 113546939f8bSRafael J. Wysocki if (error) 113646939f8bSRafael J. Wysocki return error; 113746939f8bSRafael J. Wysocki } 113846939f8bSRafael J. Wysocki 113946939f8bSRafael J. Wysocki return 0; 114046939f8bSRafael J. Wysocki } 114146939f8bSRafael J. Wysocki 1142c4b65157SRafael J. Wysocki static int pci_pm_poweroff_late(struct device *dev) 1143c4b65157SRafael J. Wysocki { 1144c4b65157SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) 1145c4b65157SRafael J. Wysocki return 0; 1146c4b65157SRafael J. Wysocki 1147c4b65157SRafael J. Wysocki pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev)); 1148c4b65157SRafael J. Wysocki 1149c4b65157SRafael J. Wysocki return pm_generic_poweroff_late(dev); 1150c4b65157SRafael J. Wysocki } 1151c4b65157SRafael J. Wysocki 115246939f8bSRafael J. Wysocki static int pci_pm_poweroff_noirq(struct device *dev) 115346939f8bSRafael J. Wysocki { 115446939f8bSRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 11556da2f2ccSBjorn Helgaas const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 115646939f8bSRafael J. Wysocki 1157c4b65157SRafael J. Wysocki if (dev_pm_smart_suspend_and_suspended(dev)) 1158c4b65157SRafael J. Wysocki return 0; 1159c4b65157SRafael J. Wysocki 11606da2f2ccSBjorn Helgaas if (pci_has_legacy_pm_support(pci_dev)) 116146939f8bSRafael J. Wysocki return pci_legacy_suspend_late(dev, PMSG_HIBERNATE); 116246939f8bSRafael J. Wysocki 11636da2f2ccSBjorn Helgaas if (!pm) { 11647d2a01b8SAndreas Noever pci_fixup_device(pci_fixup_suspend_late, pci_dev); 116546939f8bSRafael J. Wysocki return 0; 11667d2a01b8SAndreas Noever } 116746939f8bSRafael J. Wysocki 11686da2f2ccSBjorn Helgaas if (pm->poweroff_noirq) { 116946939f8bSRafael J. Wysocki int error; 117046939f8bSRafael J. Wysocki 11716da2f2ccSBjorn Helgaas error = pm->poweroff_noirq(dev); 11726da2f2ccSBjorn Helgaas suspend_report_result(pm->poweroff_noirq, error); 117346939f8bSRafael J. Wysocki if (error) 117446939f8bSRafael J. Wysocki return error; 1175bbb44d9fSRafael J. Wysocki } 1176bbb44d9fSRafael J. Wysocki 1177326c1cdaSYijing Wang if (!pci_dev->state_saved && !pci_has_subordinate(pci_dev)) 11785294e256SRafael J. Wysocki pci_prepare_to_sleep(pci_dev); 11795294e256SRafael J. Wysocki 11800b68c8e2SRafael J. Wysocki /* 11810b68c8e2SRafael J. Wysocki * The reason for doing this here is the same as for the analogous code 11820b68c8e2SRafael J. Wysocki * in pci_pm_suspend_noirq(). 11830b68c8e2SRafael J. Wysocki */ 11840b68c8e2SRafael J. Wysocki if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) 11850b68c8e2SRafael J. Wysocki pci_write_config_word(pci_dev, PCI_COMMAND, 0); 11860b68c8e2SRafael J. Wysocki 11877d2a01b8SAndreas Noever pci_fixup_device(pci_fixup_suspend_late, pci_dev); 11887d2a01b8SAndreas Noever 1189699c1985SSebastian Ott if (pcibios_pm_ops.poweroff_noirq) 1190699c1985SSebastian Ott return pcibios_pm_ops.poweroff_noirq(dev); 1191699c1985SSebastian Ott 119246939f8bSRafael J. Wysocki return 0; 1193bbb44d9fSRafael J. Wysocki } 1194bbb44d9fSRafael J. Wysocki 1195bbb44d9fSRafael J. Wysocki static int pci_pm_restore_noirq(struct device *dev) 1196bbb44d9fSRafael J. Wysocki { 1197bbb44d9fSRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 11986da2f2ccSBjorn Helgaas const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 11996da2f2ccSBjorn Helgaas int error; 1200bbb44d9fSRafael J. Wysocki 1201699c1985SSebastian Ott if (pcibios_pm_ops.restore_noirq) { 1202699c1985SSebastian Ott error = pcibios_pm_ops.restore_noirq(dev); 1203699c1985SSebastian Ott if (error) 1204699c1985SSebastian Ott return error; 1205699c1985SSebastian Ott } 1206699c1985SSebastian Ott 12076cbf8214SRafael J. Wysocki pci_pm_default_resume_early(pci_dev); 12083e26c5feSRafael J. Wysocki pci_fixup_device(pci_fixup_resume_early, pci_dev); 1209aa8c6c93SRafael J. Wysocki 1210ad8cfa1dSRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 1211*89cdbc35SBjorn Helgaas return 0; 1212bb808945SRafael J. Wysocki 12136da2f2ccSBjorn Helgaas if (pm && pm->restore_noirq) 12146da2f2ccSBjorn Helgaas return pm->restore_noirq(dev); 1215bbb44d9fSRafael J. Wysocki 12166da2f2ccSBjorn Helgaas return 0; 1217bbb44d9fSRafael J. Wysocki } 1218bbb44d9fSRafael J. Wysocki 1219f6dc1e5eSRafael J. Wysocki static int pci_pm_restore(struct device *dev) 1220f6dc1e5eSRafael J. Wysocki { 1221f6dc1e5eSRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 12228150f32bSDmitry Torokhov const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 1223f6dc1e5eSRafael J. Wysocki 1224418e4da3SRafael J. Wysocki /* 1225418e4da3SRafael J. Wysocki * This is necessary for the hibernation error path in which restore is 1226418e4da3SRafael J. Wysocki * called without restoring the standard config registers of the device. 1227418e4da3SRafael J. Wysocki */ 1228418e4da3SRafael J. Wysocki if (pci_dev->state_saved) 1229418e4da3SRafael J. Wysocki pci_restore_standard_config(pci_dev); 1230418e4da3SRafael J. Wysocki 1231f6dc1e5eSRafael J. Wysocki if (pci_has_legacy_pm_support(pci_dev)) 1232f6dc1e5eSRafael J. Wysocki return pci_legacy_resume(dev); 1233f6dc1e5eSRafael J. Wysocki 12345294e256SRafael J. Wysocki pci_pm_default_resume(pci_dev); 1235f6dc1e5eSRafael J. Wysocki 12365294e256SRafael J. Wysocki if (pm) { 12375294e256SRafael J. Wysocki if (pm->restore) 12386da2f2ccSBjorn Helgaas return pm->restore(dev); 12395294e256SRafael J. Wysocki } else { 12405294e256SRafael J. Wysocki pci_pm_reenable_device(pci_dev); 12415294e256SRafael J. Wysocki } 1242f6dc1e5eSRafael J. Wysocki 12436da2f2ccSBjorn Helgaas return 0; 1244f6dc1e5eSRafael J. Wysocki } 1245f6dc1e5eSRafael J. Wysocki 12461f112ceeSRafael J. Wysocki #else /* !CONFIG_HIBERNATE_CALLBACKS */ 1247bbb44d9fSRafael J. Wysocki 1248bbb44d9fSRafael J. Wysocki #define pci_pm_freeze NULL 1249bbb44d9fSRafael J. Wysocki #define pci_pm_freeze_noirq NULL 1250bbb44d9fSRafael J. Wysocki #define pci_pm_thaw NULL 1251bbb44d9fSRafael J. Wysocki #define pci_pm_thaw_noirq NULL 1252bbb44d9fSRafael J. Wysocki #define pci_pm_poweroff NULL 1253c4b65157SRafael J. Wysocki #define pci_pm_poweroff_late NULL 1254bbb44d9fSRafael J. Wysocki #define pci_pm_poweroff_noirq NULL 1255bbb44d9fSRafael J. Wysocki #define pci_pm_restore NULL 1256bbb44d9fSRafael J. Wysocki #define pci_pm_restore_noirq NULL 1257bbb44d9fSRafael J. Wysocki 12581f112ceeSRafael J. Wysocki #endif /* !CONFIG_HIBERNATE_CALLBACKS */ 1259bbb44d9fSRafael J. Wysocki 1260fbb988beSRafael J. Wysocki #ifdef CONFIG_PM 12616cbf8214SRafael J. Wysocki 12626cbf8214SRafael J. Wysocki static int pci_pm_runtime_suspend(struct device *dev) 12636cbf8214SRafael J. Wysocki { 12646cbf8214SRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 12656cbf8214SRafael J. Wysocki const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 12666cbf8214SRafael J. Wysocki pci_power_t prev = pci_dev->current_state; 12676cbf8214SRafael J. Wysocki int error; 12686cbf8214SRafael J. Wysocki 1269967577b0SHuang Ying /* 12705775b843SRafael J. Wysocki * If pci_dev->driver is not set (unbound), we leave the device in D0, 12715775b843SRafael J. Wysocki * but it may go to D3cold when the bridge above it runtime suspends. 12725775b843SRafael J. Wysocki * Save its config space in case that happens. 1273967577b0SHuang Ying */ 12745775b843SRafael J. Wysocki if (!pci_dev->driver) { 12755775b843SRafael J. Wysocki pci_save_state(pci_dev); 1276967577b0SHuang Ying return 0; 12775775b843SRafael J. Wysocki } 1278967577b0SHuang Ying 127982fee4d6SRafael J. Wysocki pci_dev->state_saved = false; 1280c5eb1190SJarkko Nikula if (pm && pm->runtime_suspend) { 12816cbf8214SRafael J. Wysocki error = pm->runtime_suspend(dev); 128206bf403dSImre Deak /* 128306bf403dSImre Deak * -EBUSY and -EAGAIN is used to request the runtime PM core 128406bf403dSImre Deak * to schedule a new suspend, so log the event only with debug 128506bf403dSImre Deak * log level. 128606bf403dSImre Deak */ 1287c5eb1190SJarkko Nikula if (error == -EBUSY || error == -EAGAIN) { 12886941a0c2SBjorn Helgaas pci_dbg(pci_dev, "can't suspend now (%ps returned %d)\n", 128906bf403dSImre Deak pm->runtime_suspend, error); 1290c5eb1190SJarkko Nikula return error; 1291c5eb1190SJarkko Nikula } else if (error) { 12926941a0c2SBjorn Helgaas pci_err(pci_dev, "can't suspend (%ps returned %d)\n", 129306bf403dSImre Deak pm->runtime_suspend, error); 12946cbf8214SRafael J. Wysocki return error; 129506bf403dSImre Deak } 1296c5eb1190SJarkko Nikula } 12976cbf8214SRafael J. Wysocki 12986cbf8214SRafael J. Wysocki pci_fixup_device(pci_fixup_suspend, pci_dev); 12996cbf8214SRafael J. Wysocki 1300c5eb1190SJarkko Nikula if (pm && pm->runtime_suspend 1301c5eb1190SJarkko Nikula && !pci_dev->state_saved && pci_dev->current_state != PCI_D0 13026cbf8214SRafael J. Wysocki && pci_dev->current_state != PCI_UNKNOWN) { 130312bcae44SBjorn Helgaas pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, 1304d75f773cSSakari Ailus "PCI PM: State of device not saved by %pS\n", 13056cbf8214SRafael J. Wysocki pm->runtime_suspend); 13066cbf8214SRafael J. Wysocki return 0; 13076cbf8214SRafael J. Wysocki } 13086cbf8214SRafael J. Wysocki 130942eca230SDave Airlie if (!pci_dev->state_saved) { 13106cbf8214SRafael J. Wysocki pci_save_state(pci_dev); 13116cbf8214SRafael J. Wysocki pci_finish_runtime_suspend(pci_dev); 131242eca230SDave Airlie } 13136cbf8214SRafael J. Wysocki 13146cbf8214SRafael J. Wysocki return 0; 13156cbf8214SRafael J. Wysocki } 13166cbf8214SRafael J. Wysocki 13176cbf8214SRafael J. Wysocki static int pci_pm_runtime_resume(struct device *dev) 13186cbf8214SRafael J. Wysocki { 13196cbf8214SRafael J. Wysocki struct pci_dev *pci_dev = to_pci_dev(dev); 13206cbf8214SRafael J. Wysocki const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 13216da2f2ccSBjorn Helgaas int error = 0; 13226cbf8214SRafael J. Wysocki 1323967577b0SHuang Ying /* 13245775b843SRafael J. Wysocki * Restoring config space is necessary even if the device is not bound 13255775b843SRafael J. Wysocki * to a driver because although we left it in D0, it may have gone to 13265775b843SRafael J. Wysocki * D3cold when the bridge above it runtime suspended. 1327967577b0SHuang Ying */ 13285775b843SRafael J. Wysocki pci_restore_standard_config(pci_dev); 13295775b843SRafael J. Wysocki 1330967577b0SHuang Ying if (!pci_dev->driver) 1331967577b0SHuang Ying return 0; 1332967577b0SHuang Ying 1333db288c9cSRafael J. Wysocki pci_fixup_device(pci_fixup_resume_early, pci_dev); 1334f7b32a86SBjorn Helgaas pci_pm_default_resume(pci_dev); 13356cbf8214SRafael J. Wysocki 1336c5eb1190SJarkko Nikula if (pm && pm->runtime_resume) 13376da2f2ccSBjorn Helgaas error = pm->runtime_resume(dev); 1338448bd857SHuang Ying 1339448bd857SHuang Ying pci_dev->runtime_d3cold = false; 1340448bd857SHuang Ying 13416da2f2ccSBjorn Helgaas return error; 13426cbf8214SRafael J. Wysocki } 13436cbf8214SRafael J. Wysocki 13446cbf8214SRafael J. Wysocki static int pci_pm_runtime_idle(struct device *dev) 13456cbf8214SRafael J. Wysocki { 1346967577b0SHuang Ying struct pci_dev *pci_dev = to_pci_dev(dev); 13476cbf8214SRafael J. Wysocki const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; 13486cbf8214SRafael J. Wysocki 1349967577b0SHuang Ying /* 1350967577b0SHuang Ying * If pci_dev->driver is not set (unbound), the device should 1351967577b0SHuang Ying * always remain in D0 regardless of the runtime PM status 1352967577b0SHuang Ying */ 1353967577b0SHuang Ying if (!pci_dev->driver) 135445f0a85cSRafael J. Wysocki return 0; 1355967577b0SHuang Ying 13566cbf8214SRafael J. Wysocki if (!pm) 13576cbf8214SRafael J. Wysocki return -ENOSYS; 13586cbf8214SRafael J. Wysocki 135945f0a85cSRafael J. Wysocki if (pm->runtime_idle) 13606da2f2ccSBjorn Helgaas return pm->runtime_idle(dev); 13616cbf8214SRafael J. Wysocki 13626da2f2ccSBjorn Helgaas return 0; 13636cbf8214SRafael J. Wysocki } 13646cbf8214SRafael J. Wysocki 1365f91da04dSSachin Kamat static const struct dev_pm_ops pci_dev_pm_ops = { 1366bbb44d9fSRafael J. Wysocki .prepare = pci_pm_prepare, 13672cef548aSRafael J. Wysocki .complete = pci_pm_complete, 1368bbb44d9fSRafael J. Wysocki .suspend = pci_pm_suspend, 1369c4b65157SRafael J. Wysocki .suspend_late = pci_pm_suspend_late, 1370bbb44d9fSRafael J. Wysocki .resume = pci_pm_resume, 1371bbb44d9fSRafael J. Wysocki .freeze = pci_pm_freeze, 1372bbb44d9fSRafael J. Wysocki .thaw = pci_pm_thaw, 1373bbb44d9fSRafael J. Wysocki .poweroff = pci_pm_poweroff, 1374c4b65157SRafael J. Wysocki .poweroff_late = pci_pm_poweroff_late, 1375bbb44d9fSRafael J. Wysocki .restore = pci_pm_restore, 1376bbb44d9fSRafael J. Wysocki .suspend_noirq = pci_pm_suspend_noirq, 1377bbb44d9fSRafael J. Wysocki .resume_noirq = pci_pm_resume_noirq, 1378bbb44d9fSRafael J. Wysocki .freeze_noirq = pci_pm_freeze_noirq, 1379bbb44d9fSRafael J. Wysocki .thaw_noirq = pci_pm_thaw_noirq, 1380bbb44d9fSRafael J. Wysocki .poweroff_noirq = pci_pm_poweroff_noirq, 1381bbb44d9fSRafael J. Wysocki .restore_noirq = pci_pm_restore_noirq, 13826cbf8214SRafael J. Wysocki .runtime_suspend = pci_pm_runtime_suspend, 13836cbf8214SRafael J. Wysocki .runtime_resume = pci_pm_runtime_resume, 13846cbf8214SRafael J. Wysocki .runtime_idle = pci_pm_runtime_idle, 1385bbb44d9fSRafael J. Wysocki }; 1386bbb44d9fSRafael J. Wysocki 1387adf09493SRafael J. Wysocki #define PCI_PM_OPS_PTR (&pci_dev_pm_ops) 1388bbb44d9fSRafael J. Wysocki 1389fbb988beSRafael J. Wysocki #else /* !CONFIG_PM */ 1390fbb988beSRafael J. Wysocki 1391fbb988beSRafael J. Wysocki #define pci_pm_runtime_suspend NULL 1392fbb988beSRafael J. Wysocki #define pci_pm_runtime_resume NULL 1393fbb988beSRafael J. Wysocki #define pci_pm_runtime_idle NULL 1394bbb44d9fSRafael J. Wysocki 1395bbb44d9fSRafael J. Wysocki #define PCI_PM_OPS_PTR NULL 1396bbb44d9fSRafael J. Wysocki 1397fbb988beSRafael J. Wysocki #endif /* !CONFIG_PM */ 13981da177e4SLinus Torvalds 13991da177e4SLinus Torvalds /** 1400863b18f4SLaurent riffard * __pci_register_driver - register a new pci driver 14011da177e4SLinus Torvalds * @drv: the driver structure to register 1402863b18f4SLaurent riffard * @owner: owner module of drv 1403f95d882dSRandy Dunlap * @mod_name: module name string 14041da177e4SLinus Torvalds * 14051da177e4SLinus Torvalds * Adds the driver structure to the list of registered drivers. 14061da177e4SLinus Torvalds * Returns a negative value on error, otherwise 0. 1407eaae4b3aSSteven Cole * If no error occurred, the driver remains registered even if 14081da177e4SLinus Torvalds * no device was claimed during registration. 14091da177e4SLinus Torvalds */ 1410725522b5SGreg Kroah-Hartman int __pci_register_driver(struct pci_driver *drv, struct module *owner, 1411725522b5SGreg Kroah-Hartman const char *mod_name) 14121da177e4SLinus Torvalds { 14131da177e4SLinus Torvalds /* initialize common driver fields */ 14141da177e4SLinus Torvalds drv->driver.name = drv->name; 14151da177e4SLinus Torvalds drv->driver.bus = &pci_bus_type; 1416863b18f4SLaurent riffard drv->driver.owner = owner; 1417725522b5SGreg Kroah-Hartman drv->driver.mod_name = mod_name; 141892d50fc1SGreg Kroah-Hartman drv->driver.groups = drv->groups; 141950b00755SAlan Cox 142075865858SGreg Kroah-Hartman spin_lock_init(&drv->dynids.lock); 142175865858SGreg Kroah-Hartman INIT_LIST_HEAD(&drv->dynids.list); 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds /* register with core */ 1424bfb09a86SKonstantin Khlebnikov return driver_register(&drv->driver); 14251da177e4SLinus Torvalds } 1426b7fe9434SRyan Desfosses EXPORT_SYMBOL(__pci_register_driver); 14271da177e4SLinus Torvalds 14281da177e4SLinus Torvalds /** 14291da177e4SLinus Torvalds * pci_unregister_driver - unregister a pci driver 14301da177e4SLinus Torvalds * @drv: the driver structure to unregister 14311da177e4SLinus Torvalds * 14321da177e4SLinus Torvalds * Deletes the driver structure from the list of registered PCI drivers, 14331da177e4SLinus Torvalds * gives it a chance to clean up by calling its remove() function for 14341da177e4SLinus Torvalds * each device it was responsible for, and marks those devices as 14351da177e4SLinus Torvalds * driverless. 14361da177e4SLinus Torvalds */ 14371da177e4SLinus Torvalds 14383c78bc61SRyan Desfosses void pci_unregister_driver(struct pci_driver *drv) 14391da177e4SLinus Torvalds { 14401da177e4SLinus Torvalds driver_unregister(&drv->driver); 14411da177e4SLinus Torvalds pci_free_dynids(drv); 14421da177e4SLinus Torvalds } 1443b7fe9434SRyan Desfosses EXPORT_SYMBOL(pci_unregister_driver); 14441da177e4SLinus Torvalds 14451da177e4SLinus Torvalds static struct pci_driver pci_compat_driver = { 14461da177e4SLinus Torvalds .name = "compat" 14471da177e4SLinus Torvalds }; 14481da177e4SLinus Torvalds 14491da177e4SLinus Torvalds /** 14501da177e4SLinus Torvalds * pci_dev_driver - get the pci_driver of a device 14511da177e4SLinus Torvalds * @dev: the device to query 14521da177e4SLinus Torvalds * 14531da177e4SLinus Torvalds * Returns the appropriate pci_driver structure or %NULL if there is no 14541da177e4SLinus Torvalds * registered driver for the device. 14551da177e4SLinus Torvalds */ 14563c78bc61SRyan Desfosses struct pci_driver *pci_dev_driver(const struct pci_dev *dev) 14571da177e4SLinus Torvalds { 14581da177e4SLinus Torvalds if (dev->driver) 14591da177e4SLinus Torvalds return dev->driver; 14601da177e4SLinus Torvalds else { 14611da177e4SLinus Torvalds int i; 14621da177e4SLinus Torvalds for (i = 0; i <= PCI_ROM_RESOURCE; i++) 14631da177e4SLinus Torvalds if (dev->resource[i].flags & IORESOURCE_BUSY) 14641da177e4SLinus Torvalds return &pci_compat_driver; 14651da177e4SLinus Torvalds } 14661da177e4SLinus Torvalds return NULL; 14671da177e4SLinus Torvalds } 1468b7fe9434SRyan Desfosses EXPORT_SYMBOL(pci_dev_driver); 14691da177e4SLinus Torvalds 14701da177e4SLinus Torvalds /** 14711da177e4SLinus Torvalds * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure 14721da177e4SLinus Torvalds * @dev: the PCI device structure to match against 14738f7020d3SRandy Dunlap * @drv: the device driver to search for matching PCI device id structures 14741da177e4SLinus Torvalds * 14751da177e4SLinus Torvalds * Used by a driver to check whether a PCI device present in the 14761da177e4SLinus Torvalds * system is in its list of supported devices. Returns the matching 14771da177e4SLinus Torvalds * pci_device_id structure or %NULL if there is no match. 14781da177e4SLinus Torvalds */ 14791da177e4SLinus Torvalds static int pci_bus_match(struct device *dev, struct device_driver *drv) 14801da177e4SLinus Torvalds { 148175865858SGreg Kroah-Hartman struct pci_dev *pci_dev = to_pci_dev(dev); 148258d9a38fSYinghai Lu struct pci_driver *pci_drv; 14831da177e4SLinus Torvalds const struct pci_device_id *found_id; 14841da177e4SLinus Torvalds 148558d9a38fSYinghai Lu if (!pci_dev->match_driver) 148658d9a38fSYinghai Lu return 0; 148758d9a38fSYinghai Lu 148858d9a38fSYinghai Lu pci_drv = to_pci_driver(drv); 148975865858SGreg Kroah-Hartman found_id = pci_match_device(pci_drv, pci_dev); 14901da177e4SLinus Torvalds if (found_id) 14911da177e4SLinus Torvalds return 1; 14921da177e4SLinus Torvalds 149375865858SGreg Kroah-Hartman return 0; 14941da177e4SLinus Torvalds } 14951da177e4SLinus Torvalds 14961da177e4SLinus Torvalds /** 14971da177e4SLinus Torvalds * pci_dev_get - increments the reference count of the pci device structure 14981da177e4SLinus Torvalds * @dev: the device being referenced 14991da177e4SLinus Torvalds * 15001da177e4SLinus Torvalds * Each live reference to a device should be refcounted. 15011da177e4SLinus Torvalds * 15021da177e4SLinus Torvalds * Drivers for PCI devices should normally record such references in 15031da177e4SLinus Torvalds * their probe() methods, when they bind to a device, and release 15041da177e4SLinus Torvalds * them by calling pci_dev_put(), in their disconnect() methods. 15051da177e4SLinus Torvalds * 15061da177e4SLinus Torvalds * A pointer to the device with the incremented reference counter is returned. 15071da177e4SLinus Torvalds */ 15081da177e4SLinus Torvalds struct pci_dev *pci_dev_get(struct pci_dev *dev) 15091da177e4SLinus Torvalds { 15101da177e4SLinus Torvalds if (dev) 15111da177e4SLinus Torvalds get_device(&dev->dev); 15121da177e4SLinus Torvalds return dev; 15131da177e4SLinus Torvalds } 1514b7fe9434SRyan Desfosses EXPORT_SYMBOL(pci_dev_get); 15151da177e4SLinus Torvalds 15161da177e4SLinus Torvalds /** 15171da177e4SLinus Torvalds * pci_dev_put - release a use of the pci device structure 15181da177e4SLinus Torvalds * @dev: device that's been disconnected 15191da177e4SLinus Torvalds * 15201da177e4SLinus Torvalds * Must be called when a user of a device is finished with it. When the last 15211da177e4SLinus Torvalds * user of the device calls this function, the memory of the device is freed. 15221da177e4SLinus Torvalds */ 15231da177e4SLinus Torvalds void pci_dev_put(struct pci_dev *dev) 15241da177e4SLinus Torvalds { 15251da177e4SLinus Torvalds if (dev) 15261da177e4SLinus Torvalds put_device(&dev->dev); 15271da177e4SLinus Torvalds } 1528b7fe9434SRyan Desfosses EXPORT_SYMBOL(pci_dev_put); 15291da177e4SLinus Torvalds 15308ccc9aa1SBill Pemberton static int pci_uevent(struct device *dev, struct kobj_uevent_env *env) 15318ccc9aa1SBill Pemberton { 15328ccc9aa1SBill Pemberton struct pci_dev *pdev; 15338ccc9aa1SBill Pemberton 15348ccc9aa1SBill Pemberton if (!dev) 15358ccc9aa1SBill Pemberton return -ENODEV; 15368ccc9aa1SBill Pemberton 15378ccc9aa1SBill Pemberton pdev = to_pci_dev(dev); 15388ccc9aa1SBill Pemberton 15398ccc9aa1SBill Pemberton if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class)) 15408ccc9aa1SBill Pemberton return -ENOMEM; 15418ccc9aa1SBill Pemberton 15428ccc9aa1SBill Pemberton if (add_uevent_var(env, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device)) 15438ccc9aa1SBill Pemberton return -ENOMEM; 15448ccc9aa1SBill Pemberton 15458ccc9aa1SBill Pemberton if (add_uevent_var(env, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, 15468ccc9aa1SBill Pemberton pdev->subsystem_device)) 15478ccc9aa1SBill Pemberton return -ENOMEM; 15488ccc9aa1SBill Pemberton 15498ccc9aa1SBill Pemberton if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev))) 15508ccc9aa1SBill Pemberton return -ENOMEM; 15518ccc9aa1SBill Pemberton 1552145b3fe5SRicardo Ribalda Delgado if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X", 15538ccc9aa1SBill Pemberton pdev->vendor, pdev->device, 15548ccc9aa1SBill Pemberton pdev->subsystem_vendor, pdev->subsystem_device, 15558ccc9aa1SBill Pemberton (u8)(pdev->class >> 16), (u8)(pdev->class >> 8), 15568ccc9aa1SBill Pemberton (u8)(pdev->class))) 15578ccc9aa1SBill Pemberton return -ENOMEM; 1558efdd4070SBjorn Helgaas 15598ccc9aa1SBill Pemberton return 0; 15608ccc9aa1SBill Pemberton } 15618ccc9aa1SBill Pemberton 15622e28bc84SOza Pawandeep #if defined(CONFIG_PCIEPORTBUS) || defined(CONFIG_EEH) 15633ecac020SMichael Ellerman /** 15643ecac020SMichael Ellerman * pci_uevent_ers - emit a uevent during recovery path of PCI device 15653ecac020SMichael Ellerman * @pdev: PCI device undergoing error recovery 15663ecac020SMichael Ellerman * @err_type: type of error event 15673ecac020SMichael Ellerman */ 15683ecac020SMichael Ellerman void pci_uevent_ers(struct pci_dev *pdev, enum pci_ers_result err_type) 15693ecac020SMichael Ellerman { 15703ecac020SMichael Ellerman int idx = 0; 15713ecac020SMichael Ellerman char *envp[3]; 15723ecac020SMichael Ellerman 15733ecac020SMichael Ellerman switch (err_type) { 15743ecac020SMichael Ellerman case PCI_ERS_RESULT_NONE: 15753ecac020SMichael Ellerman case PCI_ERS_RESULT_CAN_RECOVER: 15763ecac020SMichael Ellerman envp[idx++] = "ERROR_EVENT=BEGIN_RECOVERY"; 15773ecac020SMichael Ellerman envp[idx++] = "DEVICE_ONLINE=0"; 15783ecac020SMichael Ellerman break; 15793ecac020SMichael Ellerman case PCI_ERS_RESULT_RECOVERED: 15803ecac020SMichael Ellerman envp[idx++] = "ERROR_EVENT=SUCCESSFUL_RECOVERY"; 15813ecac020SMichael Ellerman envp[idx++] = "DEVICE_ONLINE=1"; 15823ecac020SMichael Ellerman break; 15833ecac020SMichael Ellerman case PCI_ERS_RESULT_DISCONNECT: 15843ecac020SMichael Ellerman envp[idx++] = "ERROR_EVENT=FAILED_RECOVERY"; 15853ecac020SMichael Ellerman envp[idx++] = "DEVICE_ONLINE=0"; 15863ecac020SMichael Ellerman break; 15873ecac020SMichael Ellerman default: 15883ecac020SMichael Ellerman break; 15893ecac020SMichael Ellerman } 15903ecac020SMichael Ellerman 15913ecac020SMichael Ellerman if (idx > 0) { 15923ecac020SMichael Ellerman envp[idx++] = NULL; 15933ecac020SMichael Ellerman kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp); 15943ecac020SMichael Ellerman } 15953ecac020SMichael Ellerman } 15963ecac020SMichael Ellerman #endif 15973ecac020SMichael Ellerman 159802e0bea6SPhil Sutter static int pci_bus_num_vf(struct device *dev) 159902e0bea6SPhil Sutter { 160002e0bea6SPhil Sutter return pci_num_vf(to_pci_dev(dev)); 160102e0bea6SPhil Sutter } 160202e0bea6SPhil Sutter 160307397df2SNipun Gupta /** 160407397df2SNipun Gupta * pci_dma_configure - Setup DMA configuration 160507397df2SNipun Gupta * @dev: ptr to dev structure 160607397df2SNipun Gupta * 160707397df2SNipun Gupta * Function to update PCI devices's DMA configuration using the same 160807397df2SNipun Gupta * info from the OF node or ACPI node of host bridge's parent (if any). 160907397df2SNipun Gupta */ 161007397df2SNipun Gupta static int pci_dma_configure(struct device *dev) 161107397df2SNipun Gupta { 161207397df2SNipun Gupta struct device *bridge; 161307397df2SNipun Gupta int ret = 0; 161407397df2SNipun Gupta 161507397df2SNipun Gupta bridge = pci_get_host_bridge_device(to_pci_dev(dev)); 161607397df2SNipun Gupta 161707397df2SNipun Gupta if (IS_ENABLED(CONFIG_OF) && bridge->parent && 161807397df2SNipun Gupta bridge->parent->of_node) { 16193d6ce86eSChristoph Hellwig ret = of_dma_configure(dev, bridge->parent->of_node, true); 162007397df2SNipun Gupta } else if (has_acpi_companion(bridge)) { 162107397df2SNipun Gupta struct acpi_device *adev = to_acpi_device_node(bridge->fwnode); 162207397df2SNipun Gupta 1623e5361ca2SRobin Murphy ret = acpi_dma_configure(dev, acpi_get_dma_attr(adev)); 162407397df2SNipun Gupta } 162507397df2SNipun Gupta 162607397df2SNipun Gupta pci_put_host_bridge_device(bridge); 162707397df2SNipun Gupta return ret; 162807397df2SNipun Gupta } 162907397df2SNipun Gupta 16301da177e4SLinus Torvalds struct bus_type pci_bus_type = { 16311da177e4SLinus Torvalds .name = "pci", 16321da177e4SLinus Torvalds .match = pci_bus_match, 1633312c004dSKay Sievers .uevent = pci_uevent, 1634b15d686aSRussell King .probe = pci_device_probe, 1635b15d686aSRussell King .remove = pci_device_remove, 1636cbd69dbbSLinus Torvalds .shutdown = pci_device_shutdown, 16375136b2daSGreg Kroah-Hartman .dev_groups = pci_dev_groups, 16380f49ba55SGreg Kroah-Hartman .bus_groups = pci_bus_groups, 16392229c1fbSGreg Kroah-Hartman .drv_groups = pci_drv_groups, 1640bbb44d9fSRafael J. Wysocki .pm = PCI_PM_OPS_PTR, 164102e0bea6SPhil Sutter .num_vf = pci_bus_num_vf, 164207397df2SNipun Gupta .dma_configure = pci_dma_configure, 16431da177e4SLinus Torvalds }; 1644b7fe9434SRyan Desfosses EXPORT_SYMBOL(pci_bus_type); 16451da177e4SLinus Torvalds 1646c6c889d9SBjorn Helgaas #ifdef CONFIG_PCIEPORTBUS 1647c6c889d9SBjorn Helgaas static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) 1648c6c889d9SBjorn Helgaas { 1649c6c889d9SBjorn Helgaas struct pcie_device *pciedev; 1650c6c889d9SBjorn Helgaas struct pcie_port_service_driver *driver; 1651c6c889d9SBjorn Helgaas 1652c6c889d9SBjorn Helgaas if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) 1653c6c889d9SBjorn Helgaas return 0; 1654c6c889d9SBjorn Helgaas 1655c6c889d9SBjorn Helgaas pciedev = to_pcie_device(dev); 1656c6c889d9SBjorn Helgaas driver = to_service_driver(drv); 1657c6c889d9SBjorn Helgaas 1658c6c889d9SBjorn Helgaas if (driver->service != pciedev->service) 1659c6c889d9SBjorn Helgaas return 0; 1660c6c889d9SBjorn Helgaas 1661c6c889d9SBjorn Helgaas if (driver->port_type != PCIE_ANY_PORT && 1662c6c889d9SBjorn Helgaas driver->port_type != pci_pcie_type(pciedev->port)) 1663c6c889d9SBjorn Helgaas return 0; 1664c6c889d9SBjorn Helgaas 1665c6c889d9SBjorn Helgaas return 1; 1666c6c889d9SBjorn Helgaas } 1667c6c889d9SBjorn Helgaas 1668c6c889d9SBjorn Helgaas struct bus_type pcie_port_bus_type = { 1669c6c889d9SBjorn Helgaas .name = "pci_express", 1670c6c889d9SBjorn Helgaas .match = pcie_port_bus_match, 1671c6c889d9SBjorn Helgaas }; 1672c6c889d9SBjorn Helgaas EXPORT_SYMBOL_GPL(pcie_port_bus_type); 1673c6c889d9SBjorn Helgaas #endif 1674c6c889d9SBjorn Helgaas 16751da177e4SLinus Torvalds static int __init pci_driver_init(void) 16761da177e4SLinus Torvalds { 1677c6c889d9SBjorn Helgaas int ret; 1678c6c889d9SBjorn Helgaas 1679c6c889d9SBjorn Helgaas ret = bus_register(&pci_bus_type); 1680c6c889d9SBjorn Helgaas if (ret) 1681c6c889d9SBjorn Helgaas return ret; 1682c6c889d9SBjorn Helgaas 1683c6c889d9SBjorn Helgaas #ifdef CONFIG_PCIEPORTBUS 1684c6c889d9SBjorn Helgaas ret = bus_register(&pcie_port_bus_type); 1685c6c889d9SBjorn Helgaas if (ret) 1686c6c889d9SBjorn Helgaas return ret; 1687c6c889d9SBjorn Helgaas #endif 1688a8651194SChristoph Hellwig dma_debug_add_bus(&pci_bus_type); 1689c6c889d9SBjorn Helgaas return 0; 16901da177e4SLinus Torvalds } 16911da177e4SLinus Torvalds postcore_initcall(pci_driver_init); 1692