Skip to content

Commit

Permalink
s390: mm: Convert to GENERIC_IOREMAP
Browse files Browse the repository at this point in the history
By taking GENERIC_IOREMAP method, the generic ioremap_prot() and
iounmap() are visible and available to arch. Arch only needs to
provide implementation of arch_ioremap() or arch_iounmap() if there's
arch specific handling needed in its ioremap() or iounmap(). This
change will simplify implementation by removing duplicated codes with
generic ioremap() and iounmap(), and has the equivalent functioality
as before.

For s390, add hooks arch_ioremap() and arch_iounmap() for s390's special
operation when ioremap() and iounmap(), then ioremap_[wc|wt]() are
converted to use ioremap_prot() from GENERIC_IOREMAP.

Signed-off-by: Baoquan He <bhe@redhat.com>
Cc: Niklas Schnelle <schnelle@linux.ibm.com>
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: linux-s390@vger.kernel.org
  • Loading branch information
Baoquan He authored and intel-lab-lkp committed Oct 9, 2022
1 parent c462137 commit 69f6514
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 61 deletions.
1 change: 1 addition & 0 deletions arch/s390/Kconfig
Expand Up @@ -135,6 +135,7 @@ config S390
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select GENERIC_VDSO_TIME_NS
select GENERIC_IOREMAP
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_JUMP_LABEL
Expand Down
25 changes: 16 additions & 9 deletions arch/s390/include/asm/io.h
Expand Up @@ -22,11 +22,22 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);

#define IO_SPACE_LIMIT 0

void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot);
void __iomem *ioremap(phys_addr_t addr, size_t size);
void __iomem *ioremap_wc(phys_addr_t addr, size_t size);
void __iomem *ioremap_wt(phys_addr_t addr, size_t size);
void iounmap(volatile void __iomem *addr);
/*
* I/O memory mapping functions.
*/
void __iomem *
arch_ioremap(phys_addr_t *paddr, size_t size, unsigned long *prot_val);
#define arch_ioremap arch_ioremap

bool arch_iounmap(void __iomem *addr);
#define arch_iounmap arch_iounmap

#define _PAGE_IOREMAP pgprot_val(PAGE_KERNEL)

#define ioremap_wc(addr, size) \
ioremap_prot((addr), (size), pgprot_val(pgprot_writecombine(PAGE_KERNEL)))
#define ioremap_wt(addr, size) \
ioremap_prot((addr), (size), pgprot_val(pgprot_writethrough(PAGE_KERNEL)))

static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
{
Expand All @@ -51,10 +62,6 @@ static inline void ioport_unmap(void __iomem *p)
#define pci_iomap_wc pci_iomap_wc
#define pci_iomap_wc_range pci_iomap_wc_range

#define ioremap ioremap
#define ioremap_wt ioremap_wt
#define ioremap_wc ioremap_wc

#define memcpy_fromio(dst, src, count) zpci_memcpy_fromio(dst, src, count)
#define memcpy_toio(dst, src, count) zpci_memcpy_toio(dst, src, count)
#define memset_io(dst, val, count) zpci_memset_io(dst, val, count)
Expand Down
65 changes: 13 additions & 52 deletions arch/s390/pci/pci.c
Expand Up @@ -244,64 +244,25 @@ void __iowrite64_copy(void __iomem *to, const void *from, size_t count)
zpci_memcpy_toio(to, from, count);
}

static void __iomem *__ioremap(phys_addr_t addr, size_t size, pgprot_t prot)
void __iomem *
arch_ioremap(phys_addr_t *paddr, size_t size, unsigned long *prot_val)
{
unsigned long offset, vaddr;
struct vm_struct *area;
phys_addr_t last_addr;

last_addr = addr + size - 1;
if (!size || last_addr < addr)
return NULL;

/*
* When PCI MIO instructions are unavailable the "physical" address
* encodes a hint for accessing the PCI memory space it represents.
* Just pass it unchanged such that ioread/iowrite can decode it.
*/
if (!static_branch_unlikely(&have_mio))
return (void __iomem *) addr;

offset = addr & ~PAGE_MASK;
addr &= PAGE_MASK;
size = PAGE_ALIGN(size + offset);
area = get_vm_area(size, VM_IOREMAP);
if (!area)
return NULL;

vaddr = (unsigned long) area->addr;
if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) {
free_vm_area(area);
return NULL;
}
return (void __iomem *) ((unsigned long) area->addr + offset);
return (void __iomem *) *paddr;
return NULL;
}

void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot)
bool arch_iounmap(void __iomem *addr)
{
return __ioremap(addr, size, __pgprot(prot));
}
EXPORT_SYMBOL(ioremap_prot);

void __iomem *ioremap(phys_addr_t addr, size_t size)
{
return __ioremap(addr, size, PAGE_KERNEL);
}
EXPORT_SYMBOL(ioremap);

void __iomem *ioremap_wc(phys_addr_t addr, size_t size)
{
return __ioremap(addr, size, pgprot_writecombine(PAGE_KERNEL));
}
EXPORT_SYMBOL(ioremap_wc);

void __iomem *ioremap_wt(phys_addr_t addr, size_t size)
{
return __ioremap(addr, size, pgprot_writethrough(PAGE_KERNEL));
}
EXPORT_SYMBOL(ioremap_wt);

void iounmap(volatile void __iomem *addr)
{
if (static_branch_likely(&have_mio))
vunmap((__force void *) ((unsigned long) addr & PAGE_MASK));
if (!static_branch_likely(&have_mio))
return false;
return true;
}
EXPORT_SYMBOL(iounmap);

/* Create a virtual mapping cookie for a PCI BAR */
static void __iomem *pci_iomap_range_fh(struct pci_dev *pdev, int bar,
Expand Down

0 comments on commit 69f6514

Please sign in to comment.