aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2014-06-02 18:18:48 -0400
committerBjorn Helgaas <bhelgaas@google.com>2014-06-02 18:18:48 -0400
commit0eeb4f2af5f71f64ba6362df33ddc1f218075c52 (patch)
treea5ba0181900968cda030364e18235e93f975b093 /drivers/pci
parent617b4157a5c82ab3e9509aa388bfd3d47e0e623a (diff)
parentebdb51eb7806df56221d4536a6a9702751d6df85 (diff)
Merge branch 'pci/iommu' into next
* pci/iommu: PCI: Add bridge DMA alias quirk for ASMedia and Tundra bridges PCI: Add support for PCIe-to-PCI bridge DMA alias quirks PCI: Add function 1 DMA alias quirk for Marvell devices PCI: Add function 0 DMA alias quirk for Ricoh devices PCI: Add support for DMA alias quirks PCI: Convert pci_dev_flags definitions to bit shifts PCI: Add DMA alias iterator
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/quirks.c75
-rw-r--r--drivers/pci/search.c87
2 files changed, 162 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 92e68c7747f7..d3f29dd29876 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3342,6 +3342,81 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe)
3342 return -ENOTTY; 3342 return -ENOTTY;
3343} 3343}
3344 3344
3345static void quirk_dma_func0_alias(struct pci_dev *dev)
3346{
3347 if (PCI_FUNC(dev->devfn) != 0) {
3348 dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
3349 dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
3350 }
3351}
3352
3353/*
3354 * https://bugzilla.redhat.com/show_bug.cgi?id=605888
3355 *
3356 * Some Ricoh devices use function 0 as the PCIe requester ID for DMA.
3357 */
3358DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe832, quirk_dma_func0_alias);
3359DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe476, quirk_dma_func0_alias);
3360
3361static void quirk_dma_func1_alias(struct pci_dev *dev)
3362{
3363 if (PCI_FUNC(dev->devfn) != 1) {
3364 dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 1);
3365 dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
3366 }
3367}
3368
3369/*
3370 * Marvell 88SE9123 uses function 1 as the requester ID for DMA. In some
3371 * SKUs function 1 is present and is a legacy IDE controller, in other
3372 * SKUs this function is not present, making this a ghost requester.
3373 * https://bugzilla.kernel.org/show_bug.cgi?id=42679
3374 */
3375DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9123,
3376 quirk_dma_func1_alias);
3377/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c14 */
3378DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9130,
3379 quirk_dma_func1_alias);
3380/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c47 + c57 */
3381DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9172,
3382 quirk_dma_func1_alias);
3383/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c59 */
3384DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x917a,
3385 quirk_dma_func1_alias);
3386/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c46 */
3387DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0,
3388 quirk_dma_func1_alias);
3389/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */
3390DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230,
3391 quirk_dma_func1_alias);
3392/* https://bugs.gentoo.org/show_bug.cgi?id=497630 */
3393DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JMICRON,
3394 PCI_DEVICE_ID_JMICRON_JMB388_ESD,
3395 quirk_dma_func1_alias);
3396
3397/*
3398 * A few PCIe-to-PCI bridges fail to expose a PCIe capability, resulting in
3399 * using the wrong DMA alias for the device. Some of these devices can be
3400 * used as either forward or reverse bridges, so we need to test whether the
3401 * device is operating in the correct mode. We could probably apply this
3402 * quirk to PCI_ANY_ID, but for now we'll just use known offenders. The test
3403 * is for a non-root, non-PCIe bridge where the upstream device is PCIe and
3404 * is not a PCIe-to-PCI bridge, then @pdev is actually a PCIe-to-PCI bridge.
3405 */
3406static void quirk_use_pcie_bridge_dma_alias(struct pci_dev *pdev)
3407{
3408 if (!pci_is_root_bus(pdev->bus) &&
3409 pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
3410 !pci_is_pcie(pdev) && pci_is_pcie(pdev->bus->self) &&
3411 pci_pcie_type(pdev->bus->self) != PCI_EXP_TYPE_PCI_BRIDGE)
3412 pdev->dev_flags |= PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS;
3413}
3414/* ASM1083/1085, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c46 */
3415DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ASMEDIA, 0x1080,
3416 quirk_use_pcie_bridge_dma_alias);
3417/* Tundra 8113, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c43 */
3418DECLARE_PCI_FIXUP_HEADER(0x10e3, 0x8113, quirk_use_pcie_bridge_dma_alias);
3419
3345static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev) 3420static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev)
3346{ 3421{
3347 if (!PCI_FUNC(dev->devfn)) 3422 if (!PCI_FUNC(dev->devfn))
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 8e495bda678f..0e9a00e5ca60 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -17,6 +17,93 @@ DECLARE_RWSEM(pci_bus_sem);
17EXPORT_SYMBOL_GPL(pci_bus_sem); 17EXPORT_SYMBOL_GPL(pci_bus_sem);
18 18
19/* 19/*
20 * pci_for_each_dma_alias - Iterate over DMA aliases for a device
21 * @pdev: starting downstream device
22 * @fn: function to call for each alias
23 * @data: opaque data to pass to @fn
24 *
25 * Starting @pdev, walk up the bus calling @fn for each possible alias
26 * of @pdev at the root bus.
27 */
28int pci_for_each_dma_alias(struct pci_dev *pdev,
29 int (*fn)(struct pci_dev *pdev,
30 u16 alias, void *data), void *data)
31{
32 struct pci_bus *bus;
33 int ret;
34
35 ret = fn(pdev, PCI_DEVID(pdev->bus->number, pdev->devfn), data);
36 if (ret)
37 return ret;
38
39 /*
40 * If the device is broken and uses an alias requester ID for
41 * DMA, iterate over that too.
42 */
43 if (unlikely(pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN)) {
44 ret = fn(pdev, PCI_DEVID(pdev->bus->number,
45 pdev->dma_alias_devfn), data);
46 if (ret)
47 return ret;
48 }
49
50 for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) {
51 struct pci_dev *tmp;
52
53 /* Skip virtual buses */
54 if (!bus->self)
55 continue;
56
57 tmp = bus->self;
58
59 /*
60 * PCIe-to-PCI/X bridges alias transactions from downstream
61 * devices using the subordinate bus number (PCI Express to
62 * PCI/PCI-X Bridge Spec, rev 1.0, sec 2.3). For all cases
63 * where the upstream bus is PCI/X we alias to the bridge
64 * (there are various conditions in the previous reference
65 * where the bridge may take ownership of transactions, even
66 * when the secondary interface is PCI-X).
67 */
68 if (pci_is_pcie(tmp)) {
69 switch (pci_pcie_type(tmp)) {
70 case PCI_EXP_TYPE_ROOT_PORT:
71 case PCI_EXP_TYPE_UPSTREAM:
72 case PCI_EXP_TYPE_DOWNSTREAM:
73 continue;
74 case PCI_EXP_TYPE_PCI_BRIDGE:
75 ret = fn(tmp,
76 PCI_DEVID(tmp->subordinate->number,
77 PCI_DEVFN(0, 0)), data);
78 if (ret)
79 return ret;
80 continue;
81 case PCI_EXP_TYPE_PCIE_BRIDGE:
82 ret = fn(tmp,
83 PCI_DEVID(tmp->bus->number,
84 tmp->devfn), data);
85 if (ret)
86 return ret;
87 continue;
88 }
89 } else {
90 if (tmp->dev_flags & PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS)
91 ret = fn(tmp,
92 PCI_DEVID(tmp->subordinate->number,
93 PCI_DEVFN(0, 0)), data);
94 else
95 ret = fn(tmp,
96 PCI_DEVID(tmp->bus->number,
97 tmp->devfn), data);
98 if (ret)
99 return ret;
100 }
101 }
102
103 return ret;
104}
105
106/*
20 * find the upstream PCIe-to-PCI bridge of a PCI device 107 * find the upstream PCIe-to-PCI bridge of a PCI device
21 * if the device is PCIE, return NULL 108 * if the device is PCIE, return NULL
22 * if the device isn't connected to a PCIe bridge (that is its parent is a 109 * if the device isn't connected to a PCIe bridge (that is its parent is a