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

Commit 6a6aa2b7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

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

* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86/amd-iommu: Fix rounding-bug in __unmap_single
  x86/amd-iommu: Work around S3 BIOS bug
  x86/amd-iommu: Set iommu configuration flags in enable-loop
  x86, setup: Fix earlyprintk=serial,0x3f8,115200
  x86, setup: Fix earlyprintk=serial,ttyS0,115200
parents f0619343 7329cf02
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -58,7 +58,19 @@ static void parse_earlyprintk(void)
		if (arg[pos] == ',')
			pos++;

		if (!strncmp(arg, "ttyS", 4)) {
		/*
		 * make sure we have
		 *	"serial,0x3f8,115200"
		 *	"serial,ttyS0,115200"
		 *	"ttyS0,115200"
		 */
		if (pos == 7 && !strncmp(arg + pos, "0x", 2)) {
			port = simple_strtoull(arg + pos, &e, 16);
			if (port == 0 || arg + pos == e)
				port = DEFAULT_SERIAL_PORT;
			else
				pos = e - arg;
		} else if (!strncmp(arg + pos, "ttyS", 4)) {
			static const int bases[] = { 0x3f8, 0x2f8 };
			int idx = 0;

+6 −0
Original line number Diff line number Diff line
@@ -38,4 +38,10 @@ static inline void amd_iommu_stats_init(void) { }

#endif /* !CONFIG_AMD_IOMMU_STATS */

static inline bool is_rd890_iommu(struct pci_dev *pdev)
{
	return (pdev->vendor == PCI_VENDOR_ID_ATI) &&
	       (pdev->device == PCI_DEVICE_ID_RD890_IOMMU);
}

#endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
+12 −0
Original line number Diff line number Diff line
@@ -368,6 +368,9 @@ struct amd_iommu {
	/* capabilities of that IOMMU read from ACPI */
	u32 cap;

	/* flags read from acpi table */
	u8 acpi_flags;

	/*
	 * Capability pointer. There could be more than one IOMMU per PCI
	 * device function if there are more than one AMD IOMMU capability
@@ -411,6 +414,15 @@ struct amd_iommu {

	/* default dma_ops domain for that IOMMU */
	struct dma_ops_domain *default_dom;

	/*
	 * This array is required to work around a potential BIOS bug.
	 * The BIOS may miss to restore parts of the PCI configuration
	 * space when the system resumes from S3. The result is that the
	 * IOMMU does not execute commands anymore which leads to system
	 * failure.
	 */
	u32 cache_cfg[4];
};

/*
+3 −1
Original line number Diff line number Diff line
@@ -1953,6 +1953,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
			   size_t size,
			   int dir)
{
	dma_addr_t flush_addr;
	dma_addr_t i, start;
	unsigned int pages;

@@ -1960,6 +1961,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
	    (dma_addr + size > dma_dom->aperture_size))
		return;

	flush_addr = dma_addr;
	pages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
	dma_addr &= PAGE_MASK;
	start = dma_addr;
@@ -1974,7 +1976,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
	dma_ops_free_addresses(dma_dom, dma_addr, pages);

	if (amd_iommu_unmap_flush || dma_dom->need_flush) {
		iommu_flush_pages(&dma_dom->domain, dma_addr, size);
		iommu_flush_pages(&dma_dom->domain, flush_addr, size);
		dma_dom->need_flush = false;
	}
}
+45 −22
Original line number Diff line number Diff line
@@ -632,6 +632,13 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu)
	iommu->last_device = calc_devid(MMIO_GET_BUS(range),
					MMIO_GET_LD(range));
	iommu->evt_msi_num = MMIO_MSI_NUM(misc);

	if (is_rd890_iommu(iommu->dev)) {
		pci_read_config_dword(iommu->dev, 0xf0, &iommu->cache_cfg[0]);
		pci_read_config_dword(iommu->dev, 0xf4, &iommu->cache_cfg[1]);
		pci_read_config_dword(iommu->dev, 0xf8, &iommu->cache_cfg[2]);
		pci_read_config_dword(iommu->dev, 0xfc, &iommu->cache_cfg[3]);
	}
}

/*
@@ -649,29 +656,9 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
	struct ivhd_entry *e;

	/*
	 * First set the recommended feature enable bits from ACPI
	 * into the IOMMU control registers
	 * First save the recommended feature enable bits from ACPI
	 */
	h->flags & IVHD_FLAG_HT_TUN_EN_MASK ?
		iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
		iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);

	h->flags & IVHD_FLAG_PASSPW_EN_MASK ?
		iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
		iommu_feature_disable(iommu, CONTROL_PASSPW_EN);

	h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
		iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
		iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);

	h->flags & IVHD_FLAG_ISOC_EN_MASK ?
		iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
		iommu_feature_disable(iommu, CONTROL_ISOC_EN);

	/*
	 * make IOMMU memory accesses cache coherent
	 */
	iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
	iommu->acpi_flags = h->flags;

	/*
	 * Done. Now parse the device entries
@@ -1116,6 +1103,40 @@ static void init_device_table(void)
	}
}

static void iommu_init_flags(struct amd_iommu *iommu)
{
	iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ?
		iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
		iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);

	iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ?
		iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
		iommu_feature_disable(iommu, CONTROL_PASSPW_EN);

	iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
		iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
		iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);

	iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ?
		iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
		iommu_feature_disable(iommu, CONTROL_ISOC_EN);

	/*
	 * make IOMMU memory accesses cache coherent
	 */
	iommu_feature_enable(iommu, CONTROL_COHERENT_EN);
}

static void iommu_apply_quirks(struct amd_iommu *iommu)
{
	if (is_rd890_iommu(iommu->dev)) {
		pci_write_config_dword(iommu->dev, 0xf0, iommu->cache_cfg[0]);
		pci_write_config_dword(iommu->dev, 0xf4, iommu->cache_cfg[1]);
		pci_write_config_dword(iommu->dev, 0xf8, iommu->cache_cfg[2]);
		pci_write_config_dword(iommu->dev, 0xfc, iommu->cache_cfg[3]);
	}
}

/*
 * This function finally enables all IOMMUs found in the system after
 * they have been initialized
@@ -1126,6 +1147,8 @@ static void enable_iommus(void)

	for_each_iommu(iommu) {
		iommu_disable(iommu);
		iommu_apply_quirks(iommu);
		iommu_init_flags(iommu);
		iommu_set_device_table(iommu);
		iommu_enable_command_buffer(iommu);
		iommu_enable_event_buffer(iommu);
Loading