mirror of
https://github.com/torvalds/linux.git
synced 2024-12-23 11:21:33 +00:00
5927145efd
There were only a few Pentium Pro multiprocessors systems where this errata applied. They are more than 20 years old now, and we've slowly dropped places which put the workarounds in and discouraged anyone from enabling the workaround. Get rid of it for good. Tested-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Joerg Roedel <joro@8bytes.org> Cc: Jon Mason <jdmason@kudzu.us> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Muli Ben-Yehuda <mulix@mulix.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: iommu@lists.linux-foundation.org Link: http://lkml.kernel.org/r/20180319103826.12853-2-hch@lst.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
91 lines
2.6 KiB
C
91 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Fallback functions when the main IOMMU code is not compiled in. This
|
|
code is roughly equivalent to i386. */
|
|
#include <linux/dma-direct.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/string.h>
|
|
#include <linux/gfp.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/mm.h>
|
|
|
|
#include <asm/processor.h>
|
|
#include <asm/iommu.h>
|
|
#include <asm/dma.h>
|
|
|
|
#define NOMMU_MAPPING_ERROR 0
|
|
|
|
static int
|
|
check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
|
|
{
|
|
if (hwdev && !dma_capable(hwdev, bus, size)) {
|
|
if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
|
|
printk(KERN_ERR
|
|
"nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
|
|
name, (long long)bus, size,
|
|
(long long)*hwdev->dma_mask);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
|
|
unsigned long offset, size_t size,
|
|
enum dma_data_direction dir,
|
|
unsigned long attrs)
|
|
{
|
|
dma_addr_t bus = phys_to_dma(dev, page_to_phys(page)) + offset;
|
|
WARN_ON(size == 0);
|
|
if (!check_addr("map_single", dev, bus, size))
|
|
return NOMMU_MAPPING_ERROR;
|
|
return bus;
|
|
}
|
|
|
|
/* Map a set of buffers described by scatterlist in streaming
|
|
* mode for DMA. This is the scatter-gather version of the
|
|
* above pci_map_single interface. Here the scatter gather list
|
|
* elements are each tagged with the appropriate dma address
|
|
* and length. They are obtained via sg_dma_{address,length}(SG).
|
|
*
|
|
* NOTE: An implementation may be able to use a smaller number of
|
|
* DMA address/length pairs than there are SG table elements.
|
|
* (for example via virtual mapping capabilities)
|
|
* The routine returns the number of addr/length pairs actually
|
|
* used, at most nents.
|
|
*
|
|
* Device ownership issues as mentioned above for pci_map_single are
|
|
* the same here.
|
|
*/
|
|
static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
|
|
int nents, enum dma_data_direction dir,
|
|
unsigned long attrs)
|
|
{
|
|
struct scatterlist *s;
|
|
int i;
|
|
|
|
WARN_ON(nents == 0 || sg[0].length == 0);
|
|
|
|
for_each_sg(sg, s, nents, i) {
|
|
BUG_ON(!sg_page(s));
|
|
s->dma_address = sg_phys(s);
|
|
if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
|
|
return 0;
|
|
s->dma_length = s->length;
|
|
}
|
|
return nents;
|
|
}
|
|
|
|
static int nommu_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
|
{
|
|
return dma_addr == NOMMU_MAPPING_ERROR;
|
|
}
|
|
|
|
const struct dma_map_ops nommu_dma_ops = {
|
|
.alloc = dma_generic_alloc_coherent,
|
|
.free = dma_generic_free_coherent,
|
|
.map_sg = nommu_map_sg,
|
|
.map_page = nommu_map_page,
|
|
.is_phys = 1,
|
|
.mapping_error = nommu_mapping_error,
|
|
.dma_supported = x86_dma_supported,
|
|
};
|