Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d681f120 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'x86-urgent-for-linus' of...

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86/amd-iommu: Fix boot crash with hidden PCI devices
  x86/amd-iommu: Use only per-device dma_ops
  x86/amd-iommu: Fix 3 possible endless loops
parents 6715a52a 26018874
Loading
Loading
Loading
Loading
+45 −3
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@
#include <asm/proto.h>
#include <asm/proto.h>
#include <asm/iommu.h>
#include <asm/iommu.h>
#include <asm/gart.h>
#include <asm/gart.h>
#include <asm/dma.h>
#include <asm/amd_iommu_proto.h>
#include <asm/amd_iommu_proto.h>
#include <asm/amd_iommu_types.h>
#include <asm/amd_iommu_types.h>
#include <asm/amd_iommu.h>
#include <asm/amd_iommu.h>
@@ -154,6 +155,10 @@ static int iommu_init_device(struct device *dev)
	pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
	pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
	if (pdev)
	if (pdev)
		dev_data->alias = &pdev->dev;
		dev_data->alias = &pdev->dev;
	else {
		kfree(dev_data);
		return -ENOTSUPP;
	}


	atomic_set(&dev_data->bind, 0);
	atomic_set(&dev_data->bind, 0);


@@ -163,6 +168,20 @@ static int iommu_init_device(struct device *dev)
	return 0;
	return 0;
}
}


static void iommu_ignore_device(struct device *dev)
{
	u16 devid, alias;

	devid = get_device_id(dev);
	alias = amd_iommu_alias_table[devid];

	memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
	memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry));

	amd_iommu_rlookup_table[devid] = NULL;
	amd_iommu_rlookup_table[alias] = NULL;
}

static void iommu_uninit_device(struct device *dev)
static void iommu_uninit_device(struct device *dev)
{
{
	kfree(dev->archdata.iommu);
	kfree(dev->archdata.iommu);
@@ -192,7 +211,9 @@ int __init amd_iommu_init_devices(void)
			continue;
			continue;


		ret = iommu_init_device(&pdev->dev);
		ret = iommu_init_device(&pdev->dev);
		if (ret)
		if (ret == -ENOTSUPP)
			iommu_ignore_device(&pdev->dev);
		else if (ret)
			goto out_free;
			goto out_free;
	}
	}


@@ -2383,6 +2404,23 @@ static struct dma_map_ops amd_iommu_dma_ops = {
	.dma_supported = amd_iommu_dma_supported,
	.dma_supported = amd_iommu_dma_supported,
};
};


static unsigned device_dma_ops_init(void)
{
	struct pci_dev *pdev = NULL;
	unsigned unhandled = 0;

	for_each_pci_dev(pdev) {
		if (!check_device(&pdev->dev)) {
			unhandled += 1;
			continue;
		}

		pdev->dev.archdata.dma_ops = &amd_iommu_dma_ops;
	}

	return unhandled;
}

/*
/*
 * The function which clues the AMD IOMMU driver into dma_ops.
 * The function which clues the AMD IOMMU driver into dma_ops.
 */
 */
@@ -2395,7 +2433,7 @@ void __init amd_iommu_init_api(void)
int __init amd_iommu_init_dma_ops(void)
int __init amd_iommu_init_dma_ops(void)
{
{
	struct amd_iommu *iommu;
	struct amd_iommu *iommu;
	int ret;
	int ret, unhandled;


	/*
	/*
	 * first allocate a default protection domain for every IOMMU we
	 * first allocate a default protection domain for every IOMMU we
@@ -2421,7 +2459,11 @@ int __init amd_iommu_init_dma_ops(void)
	swiotlb = 0;
	swiotlb = 0;


	/* Make the driver finally visible to the drivers */
	/* Make the driver finally visible to the drivers */
	dma_ops = &amd_iommu_dma_ops;
	unhandled = device_dma_ops_init();
	if (unhandled && max_pfn > MAX_DMA32_PFN) {
		/* There are unhandled devices - initialize swiotlb for them */
		swiotlb = 1;
	}


	amd_iommu_stats_init();
	amd_iommu_stats_init();


+4 −4
Original line number Original line Diff line number Diff line
@@ -731,8 +731,8 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
{
{
	u8 *p = (u8 *)h;
	u8 *p = (u8 *)h;
	u8 *end = p, flags = 0;
	u8 *end = p, flags = 0;
	u16 dev_i, devid = 0, devid_start = 0, devid_to = 0;
	u16 devid = 0, devid_start = 0, devid_to = 0;
	u32 ext_flags = 0;
	u32 dev_i, ext_flags = 0;
	bool alias = false;
	bool alias = false;
	struct ivhd_entry *e;
	struct ivhd_entry *e;


@@ -887,7 +887,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
/* Initializes the device->iommu mapping for the driver */
/* Initializes the device->iommu mapping for the driver */
static int __init init_iommu_devices(struct amd_iommu *iommu)
static int __init init_iommu_devices(struct amd_iommu *iommu)
{
{
	u16 i;
	u32 i;


	for (i = iommu->first_device; i <= iommu->last_device; ++i)
	for (i = iommu->first_device; i <= iommu->last_device; ++i)
		set_iommu_for_device(iommu, i);
		set_iommu_for_device(iommu, i);
@@ -1177,7 +1177,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table)
 */
 */
static void init_device_table(void)
static void init_device_table(void)
{
{
	u16 devid;
	u32 devid;


	for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
	for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
		set_dev_entry_bit(devid, DEV_ENTRY_VALID);
		set_dev_entry_bit(devid, DEV_ENTRY_VALID);