From eecbad7d0306b9ee4f621517052913d1adaea753 Mon Sep 17 00:00:00 2001 From: Andreea-Cristina Bernat Date: Mon, 18 Aug 2014 15:20:56 +0300 Subject: iommu: Replace rcu_assign_pointer() with RCU_INIT_POINTER() The use of "rcu_assign_pointer()" is NULLing out the pointer. According to RCU_INIT_POINTER()'s block comment: "1. This use of RCU_INIT_POINTER() is NULLing out the pointer" it is better to use it instead of rcu_assign_pointer() because it has a smaller overhead. The following Coccinelle semantic patch was used: @@ @@ - rcu_assign_pointer + RCU_INIT_POINTER (..., NULL) Signed-off-by: Andreea-Cristina Bernat Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iommu/dmar.c') diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 60ab474bfff3..8ed55b0a1ce4 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -247,7 +247,7 @@ int dmar_remove_dev_scope(struct dmar_pci_notify_info *info, u16 segment, for_each_active_dev_scope(devices, count, index, tmp) if (tmp == &info->dev->dev) { - rcu_assign_pointer(devices[index].dev, NULL); + RCU_INIT_POINTER(devices[index].dev, NULL); synchronize_rcu(); put_device(tmp); return 1; -- cgit From 57384592c43375d2c9a14d82aebbdc95fdda9e9d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 2 Oct 2014 11:50:25 +0200 Subject: iommu/vt-d: Store bus information in RMRR PCI device path This will be used later to match broken RMRR entries. Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/iommu/dmar.c') diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 8ed55b0a1ce4..68da1ab0f2cd 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -155,6 +155,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) if (event == BUS_NOTIFY_ADD_DEVICE) { for (tmp = dev; tmp; tmp = tmp->bus->self) { level--; + info->path[level].bus = tmp->bus->number; info->path[level].device = PCI_SLOT(tmp->devfn); info->path[level].function = PCI_FUNC(tmp->devfn); if (pci_is_root_bus(tmp->bus)) -- cgit From 80f7b3d1b1f4ec6c80fa3b40c7c9a419e28b0897 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 22 Sep 2014 16:30:22 +0200 Subject: iommu/vt-d: Work around broken RMRR firmware entries The VT-d specification states that an RMRR entry in the DMAR table needs to specify the full path to the device. This is also how newer Linux kernels implement it. Unfortunatly older drivers just match for the target device and not the full path to the device, so that BIOS vendors implement that behavior into their BIOSes to make them work with older Linux kernels. But those RMRR entries break on newer Linux kernels. Work around this issue by adding a fall-back into the RMRR matching code to match those old RMRR entries too. Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers/iommu/dmar.c') diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 68da1ab0f2cd..b3774ef3f255 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -178,17 +178,33 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info *info, int bus, int i; if (info->bus != bus) - return false; + goto fallback; if (info->level != count) - return false; + goto fallback; for (i = 0; i < count; i++) { if (path[i].device != info->path[i].device || path[i].function != info->path[i].function) - return false; + goto fallback; } return true; + +fallback: + + if (count != 1) + return false; + + i = info->level - 1; + if (bus == info->path[i].bus && + path[0].device == info->path[i].device && + path[0].function == info->path[i].function) { + pr_info(FW_BUG "RMRR entry for device %02x:%02x.%x is broken - applying workaround\n", + bus, path[0].device, path[0].function); + return true; + } + + return false; } /* Return: > 0 if match found, 0 if no match found, < 0 if error happens */ -- cgit