aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-06-11 01:26:55 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-06-11 20:37:43 -0400
commit12ea6cad1c7d046e21decc18b0e2170c6794dc51 (patch)
treed72a1034cd7436c4b705e86f3cfc83dad03b3574 /drivers/pci/quirks.c
parentcfaf025112d3856637ff34a767ef785ef5cf2ca9 (diff)
PCI: add PCI DMA source ID quirk
DMA transactions are tagged with the source ID of the device making the request. Occasionally hardware screws this up and uses the source ID of a different device (often the wrong function number of a multifunction device). A specific Ricoh multifunction device is a prime example of this problem and included in this patch. Given a pci_dev, this function returns the pci_dev to use as the source ID for DMA. When hardware works correctly, this returns the input device. For the components of the Ricoh multifunction device, it returns the pci_dev for function 0. This will be used by IOMMU drivers for determining the boundaries of IOMMU groups as multiple devices using the same source ID must be contained within the same group. This can also be used by existing streaming DMA paths for the same purpose. [bhelgaas: fold in pci_dev_get() for !CONFIG_PCI] Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 2a7521677541..acd3956b44bd 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3179,3 +3179,54 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe)
3179 3179
3180 return -ENOTTY; 3180 return -ENOTTY;
3181} 3181}
3182
3183static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev)
3184{
3185 if (!PCI_FUNC(dev->devfn))
3186 return pci_dev_get(dev);
3187
3188 return pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
3189}
3190
3191static const struct pci_dev_dma_source {
3192 u16 vendor;
3193 u16 device;
3194 struct pci_dev *(*dma_source)(struct pci_dev *dev);
3195} pci_dev_dma_source[] = {
3196 /*
3197 * https://bugzilla.redhat.com/show_bug.cgi?id=605888
3198 *
3199 * Some Ricoh devices use the function 0 source ID for DMA on
3200 * other functions of a multifunction device. The DMA devices
3201 * is therefore function 0, which will have implications of the
3202 * iommu grouping of these devices.
3203 */
3204 { PCI_VENDOR_ID_RICOH, 0xe822, pci_func_0_dma_source },
3205 { PCI_VENDOR_ID_RICOH, 0xe230, pci_func_0_dma_source },
3206 { PCI_VENDOR_ID_RICOH, 0xe832, pci_func_0_dma_source },
3207 { PCI_VENDOR_ID_RICOH, 0xe476, pci_func_0_dma_source },
3208 { 0 }
3209};
3210
3211/*
3212 * IOMMUs with isolation capabilities need to be programmed with the
3213 * correct source ID of a device. In most cases, the source ID matches
3214 * the device doing the DMA, but sometimes hardware is broken and will
3215 * tag the DMA as being sourced from a different device. This function
3216 * allows that translation. Note that the reference count of the
3217 * returned device is incremented on all paths.
3218 */
3219struct pci_dev *pci_get_dma_source(struct pci_dev *dev)
3220{
3221 const struct pci_dev_dma_source *i;
3222
3223 for (i = pci_dev_dma_source; i->dma_source; i++) {
3224 if ((i->vendor == dev->vendor ||
3225 i->vendor == (u16)PCI_ANY_ID) &&
3226 (i->device == dev->device ||
3227 i->device == (u16)PCI_ANY_ID))
3228 return i->dma_source(dev);
3229 }
3230
3231 return pci_dev_get(dev);
3232}