Commit c23f864d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'loongarch-fixes-6.0-1' of...

Merge tag 'loongarch-fixes-6.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson

Pull LoongArch fixes from Huacai Chen:
 "Fix a bunch of build errors/warnings, a poweroff error and an
  unbalanced locking in do_page_fault()"

* tag 'loongarch-fixes-6.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
  LoongArch: mm: Avoid unnecessary page fault retires on shared memory types
  LoongArch: Add subword xchg/cmpxchg emulation
  LoongArch: Cleanup headers to avoid circular dependency
  LoongArch: Cleanup reset routines with new API
  LoongArch: Fix build warnings in VDSO
  LoongArch: Select PCI_QUIRKS to avoid build error
parents 78effb4a b83699ea
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ config LOONGARCH
	select PCI_ECAM if ACPI
	select PCI_LOONGSON
	select PCI_MSI_ARCH_FALLBACKS
	select PCI_QUIRKS
	select PERF_USE_VMALLOC
	select RTC_LIB
	select SMP
+16 −0
Original line number Diff line number Diff line
@@ -109,4 +109,20 @@ extern unsigned long vm_map_base;
 */
#define PHYSADDR(a)		((_ACAST64_(a)) & TO_PHYS_MASK)

/*
 * On LoongArch, I/O ports mappring is following:
 *
 *              |         ....          |
 *              |-----------------------|
 *              | pci io ports(16K~32M) |
 *              |-----------------------|
 *              | isa io ports(0  ~16K) |
 * PCI_IOBASE ->|-----------------------|
 *              |         ....          |
 */
#define PCI_IOBASE	((void __iomem *)(vm_map_base + (2 * PAGE_SIZE)))
#define PCI_IOSIZE	SZ_32M
#define ISA_IOSIZE	SZ_16K
#define IO_SPACE_LIMIT	(PCI_IOSIZE - 1)

#endif /* _ASM_ADDRSPACE_H */
+97 −1
Original line number Diff line number Diff line
@@ -5,8 +5,9 @@
#ifndef __ASM_CMPXCHG_H
#define __ASM_CMPXCHG_H

#include <asm/barrier.h>
#include <linux/bits.h>
#include <linux/build_bug.h>
#include <asm/barrier.h>

#define __xchg_asm(amswap_db, m, val)		\
({						\
@@ -21,10 +22,53 @@
		__ret;				\
})

static inline unsigned int __xchg_small(volatile void *ptr, unsigned int val,
					unsigned int size)
{
	unsigned int shift;
	u32 old32, mask, temp;
	volatile u32 *ptr32;

	/* Mask value to the correct size. */
	mask = GENMASK((size * BITS_PER_BYTE) - 1, 0);
	val &= mask;

	/*
	 * Calculate a shift & mask that correspond to the value we wish to
	 * exchange within the naturally aligned 4 byte integerthat includes
	 * it.
	 */
	shift = (unsigned long)ptr & 0x3;
	shift *= BITS_PER_BYTE;
	mask <<= shift;

	/*
	 * Calculate a pointer to the naturally aligned 4 byte integer that
	 * includes our byte of interest, and load its value.
	 */
	ptr32 = (volatile u32 *)((unsigned long)ptr & ~0x3);

	asm volatile (
	"1:	ll.w		%0, %3		\n"
	"	andn		%1, %0, %z4	\n"
	"	or		%1, %1, %z5	\n"
	"	sc.w		%1, %2		\n"
	"	beqz		%1, 1b		\n"
	: "=&r" (old32), "=&r" (temp), "=ZC" (*ptr32)
	: "ZC" (*ptr32), "Jr" (mask), "Jr" (val << shift)
	: "memory");

	return (old32 & mask) >> shift;
}

static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
				   int size)
{
	switch (size) {
	case 1:
	case 2:
		return __xchg_small(ptr, x, size);

	case 4:
		return __xchg_asm("amswap_db.w", (volatile u32 *)ptr, (u32)x);

@@ -67,10 +111,62 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
	__ret;								\
})

static inline unsigned int __cmpxchg_small(volatile void *ptr, unsigned int old,
					   unsigned int new, unsigned int size)
{
	unsigned int shift;
	u32 old32, mask, temp;
	volatile u32 *ptr32;

	/* Mask inputs to the correct size. */
	mask = GENMASK((size * BITS_PER_BYTE) - 1, 0);
	old &= mask;
	new &= mask;

	/*
	 * Calculate a shift & mask that correspond to the value we wish to
	 * compare & exchange within the naturally aligned 4 byte integer
	 * that includes it.
	 */
	shift = (unsigned long)ptr & 0x3;
	shift *= BITS_PER_BYTE;
	old <<= shift;
	new <<= shift;
	mask <<= shift;

	/*
	 * Calculate a pointer to the naturally aligned 4 byte integer that
	 * includes our byte of interest, and load its value.
	 */
	ptr32 = (volatile u32 *)((unsigned long)ptr & ~0x3);

	asm volatile (
	"1:	ll.w		%0, %3		\n"
	"	and		%1, %0, %z4	\n"
	"	bne		%1, %z5, 2f	\n"
	"	andn		%1, %0, %z4	\n"
	"	or		%1, %1, %z6	\n"
	"	sc.w		%1, %2		\n"
	"	beqz		%1, 1b		\n"
	"	b		3f		\n"
	"2:					\n"
	__WEAK_LLSC_MB
	"3:					\n"
	: "=&r" (old32), "=&r" (temp), "=ZC" (*ptr32)
	: "ZC" (*ptr32), "Jr" (mask), "Jr" (old), "Jr" (new)
	: "memory");

	return (old32 & mask) >> shift;
}

static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
				      unsigned long new, unsigned int size)
{
	switch (size) {
	case 1:
	case 2:
		return __cmpxchg_small(ptr, old, new, size);

	case 4:
		return __cmpxchg_asm("ll.w", "sc.w", (volatile u32 *)ptr,
				     (u32)old, new);
+0 −19
Original line number Diff line number Diff line
@@ -7,34 +7,15 @@

#define ARCH_HAS_IOREMAP_WC

#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/types.h>

#include <asm/addrspace.h>
#include <asm/bug.h>
#include <asm/byteorder.h>
#include <asm/cpu.h>
#include <asm/page.h>
#include <asm/pgtable-bits.h>
#include <asm/string.h>

/*
 * On LoongArch, I/O ports mappring is following:
 *
 *              |         ....          |
 *              |-----------------------|
 *              | pci io ports(64K~32M) |
 *              |-----------------------|
 *              | isa io ports(0  ~16K) |
 * PCI_IOBASE ->|-----------------------|
 *              |         ....          |
 */
#define PCI_IOBASE	((void __iomem *)(vm_map_base + (2 * PAGE_SIZE)))
#define PCI_IOSIZE	SZ_32M
#define ISA_IOSIZE	SZ_16K
#define IO_SPACE_LIMIT	(PCI_IOSIZE - 1)

/*
 * Change "struct page" to physical address.
 */
+1 −1
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ static inline int pfn_valid(unsigned long pfn)

#endif

#define virt_to_pfn(kaddr)	PFN_DOWN(virt_to_phys((void *)(kaddr)))
#define virt_to_pfn(kaddr)	PFN_DOWN(PHYSADDR(kaddr))
#define virt_to_page(kaddr)	pfn_to_page(virt_to_pfn(kaddr))

extern int __virt_addr_valid(volatile void *kaddr);
Loading