x86_64: reserve TCEs with the same address as MEM regions

This works around a bug where DMAs that have the same addresses as
some MEM regions do not go through. Not clear yet if this is due to a
mis-configuration or something deeper.

[akpm@linux-foundation.org: coding style fixlet]
Signed-off-by: Muli Ben-Yehuda <muli@il.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Muli Ben-Yehuda 2007-07-21 17:10:58 +02:00 коммит произвёл Linus Torvalds
Родитель ddbd41b4e7
Коммит 07877cf6fd
1 изменённых файлов: 67 добавлений и 0 удалений

Просмотреть файл

@ -1536,3 +1536,70 @@ static int __init calgary_parse_options(char *p)
return 1;
}
__setup("calgary=", calgary_parse_options);
static void __init calgary_fixup_one_tce_space(struct pci_dev *dev)
{
struct iommu_table *tbl;
unsigned int npages;
int i;
tbl = dev->sysdata;
for (i = 0; i < 4; i++) {
struct resource *r = &dev->resource[PCI_BRIDGE_RESOURCES + i];
/* Don't give out TCEs that map MEM resources */
if (!(r->flags & IORESOURCE_MEM))
continue;
/* 0-based? we reserve the whole 1st MB anyway */
if (!r->start)
continue;
/* cover the whole region */
npages = (r->end - r->start) >> PAGE_SHIFT;
npages++;
printk(KERN_DEBUG "Calg: dev %p [%x] tbl %p reserving "
"0x%Lx-0x%Lx [0x%x pages]\n", dev, dev->bus->number,
tbl, r->start, r->end, npages);
iommu_range_reserve(tbl, r->start, npages);
}
}
static int __init calgary_fixup_tce_spaces(void)
{
struct pci_dev *dev = NULL;
void *tce_space;
if (no_iommu || swiotlb || !calgary_detected)
return -ENODEV;
printk(KERN_DEBUG "Calgary: fixing tce spaces\n");
do {
dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_ANY_ID, dev);
if (!dev)
break;
if (!is_cal_pci_dev(dev->device))
continue;
if (!translate_phb(dev))
continue;
tce_space = bus_info[dev->bus->number].tce_space;
if (!tce_space)
continue;
calgary_fixup_one_tce_space(dev);
} while (1);
return 0;
}
/*
* We need to be call after pcibios_assign_resources (fs_initcall level)
* and before device_initcall.
*/
rootfs_initcall(calgary_fixup_tce_spaces);