You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'pci/resource-mmap' into next
* pci/resource-mmap: ia64: Use generic pci_mmap_resource_range() ia64: Remove redundant checks for WC in pci_mmap_page_range() ia64: Remove redundant valid_mmap_phys_addr_range() from pci_mmap_page_range() PCI: Add I/O BAR support to generic pci_mmap_resource_range() x86/PCI: Use generic pci_mmap_resource_range() unicore32/PCI: Use generic pci_mmap_resource_range() sh/PCI: Use generic pci_mmap_resource_range() parisc: Use generic pci_mmap_resource_range() mn10300/PCI: Use generic pci_mmap_resource_range() MIPS: PCI: Use generic pci_mmap_resource_range() cris/PCI: Use generic pci_mmap_resource_range() ARM/PCI: Use generic pci_mmap_resource_range() PCI: Add pci_mmap_resource_range() and use it for ARM64 PCI: Add BAR index argument to pci_mmap_page_range() PCI: Use BAR index in sysfs attr->private instead of resource pointer PCI: Add arch_can_pci_mmap_io() on architectures which can mmap() I/O space PCI: Move multiple declarations of pci_mmap_page_range() to <linux/pci.h> PCI: Add arch_can_pci_mmap_wc() macro xtensa/PCI: Do not mmap PCI BARs to userspace as write-through PCI: Only allow WC mmap on prefetchable resources PCI: Fix another sanity check bug in /proc/pci mmap PCI: Fix pci_mmap_fits() for HAVE_PCI_RESOURCE_TO_USER platforms
This commit is contained in:
@@ -113,9 +113,18 @@ Supporting PCI access on new platforms
|
||||
--------------------------------------
|
||||
|
||||
In order to support PCI resource mapping as described above, Linux platform
|
||||
code must define HAVE_PCI_MMAP and provide a pci_mmap_page_range function.
|
||||
Platforms are free to only support subsets of the mmap functionality, but
|
||||
useful return codes should be provided.
|
||||
code should ideally define ARCH_GENERIC_PCI_MMAP_RESOURCE and use the generic
|
||||
implementation of that functionality. To support the historical interface of
|
||||
mmap() through files in /proc/bus/pci, platforms may also set HAVE_PCI_MMAP.
|
||||
|
||||
Alternatively, platforms which set HAVE_PCI_MMAP may provide their own
|
||||
implementation of pci_mmap_page_range() instead of defining
|
||||
ARCH_GENERIC_PCI_MMAP_RESOURCE.
|
||||
|
||||
Platforms which support write-combining maps of PCI resources must define
|
||||
arch_can_pci_mmap_wc() which shall evaluate to non-zero at runtime when
|
||||
write-combining is permitted. Platforms which support maps of I/O resources
|
||||
define arch_can_pci_mmap_io() similarly.
|
||||
|
||||
Legacy resources are protected by the HAVE_PCI_LEGACY define. Platforms
|
||||
wishing to support legacy functionality should define it and provide
|
||||
|
||||
@@ -29,8 +29,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
|
||||
#define PCI_DMA_BUS_IS_PHYS (1)
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
#define ARCH_GENERIC_PCI_MMAP_RESOURCE
|
||||
|
||||
static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
|
||||
{
|
||||
|
||||
@@ -597,25 +597,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||
return start;
|
||||
}
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
if (mmap_state == pci_mmap_io)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Mark this as IO
|
||||
*/
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
|
||||
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init pci_map_io_early(unsigned long pfn)
|
||||
{
|
||||
struct map_desc pci_io_desc = {
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
*/
|
||||
#define PCI_DMA_BUS_IS_PHYS (0)
|
||||
|
||||
#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
|
||||
|
||||
extern int isa_dma_bridge_buggy;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
@@ -14,28 +14,6 @@ void pcibios_set_master(struct pci_dev *dev)
|
||||
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
|
||||
}
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
unsigned long prot;
|
||||
|
||||
/* Leave vm_pgoff as-is, the PCI space address is the physical
|
||||
* address on this platform.
|
||||
*/
|
||||
prot = pgprot_val(vma->vm_page_prot);
|
||||
vma->vm_page_prot = __pgprot(prot);
|
||||
|
||||
/* Write-combine setting is ignored, it is changed via the mtrr
|
||||
* interfaces on this platform.
|
||||
*/
|
||||
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
resource_size_t
|
||||
pcibios_align_resource(void *data, const struct resource *res,
|
||||
resource_size_t size, resource_size_t align)
|
||||
|
||||
@@ -42,9 +42,7 @@ struct pci_dev;
|
||||
#define PCI_DMA_BUS_IS_PHYS (1)
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
|
||||
#define ARCH_GENERIC_PCI_MMAP_RESOURCE
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
||||
@@ -51,8 +51,9 @@ extern unsigned long ia64_max_iommu_merge_mask;
|
||||
#define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL)
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
#define ARCH_GENERIC_PCI_MMAP_RESOURCE
|
||||
#define arch_can_pci_mmap_wc() 1
|
||||
|
||||
#define HAVE_PCI_LEGACY
|
||||
extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
|
||||
struct vm_area_struct *vma,
|
||||
|
||||
@@ -418,52 +418,6 @@ pcibios_align_resource (void *data, const struct resource *res,
|
||||
return res->start;
|
||||
}
|
||||
|
||||
int
|
||||
pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
unsigned long size = vma->vm_end - vma->vm_start;
|
||||
pgprot_t prot;
|
||||
|
||||
/*
|
||||
* I/O space cannot be accessed via normal processor loads and
|
||||
* stores on this platform.
|
||||
*/
|
||||
if (mmap_state == pci_mmap_io)
|
||||
/*
|
||||
* XXX we could relax this for I/O spaces for which ACPI
|
||||
* indicates that the space is 1-to-1 mapped. But at the
|
||||
* moment, we don't support multiple PCI address spaces and
|
||||
* the legacy I/O space is not 1-to-1 mapped, so this is moot.
|
||||
*/
|
||||
return -EINVAL;
|
||||
|
||||
if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
|
||||
return -EINVAL;
|
||||
|
||||
prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
|
||||
vma->vm_page_prot);
|
||||
|
||||
/*
|
||||
* If the user requested WC, the kernel uses UC or WC for this region,
|
||||
* and the chipset supports WC, we can use WC. Otherwise, we have to
|
||||
* use the same attribute the kernel uses.
|
||||
*/
|
||||
if (write_combine &&
|
||||
((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC ||
|
||||
(pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) &&
|
||||
efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
else
|
||||
vma->vm_page_prot = prot;
|
||||
|
||||
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ia64_pci_get_legacy_mem - generic legacy mem routine
|
||||
* @bus: bus to get legacy memory base address for
|
||||
|
||||
@@ -46,12 +46,10 @@ extern int pci_domain_nr(struct pci_bus *bus);
|
||||
extern int pci_proc_domain(struct pci_bus *bus);
|
||||
|
||||
struct vm_area_struct;
|
||||
/* Map a range of PCI memory or I/O space for a device into user space */
|
||||
int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
|
||||
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
|
||||
#define HAVE_PCI_MMAP 1
|
||||
#define HAVE_PCI_MMAP 1
|
||||
#define arch_can_pci_mmap_io() 1
|
||||
|
||||
extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
|
||||
size_t count);
|
||||
|
||||
@@ -278,7 +278,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
|
||||
*
|
||||
* Returns a negative error code on failure, zero on success.
|
||||
*/
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
int pci_mmap_page_range(struct pci_dev *dev, int bar, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
resource_size_t offset =
|
||||
|
||||
@@ -110,10 +110,7 @@ extern unsigned long PCIBIOS_MIN_MEM;
|
||||
extern void pcibios_set_master(struct pci_dev *dev);
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
|
||||
#define ARCH_GENERIC_PCI_MMAP_RESOURCE
|
||||
#define HAVE_ARCH_PCI_RESOURCE_TO_USER
|
||||
|
||||
/*
|
||||
|
||||
@@ -57,27 +57,3 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
|
||||
*start = fixup_bigphys_addr(rsrc->start, size);
|
||||
*end = rsrc->start + size;
|
||||
}
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
unsigned long prot;
|
||||
|
||||
/*
|
||||
* I/O space can be accessed via normal processor loads and stores on
|
||||
* this platform but for now we elect not to do this and portable
|
||||
* drivers should not do this anyway.
|
||||
*/
|
||||
if (mmap_state == pci_mmap_io)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Ignore write-combine; for now only return uncached mappings.
|
||||
*/
|
||||
prot = pgprot_val(vma->vm_page_prot);
|
||||
prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
|
||||
vma->vm_page_prot = __pgprot(prot);
|
||||
|
||||
return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot);
|
||||
}
|
||||
|
||||
@@ -74,9 +74,7 @@ static inline int pci_controller_num(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state,
|
||||
int write_combine);
|
||||
#define ARCH_GENERIC_PCI_MMAP_RESOURCE
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
||||
@@ -210,26 +210,3 @@ void __init pcibios_resource_survey(void)
|
||||
pcibios_allocate_resources(0);
|
||||
pcibios_allocate_resources(1);
|
||||
}
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
unsigned long prot;
|
||||
|
||||
/* Leave vm_pgoff as-is, the PCI space address is the physical
|
||||
* address on this platform.
|
||||
*/
|
||||
vma->vm_flags |= VM_LOCKED;
|
||||
|
||||
prot = pgprot_val(vma->vm_page_prot);
|
||||
prot &= ~_PAGE_CACHE;
|
||||
vma->vm_page_prot = __pgprot(prot);
|
||||
|
||||
/* Write-combine setting is ignored */
|
||||
if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -200,8 +200,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
|
||||
}
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
#define ARCH_GENERIC_PCI_MMAP_RESOURCE
|
||||
|
||||
#endif /* __ASM_PARISC_PCI_H */
|
||||
|
||||
@@ -227,34 +227,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
unsigned long prot;
|
||||
|
||||
/*
|
||||
* I/O space can be accessed via normal processor loads and stores on
|
||||
* this platform but for now we elect not to do this and portable
|
||||
* drivers should not do this anyway.
|
||||
*/
|
||||
if (mmap_state == pci_mmap_io)
|
||||
return -EINVAL;
|
||||
|
||||
if (write_combine)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Ignore write-combine; for now only return uncached mappings.
|
||||
*/
|
||||
prot = pgprot_val(vma->vm_page_prot);
|
||||
prot |= _PAGE_NO_CACHE;
|
||||
vma->vm_page_prot = __pgprot(prot);
|
||||
|
||||
return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot);
|
||||
}
|
||||
|
||||
/*
|
||||
* A driver is enabling the device. We make sure that all the appropriate
|
||||
* bits are set to allow the device to operate as the driver is expecting.
|
||||
|
||||
@@ -77,12 +77,11 @@ extern int pci_domain_nr(struct pci_bus *bus);
|
||||
extern int pci_proc_domain(struct pci_bus *bus);
|
||||
|
||||
struct vm_area_struct;
|
||||
/* Map a range of PCI memory or I/O space for a device into user space */
|
||||
int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
|
||||
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
|
||||
#define HAVE_PCI_MMAP 1
|
||||
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() and it does WC */
|
||||
#define HAVE_PCI_MMAP 1
|
||||
#define arch_can_pci_mmap_io() 1
|
||||
#define arch_can_pci_mmap_wc() 1
|
||||
|
||||
extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
|
||||
size_t count);
|
||||
|
||||
@@ -521,7 +521,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
|
||||
*
|
||||
* Returns a negative error code on failure, zero on success.
|
||||
*/
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
int pci_mmap_page_range(struct pci_dev *dev, int bar,
|
||||
struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
resource_size_t offset =
|
||||
|
||||
@@ -269,27 +269,6 @@ void __ref pcibios_report_status(unsigned int status_mask, int warn)
|
||||
}
|
||||
}
|
||||
|
||||
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
{
|
||||
/*
|
||||
* I/O space can be accessed via normal processor loads and stores on
|
||||
* this platform but for now we elect not to do this and portable
|
||||
* drivers should not do this anyway.
|
||||
*/
|
||||
if (mmap_state == pci_mmap_io)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Ignore write-combine; for now only return uncached mappings.
|
||||
*/
|
||||
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
||||
|
||||
return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_GENERIC_IOMAP
|
||||
|
||||
void __iomem *__pci_ioport_map(struct pci_dev *dev,
|
||||
|
||||
@@ -66,8 +66,8 @@ extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM;
|
||||
struct pci_dev;
|
||||
|
||||
#define HAVE_PCI_MMAP
|
||||
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine);
|
||||
#define ARCH_GENERIC_PCI_MMAP_RESOURCE
|
||||
|
||||
extern void pcibios_set_master(struct pci_dev *dev);
|
||||
|
||||
/* Dynamic DMA mapping stuff.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user