diff options
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
| -rw-r--r-- | drivers/pci/pci-sysfs.c | 42 | 
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 6869009c739..02d107b1528 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -458,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)  }  struct device_attribute vga_attr = __ATTR_RO(boot_vga); +static void +pci_config_pm_runtime_get(struct pci_dev *pdev) +{ +	struct device *dev = &pdev->dev; +	struct device *parent = dev->parent; + +	if (parent) +		pm_runtime_get_sync(parent); +	pm_runtime_get_noresume(dev); +	/* +	 * pdev->current_state is set to PCI_D3cold during suspending, +	 * so wait until suspending completes +	 */ +	pm_runtime_barrier(dev); +	/* +	 * Only need to resume devices in D3cold, because config +	 * registers are still accessible for devices suspended but +	 * not in D3cold. +	 */ +	if (pdev->current_state == PCI_D3cold) +		pm_runtime_resume(dev); +} + +static void +pci_config_pm_runtime_put(struct pci_dev *pdev) +{ +	struct device *dev = &pdev->dev; +	struct device *parent = dev->parent; + +	pm_runtime_put(dev); +	if (parent) +		pm_runtime_put_sync(parent); +} +  static ssize_t  pci_read_config(struct file *filp, struct kobject *kobj,  		struct bin_attribute *bin_attr, @@ -484,6 +518,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,  		size = count;  	} +	pci_config_pm_runtime_get(dev); +  	if ((off & 1) && size) {  		u8 val;  		pci_user_read_config_byte(dev, off, &val); @@ -529,6 +565,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,  		--size;  	} +	pci_config_pm_runtime_put(dev); +  	return count;  } @@ -549,6 +587,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,  		count = size;  	} +	pci_config_pm_runtime_get(dev); +  	if ((off & 1) && size) {  		pci_user_write_config_byte(dev, off, data[off - init_off]);  		off++; @@ -587,6 +627,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,  		--size;  	} +	pci_config_pm_runtime_put(dev); +  	return count;  }  |