Comment 30 for bug 894070

Revision history for this message
In , James (james-redhat-bugs) wrote :

Just in case anybody else is in a hurry and needs a workaround, here's a patch (against 2.6.35-rc5) that kludges all the DMAR mappings to point to the first device. Tested with Cardbus (a USB controller) and Firewire, but don't be surprised if it glues your cat to the carpet or something.

--- a/drivers/pci/intel-iommu.c 2010-07-13 07:55:33.000000000 +1000
+++ b/drivers/pci/intel-iommu.c 2010-08-03 22:19:09.000000000 +1000
@@ -2560,10 +2560,12 @@
  return 0;
 }

+struct pci_dev *ricohdev = 0;
+
 static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
          size_t size, int dir, u64 dma_mask)
 {
- struct pci_dev *pdev = to_pci_dev(hwdev);
+ struct pci_dev *tmp, *pdev = to_pci_dev(hwdev);
  struct dmar_domain *domain;
  phys_addr_t start_paddr;
  struct iova *iova;
@@ -2574,6 +2576,17 @@

  BUG_ON(dir == DMA_NONE);

+ tmp = (pdev->vendor==0x1180) ? pdev : pdev->bus->self;
+ if (tmp && tmp->vendor==0x1180 &&
+ (tmp->device==0xe822 ||
+ tmp->device==0xe230 ||
+ tmp->device==0xe832 ||
+ tmp->device==0xe476)) {
+ if (!ricohdev)
+ ricohdev = pci_get_domain_bus_and_slot(0, tmp->bus->number, tmp->devfn & ~7);
+ pdev = ricohdev;
+ }
+
  if (iommu_no_mapping(hwdev))
   return paddr;

@@ -2716,7 +2729,7 @@
         size_t size, enum dma_data_direction dir,
         struct dma_attrs *attrs)
 {
- struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_dev *tmp, *pdev = to_pci_dev(dev);
  struct dmar_domain *domain;
  unsigned long start_pfn, last_pfn;
  struct iova *iova;
@@ -2724,6 +2737,15 @@

  if (iommu_no_mapping(dev))
   return;
+
+ tmp = (pdev->vendor==0x1180) ? pdev : pdev->bus->self;
+ if (tmp && tmp->vendor==0x1180 &&
+ (tmp->device==0xe822 ||
+ tmp->device==0xe230 ||
+ tmp->device==0xe832 ||
+ tmp->device==0xe476)) {
+ pdev = ricohdev;
+ }

  domain = find_domain(pdev);
  BUG_ON(!domain);