mirror of https://gitee.com/openkylin/linux.git
PCI updates for v3.6:
Power management - PCI/PM: Enable D3/D3cold by default for most devices - PCI/PM: Keep parent bridge active when probing device - PCI/PM: Fix config reg access for D3cold and bridge suspending - PCI/PM: Add ABI document for sysfs file d3cold_allowed Core - PCI: Don't print anything while decoding is disabled -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJQSQ9nAAoJEPGMOI97Hn6zc+EQAMWlPJUAUR0uY2mnz9KANGxQ 7yHsgoCj1lbMNMrlyD9CveE1b5PCUwL8oiSnsLvqUwsdvNr14FGhCCtTYotoDEBh 2QuSkI2rG1y+2Kr9Lrd4TrzdcCfBjQ3vUIhU1va2uPjrf8fsPQCvm0Yn8gC/SKDg qV452021IFxkeO0PIZ9z7H4uaOIuqqb1mnqXImKZ3zUMNfNl0xLaZfrWUK5DG6qn Mgm25qCNZ70Hj5mM/AqhKLsWH2ruMsZuA/5QvdHHJmi0pGF8OkFtvcKNv785Ajlg Ar5YOtLaeszyVpueNAWzevH+1m86D6USW1yKnlxgVigVpxFNhHs2OHr4kU1IzwKU AkMdDCyGCBXoEBiXwozsMSVX4gi87k91ETpe8E/WlU5gkLN8hqBO8TJlCsLBAXGV 7RIWJPeoem6UjoYYbqUe8Z4/ZPbSgWgdVkSI9PLcVsVrPQZR0Z7f3JM5Kcdgooc9 iPQleMK0x5YPtsFHVqCJLD6A4xaWR8VZaK3hHSziYlyOjPpIJ0vErh5uxh6pWBWo wAzQDp/dfmOBhld7RzzQQrOyHHIPR7+jHghH7/zpgAhaaGhAeqMXX4Y+R2CKt9yR iNW6QlHasaBPQHehWjstMKlwR7iXZDORMtEv+tAyg2m1ZmgWi7Aut2Mk/6e3Z3Jy +d2tn7b5aBTc3y8dcVBP =zFNa -----END PGP SIGNATURE----- Merge tag '3.6-pci-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci Pull PCI updates from Bjorn Helgaas: "Power management - PCI/PM: Enable D3/D3cold by default for most devices - PCI/PM: Keep parent bridge active when probing device - PCI/PM: Fix config reg access for D3cold and bridge suspending - PCI/PM: Add ABI document for sysfs file d3cold_allowed Core - PCI: Don't print anything while decoding is disabled" * tag '3.6-pci-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: PCI: Don't print anything while decoding is disabled PCI/PM: Add ABI document for sysfs file d3cold_allowed PCI/PM: Fix config reg access for D3cold and bridge suspending PCI/PM: Keep parent bridge active when probing device PCI/PM: Enable D3/D3cold by default for most devices
This commit is contained in:
commit
f8b9cf0f31
|
@ -210,3 +210,15 @@ Users:
|
|||
firmware assigned instance number of the PCI
|
||||
device that can help in understanding the firmware
|
||||
intended order of the PCI device.
|
||||
|
||||
What: /sys/bus/pci/devices/.../d3cold_allowed
|
||||
Date: July 2012
|
||||
Contact: Huang Ying <ying.huang@intel.com>
|
||||
Description:
|
||||
d3cold_allowed is bit to control whether the corresponding PCI
|
||||
device can be put into D3Cold state. If it is cleared, the
|
||||
device will never be put into D3Cold state. If it is set, the
|
||||
device may be put into D3Cold state if other requirements are
|
||||
satisfied too. Reading this attribute will show the current
|
||||
value of d3cold_allowed bit. Writing this attribute will set
|
||||
the value of d3cold_allowed bit.
|
||||
|
|
|
@ -280,8 +280,12 @@ static long local_pci_probe(void *_ddi)
|
|||
{
|
||||
struct drv_dev_and_id *ddi = _ddi;
|
||||
struct device *dev = &ddi->dev->dev;
|
||||
struct device *parent = dev->parent;
|
||||
int rc;
|
||||
|
||||
/* The parent bridge must be in active state when probing */
|
||||
if (parent)
|
||||
pm_runtime_get_sync(parent);
|
||||
/* Unbound PCI devices are always set to disabled and suspended.
|
||||
* During probe, the device is set to enabled and active and the
|
||||
* usage count is incremented. If the driver supports runtime PM,
|
||||
|
@ -298,6 +302,8 @@ static long local_pci_probe(void *_ddi)
|
|||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
}
|
||||
if (parent)
|
||||
pm_runtime_put(parent);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1941,6 +1941,7 @@ void pci_pm_init(struct pci_dev *dev)
|
|||
dev->pm_cap = pm;
|
||||
dev->d3_delay = PCI_PM_D3_WAIT;
|
||||
dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
|
||||
dev->d3cold_allowed = true;
|
||||
|
||||
dev->d1_support = false;
|
||||
dev->d2_support = false;
|
||||
|
|
|
@ -140,9 +140,17 @@ static int pcie_port_runtime_resume(struct device *dev)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcie_port_runtime_idle(struct device *dev)
|
||||
{
|
||||
/* Delay for a short while to prevent too frequent suspend/resume */
|
||||
pm_schedule_suspend(dev, 10);
|
||||
return -EBUSY;
|
||||
}
|
||||
#else
|
||||
#define pcie_port_runtime_suspend NULL
|
||||
#define pcie_port_runtime_resume NULL
|
||||
#define pcie_port_runtime_idle NULL
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
||||
|
@ -155,6 +163,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
|||
.resume_noirq = pcie_port_resume_noirq,
|
||||
.runtime_suspend = pcie_port_runtime_suspend,
|
||||
.runtime_resume = pcie_port_runtime_resume,
|
||||
.runtime_idle = pcie_port_runtime_idle,
|
||||
};
|
||||
|
||||
#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
|
||||
|
@ -200,6 +209,11 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
|
|||
return status;
|
||||
|
||||
pci_save_state(dev);
|
||||
/*
|
||||
* D3cold may not work properly on some PCIe port, so disable
|
||||
* it by default.
|
||||
*/
|
||||
dev->d3cold_allowed = false;
|
||||
if (!pci_match_id(port_runtime_pm_black_list, dev))
|
||||
pm_runtime_put_noidle(&dev->dev);
|
||||
|
||||
|
|
|
@ -144,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
|
|||
case PCI_BASE_ADDRESS_MEM_TYPE_32:
|
||||
break;
|
||||
case PCI_BASE_ADDRESS_MEM_TYPE_1M:
|
||||
dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
|
||||
/* 1M mem BAR treated as 32-bit BAR */
|
||||
break;
|
||||
case PCI_BASE_ADDRESS_MEM_TYPE_64:
|
||||
flags |= IORESOURCE_MEM_64;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&dev->dev,
|
||||
"mem unknown type %x treated as 32-bit BAR\n",
|
||||
mem_type);
|
||||
/* mem unknown type treated as 32-bit BAR */
|
||||
break;
|
||||
}
|
||||
return flags;
|
||||
|
@ -173,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
u32 l, sz, mask;
|
||||
u16 orig_cmd;
|
||||
struct pci_bus_region region;
|
||||
bool bar_too_big = false, bar_disabled = false;
|
||||
|
||||
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
|
||||
|
||||
/* No printks while decoding is disabled! */
|
||||
if (!dev->mmio_always_on) {
|
||||
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
|
||||
pci_write_config_word(dev, PCI_COMMAND,
|
||||
|
@ -240,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
goto fail;
|
||||
|
||||
if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
|
||||
dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
|
||||
pos);
|
||||
bar_too_big = true;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -252,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
region.start = 0;
|
||||
region.end = sz64;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
bar_disabled = true;
|
||||
} else {
|
||||
region.start = l64;
|
||||
region.end = l64 + sz64;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
|
||||
pos, res);
|
||||
}
|
||||
} else {
|
||||
sz = pci_size(l, sz, mask);
|
||||
|
@ -268,18 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
region.start = l;
|
||||
region.end = l + sz;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
|
||||
}
|
||||
|
||||
out:
|
||||
goto out;
|
||||
|
||||
|
||||
fail:
|
||||
res->flags = 0;
|
||||
out:
|
||||
if (!dev->mmio_always_on)
|
||||
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
|
||||
|
||||
if (bar_too_big)
|
||||
dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
|
||||
if (res->flags && !bar_disabled)
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
|
||||
|
||||
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
|
||||
fail:
|
||||
res->flags = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
|
||||
|
|
Loading…
Reference in New Issue