From bbef98ab0f019f1b0c25c1acdf1683c68933d41b Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Sun, 6 Nov 2011 10:33:10 +0800 Subject: PCI: defer enablement of SRIOV BARS All the PCI BARs of a device are enabled when the device is enabled using pci_enable_device(). This unnecessarily enables SRIOV BARs of the device. On some platforms, which do not support SRIOV as yet, the pci_enable_device() fails to enable the device if its SRIOV BARs are not allocated resources correctly. The following patch fixes the above problem. The SRIOV BARs are now enabled when IOV capability of the device is enabled in sriov_enable(). NOTE: Note, there is subtle change in the pci_enable_device() API. Any driver that depends on SRIOV BARS to be enabled in pci_enable_device() can fail. The patch has been touch tested on power and x86 platform. Tested-by: Michael Wang Signed-off-by: Ram Pai Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/pci.c') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6f45a73c6e9f..4788413f43d7 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1126,7 +1126,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev, if (atomic_add_return(1, &dev->enable_cnt) > 1) return 0; /* already enabled */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) + for (i = 0; i < PCI_ROM_RESOURCE; i++) if (dev->resource[i].flags & flags) bars |= (1 << i); -- cgit v1.2.3 From b51306c63449d7f06ffa689036ba49eb46e898b5 Mon Sep 17 00:00:00 2001 From: Ajaykumar Hotchandani Date: Mon, 12 Dec 2011 13:57:36 +0530 Subject: PCI: Set device power state to PCI_D0 for device without native PM support During test of one IB card with guest VM, found that, msi is not initialized properly. It turns out __write_msi_msg will do nothing if device current_state is not PCI_D0. And, that pci device does not have pm_cap in guest VM. There is an error in setting of power state to PCI_D0 in pci_enable_device(), but error is not returned for this. Following is code flow: pci_enable_device() --> __pci_enable_device_flags() --> do_pci_enable_device() --> pci_set_power_state() --> __pci_start_power_transition() We have following condition inside __pci_start_power_transition(): if (platform_pci_power_manageable(dev)) { error = platform_pci_set_power_state(dev, state); if (!error) pci_update_current_state(dev, state); } else { error = -ENODEV; /* Fall back to PCI_D0 if native PM is not supported */ if (!dev->pm_cap) dev->current_state = PCI_D0; } Here, from platform_pci_set_power_state(), acpi_pci_set_power_state() is getting called and that is failing with ENODEV because of following condition: if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0",&tmp))) return -ENODEV; Because of that, pci_update_current_state() is not getting called. With this patch, if device power state can not be set via platform_pci_set_power_state and that device does not have native pm support, then PCI device power state will be set to PCI_D0. -v2: This also reverts 47e9037ac16637cd7f12b8790ea7ce6680e42168, as it's not needed after this change. Acked-by: "Rafael J. Wysocki" Signed-off-by: Ajaykumar Hotchandani Signed-off-by: Yinghai Lu Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/pci/pci.c') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4788413f43d7..faccb8937706 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -664,6 +664,9 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state) error = platform_pci_set_power_state(dev, state); if (!error) pci_update_current_state(dev, state); + /* Fall back to PCI_D0 if native PM is not supported */ + if (!dev->pm_cap) + dev->current_state = PCI_D0; } else { error = -ENODEV; /* Fall back to PCI_D0 if native PM is not supported */ -- cgit v1.2.3