diff options
-rw-r--r-- | drivers/pci/quirks.c | 51 | ||||
-rw-r--r-- | include/linux/pci.h | 8 |
2 files changed, 59 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 | |||
3183 | static 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 | |||
3191 | static 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 | */ | ||
3219 | struct 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 | } | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index d8c379dba6ad..39983be7b25b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -1332,6 +1332,9 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, | |||
1332 | static inline int pci_domain_nr(struct pci_bus *bus) | 1332 | static inline int pci_domain_nr(struct pci_bus *bus) |
1333 | { return 0; } | 1333 | { return 0; } |
1334 | 1334 | ||
1335 | static inline struct pci_dev *pci_dev_get(struct pci_dev *dev) | ||
1336 | { return NULL; } | ||
1337 | |||
1335 | #define dev_is_pci(d) (false) | 1338 | #define dev_is_pci(d) (false) |
1336 | #define dev_is_pf(d) (false) | 1339 | #define dev_is_pf(d) (false) |
1337 | #define dev_num_vf(d) (0) | 1340 | #define dev_num_vf(d) (0) |
@@ -1486,9 +1489,14 @@ enum pci_fixup_pass { | |||
1486 | 1489 | ||
1487 | #ifdef CONFIG_PCI_QUIRKS | 1490 | #ifdef CONFIG_PCI_QUIRKS |
1488 | void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); | 1491 | void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); |
1492 | struct pci_dev *pci_get_dma_source(struct pci_dev *dev); | ||
1489 | #else | 1493 | #else |
1490 | static inline void pci_fixup_device(enum pci_fixup_pass pass, | 1494 | static inline void pci_fixup_device(enum pci_fixup_pass pass, |
1491 | struct pci_dev *dev) {} | 1495 | struct pci_dev *dev) {} |
1496 | static inline struct pci_dev *pci_get_dma_source(struct pci_dev *dev) | ||
1497 | { | ||
1498 | return pci_dev_get(dev); | ||
1499 | } | ||
1492 | #endif | 1500 | #endif |
1493 | 1501 | ||
1494 | void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); | 1502 | void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); |