Skip to content

Commit

Permalink
xtensa/PCI: Use generic pci_mmap_resource_range()
Browse files Browse the repository at this point in the history
Commit f719582 ("PCI: Add pci_mmap_resource_range() and use it for
ARM64") added this generic function with the intent of using it everywhere
and ultimately killing the old arch-specific implementations.

Remove the xtensa-specific pci_mmap_page_range() and use the generic
pci_mmap_resource_range() instead.

Xtensa can mmap I/O port space, so supply the xtensa-specific
pci_iobar_pfn() required to make that work.

Signed-off-by: David Woodhouse <[email protected]>
[bhelgaas: changelog]
Signed-off-by: Bjorn Helgaas <[email protected]>
Acked-by: Max Filippov <[email protected]>
  • Loading branch information
dwmw2 authored and Bjorn Helgaas committed Feb 28, 2018
1 parent 28f8f18 commit 46e15a2
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 89 deletions.
7 changes: 4 additions & 3 deletions arch/xtensa/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ extern struct pci_controller* pcibios_alloc_controller(void);

#define PCI_DMA_BUS_IS_PHYS (1)

/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
#define HAVE_PCI_MMAP 1
#define arch_can_pci_mmap_io() 1
/* Tell PCI code what kind of PCI resource mappings we support */
#define HAVE_PCI_MMAP 1
#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
#define arch_can_pci_mmap_io() 1

#endif /* __KERNEL__ */

Expand Down
94 changes: 8 additions & 86 deletions arch/xtensa/kernel/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
* pcibios_align_resource
* pcibios_fixup_bus
* pci_bus_add_device
* pci_mmap_page_range
*/

struct pci_controller* pci_ctrl_head;
Expand Down Expand Up @@ -258,98 +257,21 @@ pci_controller_num(struct pci_dev *dev)
#endif /* CONFIG_PROC_FS */

/*
* Platform support for /proc/bus/pci/X/Y mmap()s,
* modelled on the sparc64 implementation by Dave Miller.
* Platform support for /proc/bus/pci/X/Y mmap()s.
* -- paulus.
*/

/*
* Adjust vm_pgoff of VMA such that it is the physical page offset
* corresponding to the 32-bit pci bus offset for DEV requested by the user.
*
* Basically, the user finds the base address for his device which he wishes
* to mmap. They read the 32-bit value from the config space base register,
* add whatever PAGE_SIZE multiple offset they wish, and feed this into the
* offset parameter of mmap on /proc/bus/pci/XXX for that device.
*
* Returns negative error code on failure, zero on success.
*/
static __inline__ int
__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma)
{
struct pci_controller *pci_ctrl = (struct pci_controller*) dev->sysdata;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long io_offset = 0;
int i, res_bit;
struct pci_controller *pci_ctrl = (struct pci_controller*) pdev->sysdata;
resource_size_t ioaddr = pci_resource_start(pdev, bar);

if (pci_ctrl == 0)
return -EINVAL; /* should never happen */

/* If memory, add on the PCI bridge address offset */
if (mmap_state == pci_mmap_mem) {
res_bit = IORESOURCE_MEM;
} else {
io_offset = (unsigned long)pci_ctrl->io_space.base;
offset += io_offset;
res_bit = IORESOURCE_IO;
}

/*
* Check that the offset requested corresponds to one of the
* resources of the device.
*/
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
struct resource *rp = &dev->resource[i];
int flags = rp->flags;

/* treat ROM as memory (should be already) */
if (i == PCI_ROM_RESOURCE)
flags |= IORESOURCE_MEM;

/* Active and same type? */
if ((flags & res_bit) == 0)
continue;

/* In the range of this resource? */
if (offset < (rp->start & PAGE_MASK) || offset > rp->end)
continue;

/* found it! construct the final physical address */
if (mmap_state == pci_mmap_io)
offset += pci_ctrl->io_space.start - io_offset;
vma->vm_pgoff = offset >> PAGE_SHIFT;
return 0;
}

return -EINVAL;
}
/* Convert to an offset within this PCI controller */
ioaddr -= (unsigned long)pci_ctrl->io_space.base;

/*
* Perform the actual remap of the pages for a PCI device mapping, as
* appropriate for this architecture. The region in the process to map
* is described by vm_start and vm_end members of VMA, the base physical
* address is found in vm_pgoff.
* The pci device structure is provided so that architectures may make mapping
* decisions on a per-device or per-bus basis.
*
* Returns a negative error code on failure, zero on success.
*/
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)
{
int ret;

ret = __pci_mmap_make_offset(dev, vma, mmap_state);
if (ret < 0)
return ret;

vma->vm_page_prot = pgprot_device(vma->vm_page_prot);

ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start,vma->vm_page_prot);

return ret;
vma->vm_pgoff += (ioaddr + pci_ctrl->io_space.start) >> PAGE_SHIFT;
return 0;
}

0 comments on commit 46e15a2

Please sign in to comment.