Commit b274014c authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds

powerpc: add an ioremap_phb helper

Factor code shared between pci_64 and electra_cf into a ioremap_pbh helper
that follows the normal ioremap semantics, and returns a useful __iomem
pointer.  Note that it opencodes __ioremap_at as we know from the callers
the slab is available.  Switch pci_64 to also store the result as __iomem
pointer, and unmap the result using iounmap instead of force casting and
using vmalloc APIs.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: David Airlie <airlied@linux.ie>
Cc: Gao Xiang <xiang@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Laura Abbott <labbott@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Nitin Gupta <ngupta@vflare.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Paul Mackerras <paulus@ozlabs.org>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Will Deacon <will@kernel.org>
Link: http://lkml.kernel.org/r/20200414131348.444715-7-hch@lst.deSigned-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 515e5b6d
...@@ -719,6 +719,8 @@ void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size); ...@@ -719,6 +719,8 @@ void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size);
extern void iounmap(volatile void __iomem *addr); extern void iounmap(volatile void __iomem *addr);
void __iomem *ioremap_phb(phys_addr_t paddr, unsigned long size);
int early_ioremap_range(unsigned long ea, phys_addr_t pa, int early_ioremap_range(unsigned long ea, phys_addr_t pa,
unsigned long size, pgprot_t prot); unsigned long size, pgprot_t prot);
void __iomem *do_ioremap(phys_addr_t pa, phys_addr_t offset, unsigned long size, void __iomem *do_ioremap(phys_addr_t pa, phys_addr_t offset, unsigned long size,
......
...@@ -66,7 +66,7 @@ struct pci_controller { ...@@ -66,7 +66,7 @@ struct pci_controller {
void __iomem *io_base_virt; void __iomem *io_base_virt;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
void *io_base_alloc; void __iomem *io_base_alloc;
#endif #endif
resource_size_t io_base_phys; resource_size_t io_base_phys;
resource_size_t pci_io_size; resource_size_t pci_io_size;
......
...@@ -109,23 +109,46 @@ int pcibios_unmap_io_space(struct pci_bus *bus) ...@@ -109,23 +109,46 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
/* Get the host bridge */ /* Get the host bridge */
hose = pci_bus_to_host(bus); hose = pci_bus_to_host(bus);
/* Check if we have IOs allocated */
if (hose->io_base_alloc == NULL)
return 0;
pr_debug("IO unmapping for PHB %pOF\n", hose->dn); pr_debug("IO unmapping for PHB %pOF\n", hose->dn);
pr_debug(" alloc=0x%p\n", hose->io_base_alloc); pr_debug(" alloc=0x%p\n", hose->io_base_alloc);
/* This is a PHB, we fully unmap the IO area */ iounmap(hose->io_base_alloc);
vunmap(hose->io_base_alloc);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(pcibios_unmap_io_space); EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
static int pcibios_map_phb_io_space(struct pci_controller *hose) void __iomem *ioremap_phb(phys_addr_t paddr, unsigned long size)
{ {
struct vm_struct *area; struct vm_struct *area;
unsigned long addr;
WARN_ON_ONCE(paddr & ~PAGE_MASK);
WARN_ON_ONCE(size & ~PAGE_MASK);
/*
* Let's allocate some IO space for that guy. We don't pass VM_IOREMAP
* because we don't care about alignment tricks that the core does in
* that case. Maybe we should due to stupid card with incomplete
* address decoding but I'd rather not deal with those outside of the
* reserved 64K legacy region.
*/
area = __get_vm_area(size, 0, PHB_IO_BASE, PHB_IO_END);
if (!area)
return NULL;
addr = (unsigned long)area->addr;
if (ioremap_page_range(addr, addr + size, paddr,
pgprot_noncached(PAGE_KERNEL))) {
unmap_kernel_range(addr, size);
return NULL;
}
return (void __iomem *)addr;
}
EXPORT_SYMBOL_GPL(ioremap_phb);
static int pcibios_map_phb_io_space(struct pci_controller *hose)
{
unsigned long phys_page; unsigned long phys_page;
unsigned long size_page; unsigned long size_page;
unsigned long io_virt_offset; unsigned long io_virt_offset;
...@@ -146,12 +169,11 @@ static int pcibios_map_phb_io_space(struct pci_controller *hose) ...@@ -146,12 +169,11 @@ static int pcibios_map_phb_io_space(struct pci_controller *hose)
* with incomplete address decoding but I'd rather not deal with * with incomplete address decoding but I'd rather not deal with
* those outside of the reserved 64K legacy region. * those outside of the reserved 64K legacy region.
*/ */
area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END); hose->io_base_alloc = ioremap_phb(phys_page, size_page);
if (area == NULL) if (!hose->io_base_alloc)
return -ENOMEM; return -ENOMEM;
hose->io_base_alloc = area->addr; hose->io_base_virt = hose->io_base_alloc +
hose->io_base_virt = (void __iomem *)(area->addr + hose->io_base_phys - phys_page;
hose->io_base_phys - phys_page);
pr_debug("IO mapping for PHB %pOF\n", hose->dn); pr_debug("IO mapping for PHB %pOF\n", hose->dn);
pr_debug(" phys=0x%016llx, virt=0x%p (alloc=0x%p)\n", pr_debug(" phys=0x%016llx, virt=0x%p (alloc=0x%p)\n",
...@@ -159,11 +181,6 @@ static int pcibios_map_phb_io_space(struct pci_controller *hose) ...@@ -159,11 +181,6 @@ static int pcibios_map_phb_io_space(struct pci_controller *hose)
pr_debug(" size=0x%016llx (alloc=0x%016lx)\n", pr_debug(" size=0x%016llx (alloc=0x%016lx)\n",
hose->pci_io_size, size_page); hose->pci_io_size, size_page);
/* Establish the mapping */
if (__ioremap_at(phys_page, area->addr, size_page,
pgprot_noncached(PAGE_KERNEL)) == NULL)
return -ENOMEM;
/* Fixup hose IO resource */ /* Fixup hose IO resource */
io_virt_offset = pcibios_io_space_offset(hose); io_virt_offset = pcibios_io_space_offset(hose);
hose->io_resource.start += io_virt_offset; hose->io_resource.start += io_virt_offset;
......
...@@ -178,10 +178,9 @@ static int electra_cf_probe(struct platform_device *ofdev) ...@@ -178,10 +178,9 @@ static int electra_cf_probe(struct platform_device *ofdev)
struct device_node *np = ofdev->dev.of_node; struct device_node *np = ofdev->dev.of_node;
struct electra_cf_socket *cf; struct electra_cf_socket *cf;
struct resource mem, io; struct resource mem, io;
int status; int status = -ENOMEM;
const unsigned int *prop; const unsigned int *prop;
int err; int err;
struct vm_struct *area;
err = of_address_to_resource(np, 0, &mem); err = of_address_to_resource(np, 0, &mem);
if (err) if (err)
...@@ -202,30 +201,19 @@ static int electra_cf_probe(struct platform_device *ofdev) ...@@ -202,30 +201,19 @@ static int electra_cf_probe(struct platform_device *ofdev)
cf->mem_phys = mem.start; cf->mem_phys = mem.start;
cf->mem_size = PAGE_ALIGN(resource_size(&mem)); cf->mem_size = PAGE_ALIGN(resource_size(&mem));
cf->mem_base = ioremap(cf->mem_phys, cf->mem_size); cf->mem_base = ioremap(cf->mem_phys, cf->mem_size);
if (!cf->mem_base)
goto out_free_cf;
cf->io_size = PAGE_ALIGN(resource_size(&io)); cf->io_size = PAGE_ALIGN(resource_size(&io));
cf->io_virt = ioremap_phb(io.start, cf->io_size);
area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END); if (!cf->io_virt)
if (area == NULL) { goto out_unmap_mem;
status = -ENOMEM;
goto fail1;
}
cf->io_virt = (void __iomem *)(area->addr);
cf->gpio_base = ioremap(0xfc103000, 0x1000); cf->gpio_base = ioremap(0xfc103000, 0x1000);
if (!cf->gpio_base)
goto out_unmap_virt;
dev_set_drvdata(device, cf); dev_set_drvdata(device, cf);
if (!cf->mem_base || !cf->io_virt || !cf->gpio_base ||
(__ioremap_at(io.start, cf->io_virt, cf->io_size,
pgprot_noncached(PAGE_KERNEL)) == NULL)) {
dev_err(device, "can't ioremap ranges\n");
status = -ENOMEM;
goto fail1;
}
cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END; cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END;
cf->iomem.start = (unsigned long)cf->mem_base; cf->iomem.start = (unsigned long)cf->mem_base;
cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start); cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start);
cf->iomem.flags = IORESOURCE_MEM; cf->iomem.flags = IORESOURCE_MEM;
...@@ -305,14 +293,13 @@ static int electra_cf_probe(struct platform_device *ofdev) ...@@ -305,14 +293,13 @@ static int electra_cf_probe(struct platform_device *ofdev)
if (cf->irq) if (cf->irq)
free_irq(cf->irq, cf); free_irq(cf->irq, cf);
if (cf->io_virt) iounmap(cf->gpio_base);
__iounmap_at(cf->io_virt, cf->io_size); out_unmap_virt:
if (cf->mem_base) device_init_wakeup(&ofdev->dev, 0);
iounmap(cf->mem_base); iounmap(cf->io_virt);
if (cf->gpio_base) out_unmap_mem:
iounmap(cf->gpio_base); iounmap(cf->mem_base);
if (area) out_free_cf:
device_init_wakeup(&ofdev->dev, 0);
kfree(cf); kfree(cf);
return status; return status;
...@@ -330,7 +317,7 @@ static int electra_cf_remove(struct platform_device *ofdev) ...@@ -330,7 +317,7 @@ static int electra_cf_remove(struct platform_device *ofdev)
free_irq(cf->irq, cf); free_irq(cf->irq, cf);
del_timer_sync(&cf->timer); del_timer_sync(&cf->timer);
__iounmap_at(cf->io_virt, cf->io_size); iounmap(cf->io_virt);
iounmap(cf->mem_base); iounmap(cf->mem_base);
iounmap(cf->gpio_base); iounmap(cf->gpio_base);
release_mem_region(cf->mem_phys, cf->mem_size); release_mem_region(cf->mem_phys, cf->mem_size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment