PCI: Autosense device removal in pci_bridge_d3_update()
The algorithm to update the flag indicating whether a bridge may go to D3 makes a few optimizations based on whether the update was caused by the removal of a device on the one hand, versus the addition of a device or the change of its D3cold flags on the other hand. The information whether the update pertains to a removal is currently passed in by the caller, but the function may as well determine that itself by examining the device in question, thereby allowing for a considerable simplification and reduction of the code. Out of several options to determine removal, I've chosen the function device_is_registered() because it's cheap: It merely returns the dev->kobj.state_in_sysfs flag. That flag is set through device_add() when the root bus is scanned and cleared through device_remove(). The call to pci_bridge_d3_update() happens after each of these calls, respectively, so the ordering is correct. No functional change intended. Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
738a7edbfc
commit
1ed276a7b9
|
@ -320,7 +320,7 @@ void pci_bus_add_device(struct pci_dev *dev)
|
|||
pci_fixup_device(pci_fixup_final, dev);
|
||||
pci_create_sysfs_dev_files(dev);
|
||||
pci_proc_attach_device(dev);
|
||||
pci_bridge_d3_device_changed(dev);
|
||||
pci_bridge_d3_update(dev);
|
||||
|
||||
dev->match_driver = true;
|
||||
retval = device_attach(&dev->dev);
|
||||
|
|
|
@ -2281,14 +2281,14 @@ static int pci_dev_check_d3cold(struct pci_dev *dev, void *data)
|
|||
/*
|
||||
* pci_bridge_d3_update - Update bridge D3 capabilities
|
||||
* @dev: PCI device which is changed
|
||||
* @remove: Is the device being removed
|
||||
*
|
||||
* Update upstream bridge PM capabilities accordingly depending on if the
|
||||
* device PM configuration was changed or the device is being removed. The
|
||||
* change is also propagated upstream.
|
||||
*/
|
||||
static void pci_bridge_d3_update(struct pci_dev *dev, bool remove)
|
||||
void pci_bridge_d3_update(struct pci_dev *dev)
|
||||
{
|
||||
bool remove = !device_is_registered(&dev->dev);
|
||||
struct pci_dev *bridge;
|
||||
bool d3cold_ok = true;
|
||||
|
||||
|
@ -2315,35 +2315,10 @@ static void pci_bridge_d3_update(struct pci_dev *dev, bool remove)
|
|||
if (bridge->bridge_d3 != d3cold_ok) {
|
||||
bridge->bridge_d3 = d3cold_ok;
|
||||
/* Propagate change to upstream bridges */
|
||||
pci_bridge_d3_update(bridge, false);
|
||||
pci_bridge_d3_update(bridge);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_bridge_d3_device_changed - Update bridge D3 capabilities on change
|
||||
* @dev: PCI device that was changed
|
||||
*
|
||||
* If a device is added or its PM configuration, such as is it allowed to
|
||||
* enter D3cold, is changed this function updates upstream bridge PM
|
||||
* capabilities accordingly.
|
||||
*/
|
||||
void pci_bridge_d3_device_changed(struct pci_dev *dev)
|
||||
{
|
||||
pci_bridge_d3_update(dev, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_bridge_d3_device_removed - Update bridge D3 capabilities on remove
|
||||
* @dev: PCI device being removed
|
||||
*
|
||||
* Function updates upstream bridge PM capabilities based on other devices
|
||||
* still left on the bus.
|
||||
*/
|
||||
void pci_bridge_d3_device_removed(struct pci_dev *dev)
|
||||
{
|
||||
pci_bridge_d3_update(dev, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_d3cold_enable - Enable D3cold for device
|
||||
* @dev: PCI device to handle
|
||||
|
@ -2356,7 +2331,7 @@ void pci_d3cold_enable(struct pci_dev *dev)
|
|||
{
|
||||
if (dev->no_d3cold) {
|
||||
dev->no_d3cold = false;
|
||||
pci_bridge_d3_device_changed(dev);
|
||||
pci_bridge_d3_update(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_d3cold_enable);
|
||||
|
@ -2373,7 +2348,7 @@ void pci_d3cold_disable(struct pci_dev *dev)
|
|||
{
|
||||
if (!dev->no_d3cold) {
|
||||
dev->no_d3cold = true;
|
||||
pci_bridge_d3_device_changed(dev);
|
||||
pci_bridge_d3_update(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_d3cold_disable);
|
||||
|
|
|
@ -85,8 +85,7 @@ void pci_pm_init(struct pci_dev *dev);
|
|||
void pci_ea_init(struct pci_dev *dev);
|
||||
void pci_allocate_cap_save_buffers(struct pci_dev *dev);
|
||||
void pci_free_cap_save_buffers(struct pci_dev *dev);
|
||||
void pci_bridge_d3_device_changed(struct pci_dev *dev);
|
||||
void pci_bridge_d3_device_removed(struct pci_dev *dev);
|
||||
void pci_bridge_d3_update(struct pci_dev *dev);
|
||||
|
||||
static inline void pci_wakeup_event(struct pci_dev *dev)
|
||||
{
|
||||
|
|
|
@ -40,7 +40,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
|
|||
list_del(&dev->bus_list);
|
||||
up_write(&pci_bus_sem);
|
||||
|
||||
pci_bridge_d3_device_removed(dev);
|
||||
pci_bridge_d3_update(dev);
|
||||
pci_free_resources(dev);
|
||||
put_device(&dev->dev);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue