summaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-06-27 18:39:54 -0400
committerBjorn Helgaas <bhelgaas@google.com>2013-07-25 14:27:01 -0400
commit83db7e0bdb70a9bb93cd000fefc3fbac3394f516 (patch)
treeada06647d4b4e5577f7a6b4642256e1dcd988f83 /drivers/pci/pci.c
parent0a67119fce8e0246ce7c448e3db12afd57857ac0 (diff)
PCI: Differentiate ACS controllable from enabled
We currently misinterpret that in order for an ACS feature to be enabled it must be set in the control field. In reality, this means that the feature is not only enabled, but controllable. Many of the ACS capability bits are not required if the device behaves by default in the way specified when both the capability and control bit are set and does not support or allow the alternate mode. We therefore need to check the capabilities and mask out flags that are enabled but not controllable. Egress control seems to be the only flag which is purely optional. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Donald Dutile <ddutile@redhat.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3c1ff63aa56d..a599a6bbdf37 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2362,12 +2362,20 @@ void pci_enable_acs(struct pci_dev *dev)
2362static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) 2362static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags)
2363{ 2363{
2364 int pos; 2364 int pos;
2365 u16 ctrl; 2365 u16 cap, ctrl;
2366 2366
2367 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); 2367 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS);
2368 if (!pos) 2368 if (!pos)
2369 return false; 2369 return false;
2370 2370
2371 /*
2372 * Except for egress control, capabilities are either required
2373 * or only required if controllable. Features missing from the
2374 * capability field can therefore be assumed as hard-wired enabled.
2375 */
2376 pci_read_config_word(pdev, pos + PCI_ACS_CAP, &cap);
2377 acs_flags &= (cap | PCI_ACS_EC);
2378
2371 pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); 2379 pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl);
2372 return (ctrl & acs_flags) == acs_flags; 2380 return (ctrl & acs_flags) == acs_flags;
2373} 2381}
@@ -2442,9 +2450,6 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)
2442 if (!pdev->multifunction) 2450 if (!pdev->multifunction)
2443 break; 2451 break;
2444 2452
2445 acs_flags &= (PCI_ACS_RR | PCI_ACS_CR |
2446 PCI_ACS_EC | PCI_ACS_DT);
2447
2448 return pci_acs_flags_enabled(pdev, acs_flags); 2453 return pci_acs_flags_enabled(pdev, acs_flags);
2449 } 2454 }
2450 2455