John, Could you refresh this patch, since the file has changed locations, and make some repairs based on feedback below? attached a patch that could be possible update... - Don On 07/28/2011 05:13 PM, jharg93@xxxxxxxxx wrote:
The DMAR driver currently doesn't reserve the memory used for the IOMMU registers. On one specific combination of cards on our system, the kernel pci resource allocator was assigning a BAR to the same address as the IOMMU. When the other driver did an ioremap, suddenly the IOMMU registers were no longer valid. Signed-off-by: Jordan Hargrave<Jordan_Hargrave@xxxxxxxx> --- drivers/pci/dmar.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 12e02bf..9650b9b 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -750,6 +750,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) iommu->seq_id = iommu_allocated++; sprintf (iommu->name, "dmar%d", iommu->seq_id); + if (!request_mem_region(drhd->reg_base_addr, VTD_PAGE_SIZE, iommu->name)) { + printk(KERN_ERR "IOMMU: can't reserve memory\n"); + goto error; + } iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE); if (!iommu->reg) { printk(KERN_ERR "IOMMU: can't map the region\n");
probably want to introduce an err_release: at bottom of function that does release_mem_region(), and set map_size to VTD_PAGE_SIZE here, so it can be used in both ioremap() error checks in this function.
@@ -789,7 +793,12 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) cap_max_fault_reg_offset(iommu->cap)); map_size = VTD_PAGE_ALIGN(map_size); if (map_size> VTD_PAGE_SIZE) { + release_mem_region(drhd->reg_base_addr, VTD_PAGE_SIZE);
need to do release after iounmap() below, not before it.
iounmap(iommu->reg); + if (!request_mem_region(drhd->reg_base_addr, map_size, iommu->name)) { + printk(KERN_ERR "IOMMU: can't reserve memory\n"); + goto error; + } iommu->reg = ioremap(drhd->reg_base_addr, map_size); if (!iommu->reg) { printk(KERN_ERR "IOMMU: can't map the region\n");
this is where you need an err_release goto as well
--- drivers/iommu/dmar.c.orig 2011-09-12 14:51:11.815394493 -0400 +++ drivers/iommu/dmar.c 2011-09-12 14:58:13.994299472 -0400 @@ -745,10 +745,16 @@ int alloc_iommu(struct dmar_drhd_unit *d iommu->seq_id = iommu_allocated++; sprintf (iommu->name, "dmar%d", iommu->seq_id); - iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE); + map_size = VTD_PAGE_SIZE; + if (!request_mem_region(drhd->reg_base_addr, map_size, iommu->name)) { + printk(KERN_ERR "IOMMU: can't reserve memory\n"); + goto error; + } + + iommu->reg = ioremap(drhd->reg_base_addr, map_size); if (!iommu->reg) { printk(KERN_ERR "IOMMU: can't map the region\n"); - goto error; + goto err_release; } iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); @@ -785,10 +791,15 @@ int alloc_iommu(struct dmar_drhd_unit *d map_size = VTD_PAGE_ALIGN(map_size); if (map_size > VTD_PAGE_SIZE) { iounmap(iommu->reg); + release_mem_region(drhd->reg_base_addr, VTD_PAGE_SIZE); + if (!request_mem_region(drhd->reg_base_addr, map_size, iommu->name)) { + printk(KERN_ERR "IOMMU: can't reserve memory\n"); + goto error; + } iommu->reg = ioremap(drhd->reg_base_addr, map_size); if (!iommu->reg) { printk(KERN_ERR "IOMMU: can't map the region\n"); - goto error; + goto err_release; } } @@ -807,6 +818,8 @@ int alloc_iommu(struct dmar_drhd_unit *d err_unmap: iounmap(iommu->reg); + err_release: + release_mem_region(drhd->reg_base_addr, map_size); error: kfree(iommu); return -1;