PCI: read current power state at enable time
authorJesse Barnes <jbarnes@virtuousgeek.org>
Fri, 5 Nov 2010 19:16:36 +0000 (15:16 -0400)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Thu, 11 Nov 2010 17:38:14 +0000 (09:38 -0800)
When we enable a PCI device, we avoid doing a lot of the initial setup
work if the device's enable count is non-zero.  If we don't fetch the
power state though, we may later fail to set up MSI due to the unknown
status.  So pick it up before we short circuit the rest due to a
pre-existing enable or mismatched enable/disable pair (as happens with
VGA devices, which are special in a special way).

Tested-by: Jesse Brandeburg <jesse.brandeburg@gmail.com>
Reported-by: Dave Airlie <airlied@linux.ie>
Tested-by: Dave Airlie <airlied@linux.ie>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/pci/pci.c

index e98c8104297b6c25eb130b01af6c8f00f14008de..710c8a29be0d5b8028eafb239bde42ae5d5934b6 100644 (file)
@@ -1007,6 +1007,18 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
        int err;
        int i, bars = 0;
 
+       /*
+        * Power state could be unknown at this point, either due to a fresh
+        * boot or a device removal call.  So get the current power state
+        * so that things like MSI message writing will behave as expected
+        * (e.g. if the device really is in D0 at enable time).
+        */
+       if (dev->pm_cap) {
+               u16 pmcsr;
+               pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
+               dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
+       }
+
        if (atomic_add_return(1, &dev->enable_cnt) > 1)
                return 0;               /* already enabled */