IOMMU Fixes for Linux v4.17-rc4
Fixes come with: * Fix for compile warning in AMD IOMMU driver with irq remapping disabled * Fix for VT-d interrupt remapping and invalidation size (caused a BUG_ON when trying to invalidate more than 4GB) * Build fix and a regression fix for broken graphics with old DTS for the rockchip iommu driver * A revert in PCI window reservation code which fixes a regression with VFIO. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJa7s0XAAoJECvwRC2XARrj5bAP/RuP5Y+R67+pT4HfWb2gthJN pHwzZL90EG4DU1b5rdzaElWHXtJglqYHaH4QUnuwh/JwLhrOV2goN3EfzYKNfcHF voEzuM5OCP8OX+j6hLvg+Lroq6PktrnKpKlVpQ6CMK4pPTxv/ig72BdQ3iaAsg4y DUtDCJeG0pGSOuK9HBjRhvQtk77tT26Y0nkyDTev1Zk+1kW0yxeEvWPEXOo+rbVQ ZvDUksAiK7iLRTejm+tR/xC8lSs8Tj2o05HTEhfCMTMcChpKeSOunq4TyVMzWDVv xss9dB+7SNxZtKp6Ek+ORMgBpGlP4kKTgeWVLUVHW/3NkQGMeKzrYX8d7rXHcn1m aPNTB2xNcjTV0x8zEsuBCht2aMW4vnxhx0WwqnXxBVGs9X0hwFNeMAXIuzKdZJjo FuCzYpdBooYKyBbL8j7lxBBVGHKwh7DMVw1LDAgCwq14qTXcGA0hL41uCpjsB1Z+ PJHsso5d+7NqXzqQ/h4Hp4gEgIGluKcXtR7M3toriXUW7b4BatdU62CvFL93Wu4S qYV/ShnTVrvEBMGEoM2QHvqnD0zDIsMhVLK5u386nmQRmfv3yj8gN/f/QxecLW3v r5UOMSjIGLv655g4RaVQtG44hTXz7HHuUJIxFKxU7ExufAGkkZLG3k+seokQdeex 3I3I2xnmRwrdSeWcR5tv =RGxK -----END PGP SIGNATURE----- Merge tag 'iommu-fixes-v4.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu Pull iommu fixes from Joerg Roedel: - fix a compile warning in the AMD IOMMU driver with irq remapping disabled - fix for VT-d interrupt remapping and invalidation size (caused a BUG_ON when trying to invalidate more than 4GB) - build fix and a regression fix for broken graphics with old DTS for the rockchip iommu driver - a revert in the PCI window reservation code which fixes a regression with VFIO. * tag 'iommu-fixes-v4.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu: rockchip: fix building without CONFIG_OF iommu/vt-d: Use WARN_ON_ONCE instead of BUG_ON in qi_flush_dev_iotlb() iommu/vt-d: fix shift-out-of-bounds in bug checking iommu/dma: Move PCI window region reservation back into dma specific path. iommu/rockchip: Make clock handling optional iommu/amd: Hide unused iommu_table_lock iommu/vt-d: Fix usage of force parameter in intel_ir_reconfigure_irte()
This commit is contained in:
Коммит
772d4f84c6
|
@ -83,7 +83,6 @@
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(amd_iommu_devtable_lock);
|
static DEFINE_SPINLOCK(amd_iommu_devtable_lock);
|
||||||
static DEFINE_SPINLOCK(pd_bitmap_lock);
|
static DEFINE_SPINLOCK(pd_bitmap_lock);
|
||||||
static DEFINE_SPINLOCK(iommu_table_lock);
|
|
||||||
|
|
||||||
/* List of all available dev_data structures */
|
/* List of all available dev_data structures */
|
||||||
static LLIST_HEAD(dev_data_list);
|
static LLIST_HEAD(dev_data_list);
|
||||||
|
@ -3562,6 +3561,7 @@ EXPORT_SYMBOL(amd_iommu_device_info);
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
static struct irq_chip amd_ir_chip;
|
static struct irq_chip amd_ir_chip;
|
||||||
|
static DEFINE_SPINLOCK(iommu_table_lock);
|
||||||
|
|
||||||
static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
|
static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
|
||||||
{
|
{
|
||||||
|
|
|
@ -167,40 +167,16 @@ EXPORT_SYMBOL(iommu_put_dma_cookie);
|
||||||
* @list: Reserved region list from iommu_get_resv_regions()
|
* @list: Reserved region list from iommu_get_resv_regions()
|
||||||
*
|
*
|
||||||
* IOMMU drivers can use this to implement their .get_resv_regions callback
|
* IOMMU drivers can use this to implement their .get_resv_regions callback
|
||||||
* for general non-IOMMU-specific reservations. Currently, this covers host
|
* for general non-IOMMU-specific reservations. Currently, this covers GICv3
|
||||||
* bridge windows for PCI devices and GICv3 ITS region reservation on ACPI
|
* ITS region reservation on ACPI based ARM platforms that may require HW MSI
|
||||||
* based ARM platforms that may require HW MSI reservation.
|
* reservation.
|
||||||
*/
|
*/
|
||||||
void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
|
void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
|
||||||
{
|
{
|
||||||
struct pci_host_bridge *bridge;
|
|
||||||
struct resource_entry *window;
|
|
||||||
|
|
||||||
if (!is_of_node(dev->iommu_fwspec->iommu_fwnode) &&
|
if (!is_of_node(dev->iommu_fwspec->iommu_fwnode))
|
||||||
iort_iommu_msi_get_resv_regions(dev, list) < 0)
|
iort_iommu_msi_get_resv_regions(dev, list);
|
||||||
return;
|
|
||||||
|
|
||||||
if (!dev_is_pci(dev))
|
|
||||||
return;
|
|
||||||
|
|
||||||
bridge = pci_find_host_bridge(to_pci_dev(dev)->bus);
|
|
||||||
resource_list_for_each_entry(window, &bridge->windows) {
|
|
||||||
struct iommu_resv_region *region;
|
|
||||||
phys_addr_t start;
|
|
||||||
size_t length;
|
|
||||||
|
|
||||||
if (resource_type(window->res) != IORESOURCE_MEM)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
start = window->res->start - window->offset;
|
|
||||||
length = window->res->end - window->res->start + 1;
|
|
||||||
region = iommu_alloc_resv_region(start, length, 0,
|
|
||||||
IOMMU_RESV_RESERVED);
|
|
||||||
if (!region)
|
|
||||||
return;
|
|
||||||
|
|
||||||
list_add_tail(®ion->list, list);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iommu_dma_get_resv_regions);
|
EXPORT_SYMBOL(iommu_dma_get_resv_regions);
|
||||||
|
|
||||||
|
@ -229,6 +205,23 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iova_reserve_pci_windows(struct pci_dev *dev,
|
||||||
|
struct iova_domain *iovad)
|
||||||
|
{
|
||||||
|
struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
|
||||||
|
struct resource_entry *window;
|
||||||
|
unsigned long lo, hi;
|
||||||
|
|
||||||
|
resource_list_for_each_entry(window, &bridge->windows) {
|
||||||
|
if (resource_type(window->res) != IORESOURCE_MEM)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
lo = iova_pfn(iovad, window->res->start - window->offset);
|
||||||
|
hi = iova_pfn(iovad, window->res->end - window->offset);
|
||||||
|
reserve_iova(iovad, lo, hi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int iova_reserve_iommu_regions(struct device *dev,
|
static int iova_reserve_iommu_regions(struct device *dev,
|
||||||
struct iommu_domain *domain)
|
struct iommu_domain *domain)
|
||||||
{
|
{
|
||||||
|
@ -238,6 +231,9 @@ static int iova_reserve_iommu_regions(struct device *dev,
|
||||||
LIST_HEAD(resv_regions);
|
LIST_HEAD(resv_regions);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
if (dev_is_pci(dev))
|
||||||
|
iova_reserve_pci_windows(to_pci_dev(dev), iovad);
|
||||||
|
|
||||||
iommu_get_resv_regions(dev, &resv_regions);
|
iommu_get_resv_regions(dev, &resv_regions);
|
||||||
list_for_each_entry(region, &resv_regions, list) {
|
list_for_each_entry(region, &resv_regions, list) {
|
||||||
unsigned long lo, hi;
|
unsigned long lo, hi;
|
||||||
|
|
|
@ -1345,7 +1345,7 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
|
||||||
struct qi_desc desc;
|
struct qi_desc desc;
|
||||||
|
|
||||||
if (mask) {
|
if (mask) {
|
||||||
BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
|
WARN_ON_ONCE(addr & ((1ULL << (VTD_PAGE_SHIFT + mask)) - 1));
|
||||||
addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1;
|
addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1;
|
||||||
desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
|
desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -1136,7 +1136,7 @@ static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force)
|
||||||
irte->dest_id = IRTE_DEST(cfg->dest_apicid);
|
irte->dest_id = IRTE_DEST(cfg->dest_apicid);
|
||||||
|
|
||||||
/* Update the hardware only if the interrupt is in remapped mode. */
|
/* Update the hardware only if the interrupt is in remapped mode. */
|
||||||
if (!force || ir_data->irq_2_iommu.mode == IRQ_REMAPPING)
|
if (force || ir_data->irq_2_iommu.mode == IRQ_REMAPPING)
|
||||||
modify_irte(&ir_data->irq_2_iommu, irte);
|
modify_irte(&ir_data->irq_2_iommu, irte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1098,7 +1098,7 @@ static int rk_iommu_of_xlate(struct device *dev,
|
||||||
data->iommu = platform_get_drvdata(iommu_dev);
|
data->iommu = platform_get_drvdata(iommu_dev);
|
||||||
dev->archdata.iommu = data;
|
dev->archdata.iommu = data;
|
||||||
|
|
||||||
of_dev_put(iommu_dev);
|
platform_device_put(iommu_dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1175,8 +1175,15 @@ static int rk_iommu_probe(struct platform_device *pdev)
|
||||||
for (i = 0; i < iommu->num_clocks; ++i)
|
for (i = 0; i < iommu->num_clocks; ++i)
|
||||||
iommu->clocks[i].id = rk_iommu_clocks[i];
|
iommu->clocks[i].id = rk_iommu_clocks[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* iommu clocks should be present for all new devices and devicetrees
|
||||||
|
* but there are older devicetrees without clocks out in the wild.
|
||||||
|
* So clocks as optional for the time being.
|
||||||
|
*/
|
||||||
err = devm_clk_bulk_get(iommu->dev, iommu->num_clocks, iommu->clocks);
|
err = devm_clk_bulk_get(iommu->dev, iommu->num_clocks, iommu->clocks);
|
||||||
if (err)
|
if (err == -ENOENT)
|
||||||
|
iommu->num_clocks = 0;
|
||||||
|
else if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = clk_bulk_prepare(iommu->num_clocks, iommu->clocks);
|
err = clk_bulk_prepare(iommu->num_clocks, iommu->clocks);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче