Commit 4ea65534 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mips_fixes_5.4_1' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux

Pull MIPS fixes from Paul Burton:

 - Build fixes for Cavium Octeon & PMC-Sierra MSP systems, as well as
   all pre-MIPSr6 configurations built with binutils < 2.25.

 - Boot fixes for 64-bit Loongson systems & SGI IP28 systems.

 - Wire up the new clone3 syscall.

 - Clean ups for a few build-time warnings.

* tag 'mips_fixes_5.4_1' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux:
  MIPS: fw/arc: Remove unused addr variable
  MIPS: pmcs-msp71xx: Remove unused addr variable
  MIPS: pmcs-msp71xx: Add missing MAX_PROM_MEM definition
  mips: Loongson: Fix the link time qualifier of 'serial_exit()'
  MIPS: init: Prevent adding memory before PHYS_OFFSET
  MIPS: init: Fix reservation of memory between PHYS_OFFSET and mem start
  MIPS: VDSO: Fix build for binutils < 2.25
  MIPS: VDSO: Remove unused gettimeofday.c
  MIPS: Wire up clone3 syscall
  MIPS: octeon: Include required header; fix octeon ethernet build
  MIPS: cpu-bugs64: Mark inline functions as __always_inline
  MIPS: dts: ar9331: fix interrupt-controller size
  MIPS: Loongson64: Fix boot failure after dropping boot_mem_map
parents 812ad49d 6822c29d
......@@ -99,7 +99,7 @@ pll: pll-controller@18050000 {
miscintc: interrupt-controller@18060010 {
compatible = "qca,ar7240-misc-intc";
reg = <0x18060010 0x4>;
reg = <0x18060010 0x8>;
interrupt-parent = <&cpuintc>;
interrupts = <6>;
......
......@@ -160,7 +160,6 @@ void __init prom_meminit(void)
void __init prom_free_prom_memory(void)
{
unsigned long addr;
int i;
if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
......
......@@ -36,6 +36,7 @@
#include <asm/octeon/octeon-feature.h>
#include <asm/octeon/cvmx-ipd-defs.h>
#include <asm/octeon/cvmx-pip-defs.h>
enum cvmx_ipd_mode {
CVMX_IPD_OPC_MODE_STT = 0LL, /* All blocks DRAM, not cached in L2 */
......
......@@ -52,6 +52,7 @@
# endif
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_CLONE
#define __ARCH_WANT_SYS_CLONE3
/* whitelists for checksyscalls */
#define __IGNORE_fadvise64_64
......
......@@ -24,7 +24,8 @@ static char r4kwar[] __initdata =
static char daddiwar[] __initdata =
"Enable CPU_DADDI_WORKAROUNDS to rectify.";
static inline void align_mod(const int align, const int mod)
static __always_inline __init
void align_mod(const int align, const int mod)
{
asm volatile(
".set push\n\t"
......@@ -38,8 +39,9 @@ static inline void align_mod(const int align, const int mod)
: "n"(align), "n"(mod));
}
static __always_inline void mult_sh_align_mod(long *v1, long *v2, long *w,
const int align, const int mod)
static __always_inline __init
void mult_sh_align_mod(long *v1, long *v2, long *w,
const int align, const int mod)
{
unsigned long flags;
int m1, m2;
......@@ -113,7 +115,7 @@ static __always_inline void mult_sh_align_mod(long *v1, long *v2, long *w,
*w = lw;
}
static inline void check_mult_sh(void)
static __always_inline __init void check_mult_sh(void)
{
long v1[8], v2[8], w[8];
int bug, fix, i;
......@@ -176,7 +178,7 @@ asmlinkage void __init do_daddi_ov(struct pt_regs *regs)
exception_exit(prev_state);
}
static inline void check_daddi(void)
static __init void check_daddi(void)
{
extern asmlinkage void handle_daddi_ov(void);
unsigned long flags;
......@@ -242,7 +244,7 @@ static inline void check_daddi(void)
int daddiu_bug = IS_ENABLED(CONFIG_CPU_MIPSR6) ? 0 : -1;
static inline void check_daddiu(void)
static __init void check_daddiu(void)
{
long v, w, tmp;
......
......@@ -108,6 +108,9 @@ void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type)
return;
}
if (start < PHYS_OFFSET)
return;
memblock_add(start, size);
/* Reserve any memory except the ordinary RAM ranges. */
switch (type) {
......@@ -321,7 +324,7 @@ static void __init bootmem_init(void)
* Reserve any memory between the start of RAM and PHYS_OFFSET
*/
if (ramstart > PHYS_OFFSET)
memblock_reserve(PHYS_OFFSET, PFN_UP(ramstart) - PHYS_OFFSET);
memblock_reserve(PHYS_OFFSET, ramstart - PHYS_OFFSET);
if (PFN_UP(ramstart) > ARCH_PFN_OFFSET) {
pr_info("Wasting %lu bytes for tracking %lu unused pages\n",
......
......@@ -80,6 +80,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
save_static_function(sys_fork);
save_static_function(sys_clone);
save_static_function(sys_clone3);
SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
{
......
......@@ -373,4 +373,4 @@
432 n32 fsmount sys_fsmount
433 n32 fspick sys_fspick
434 n32 pidfd_open sys_pidfd_open
# 435 reserved for clone3
435 n32 clone3 __sys_clone3
......@@ -349,4 +349,4 @@
432 n64 fsmount sys_fsmount
433 n64 fspick sys_fspick
434 n64 pidfd_open sys_pidfd_open
# 435 reserved for clone3
435 n64 clone3 __sys_clone3
......@@ -422,4 +422,4 @@
432 o32 fsmount sys_fsmount
433 o32 fspick sys_fspick
434 o32 pidfd_open sys_pidfd_open
# 435 reserved for clone3
435 o32 clone3 __sys_clone3
......@@ -3,6 +3,7 @@
*/
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <asm/bootinfo.h>
......@@ -64,24 +65,22 @@ void __init prom_init_memory(void)
node_id = loongson_memmap->map[i].node_id;
mem_type = loongson_memmap->map[i].mem_type;
if (node_id == 0) {
switch (mem_type) {
case SYSTEM_RAM_LOW:
add_memory_region(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20,
BOOT_MEM_RAM);
break;
case SYSTEM_RAM_HIGH:
add_memory_region(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20,
BOOT_MEM_RAM);
break;
case SYSTEM_RAM_RESERVED:
add_memory_region(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20,
BOOT_MEM_RESERVED);
break;
}
if (node_id != 0)
continue;
switch (mem_type) {
case SYSTEM_RAM_LOW:
memblock_add(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20);
break;
case SYSTEM_RAM_HIGH:
memblock_add(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20);
break;
case SYSTEM_RAM_RESERVED:
memblock_reserve(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20);
break;
}
}
}
......
......@@ -110,7 +110,7 @@ static int __init serial_init(void)
}
module_init(serial_init);
static void __init serial_exit(void)
static void __exit serial_exit(void)
{
platform_device_unregister(&uart8250_device);
}
......
......@@ -142,8 +142,6 @@ static void __init szmem(unsigned int node)
(u32)node_id, mem_type, mem_start, mem_size);
pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
start_pfn, end_pfn, num_physpages);
add_memory_region((node_id << 44) + mem_start,
(u64)mem_size << 20, BOOT_MEM_RAM);
memblock_add_node(PFN_PHYS(start_pfn),
PFN_PHYS(end_pfn - start_pfn), node);
break;
......@@ -156,16 +154,12 @@ static void __init szmem(unsigned int node)
(u32)node_id, mem_type, mem_start, mem_size);
pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
start_pfn, end_pfn, num_physpages);
add_memory_region((node_id << 44) + mem_start,
(u64)mem_size << 20, BOOT_MEM_RAM);
memblock_add_node(PFN_PHYS(start_pfn),
PFN_PHYS(end_pfn - start_pfn), node);
break;
case SYSTEM_RAM_RESERVED:
pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
(u32)node_id, mem_type, mem_start, mem_size);
add_memory_region((node_id << 44) + mem_start,
(u64)mem_size << 20, BOOT_MEM_RESERVED);
memblock_reserve(((node_id << 44) + mem_start),
mem_size << 20);
break;
......@@ -191,8 +185,6 @@ static void __init node_mem_init(unsigned int node)
NODE_DATA(node)->node_start_pfn = start_pfn;
NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
free_bootmem_with_active_regions(node, end_pfn);
if (node == 0) {
/* kernel end address */
unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end));
......@@ -209,8 +201,6 @@ static void __init node_mem_init(unsigned int node)
memblock_reserve((node_addrspace_offset | 0xfe000000),
32 << 20);
}
sparse_memory_present_with_active_regions(node);
}
static __init void prom_meminit(void)
......@@ -227,6 +217,7 @@ static __init void prom_meminit(void)
cpumask_clear(&__node_data[(node)]->cpumask);
}
}
memblocks_present();
max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
......
......@@ -61,6 +61,7 @@ int init_debug = 1;
/* memory blocks */
struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
#define MAX_PROM_MEM 5
static phys_addr_t prom_mem_base[MAX_PROM_MEM] __initdata;
static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata;
static unsigned int nr_prom_mem __initdata;
......@@ -358,7 +359,7 @@ void __init prom_meminit(void)
p++;
if (type == BOOT_MEM_ROM_DATA) {
if (nr_prom_mem >= 5) {
if (nr_prom_mem >= MAX_PROM_MEM) {
pr_err("Too many ROM DATA regions");
continue;
}
......@@ -377,7 +378,6 @@ void __init prom_free_prom_memory(void)
char *ptr;
int len = 0;
int i;
unsigned long addr;
/*
* preserve environment variables and command line from pmon/bbload
......
......@@ -59,7 +59,7 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg
ifndef CONFIG_CPU_MIPSR6
ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
$(warning MIPS VDSO requires binutils >= 2.25)
obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
obj-vdso-y := $(filter-out vgettimeofday.o, $(obj-vdso-y))
ccflags-vdso += -DDISABLE_MIPS_VDSO
endif
endif
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2015 Imagination Technologies
* Author: Alex Smith <alex.smith@imgtec.com>
*/
#include "vdso.h"
#include <linux/compiler.h>
#include <linux/time.h>
#include <asm/clocksource.h>
#include <asm/io.h>
#include <asm/unistd.h>
#include <asm/vdso.h>
#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
static __always_inline long gettimeofday_fallback(struct timeval *_tv,
struct timezone *_tz)
{
register struct timezone *tz asm("a1") = _tz;
register struct timeval *tv asm("a0") = _tv;
register long ret asm("v0");
register long nr asm("v0") = __NR_gettimeofday;
register long error asm("a3");
asm volatile(
" syscall\n"
: "=r" (ret), "=r" (error)
: "r" (tv), "r" (tz), "r" (nr)
: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
"$14", "$15", "$24", "$25", "hi", "lo", "memory");
return error ? -ret : ret;
}
#endif
static __always_inline long clock_gettime_fallback(clockid_t _clkid,
struct timespec *_ts)
{
register struct timespec *ts asm("a1") = _ts;
register clockid_t clkid asm("a0") = _clkid;
register long ret asm("v0");
register long nr asm("v0") = __NR_clock_gettime;
register long error asm("a3");
asm volatile(
" syscall\n"
: "=r" (ret), "=r" (error)
: "r" (clkid), "r" (ts), "r" (nr)
: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
"$14", "$15", "$24", "$25", "hi", "lo", "memory");
return error ? -ret : ret;
}
static __always_inline int do_realtime_coarse(struct timespec *ts,
const union mips_vdso_data *data)
{
u32 start_seq;
do {
start_seq = vdso_data_read_begin(data);
ts->tv_sec = data->xtime_sec;
ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
} while (vdso_data_read_retry(data, start_seq));
return 0;
}
static __always_inline int do_monotonic_coarse(struct timespec *ts,
const union mips_vdso_data *data)
{
u32 start_seq;
u64 to_mono_sec;
u64 to_mono_nsec;
do {
start_seq = vdso_data_read_begin(data);
ts->tv_sec = data->xtime_sec;
ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
to_mono_sec = data->wall_to_mono_sec;
to_mono_nsec = data->wall_to_mono_nsec;
} while (vdso_data_read_retry(data, start_seq));
ts->tv_sec += to_mono_sec;
timespec_add_ns(ts, to_mono_nsec);
return 0;
}
#ifdef CONFIG_CSRC_R4K
static __always_inline u64 read_r4k_count(void)
{
unsigned int count;
__asm__ __volatile__(
" .set push\n"
" .set mips32r2\n"
" rdhwr %0, $2\n"
" .set pop\n"
: "=r" (count));
return count;
}
#endif
#ifdef CONFIG_CLKSRC_MIPS_GIC
static __always_inline u64 read_gic_count(const union mips_vdso_data *data)
{
void __iomem *gic = get_gic(data);
u32 hi, hi2, lo;
do {
hi = __raw_readl(gic + sizeof(lo));
lo = __raw_readl(gic);
hi2 = __raw_readl(gic + sizeof(lo));
} while (hi2 != hi);
return (((u64)hi) << 32) + lo;
}
#endif
static __always_inline u64 get_ns(const union mips_vdso_data *data)
{
u64 cycle_now, delta, nsec;
switch (data->clock_mode) {
#ifdef CONFIG_CSRC_R4K
case VDSO_CLOCK_R4K:
cycle_now = read_r4k_count();
break;
#endif
#ifdef CONFIG_CLKSRC_MIPS_GIC
case VDSO_CLOCK_GIC:
cycle_now = read_gic_count(data);
break;
#endif
default:
return 0;
}
delta = (cycle_now - data->cs_cycle_last) & data->cs_mask;
nsec = (delta * data->cs_mult) + data->xtime_nsec;
nsec >>= data->cs_shift;
return nsec;
}
static __always_inline int do_realtime(struct timespec *ts,
const union mips_vdso_data *data)
{
u32 start_seq;
u64 ns;
do {
start_seq = vdso_data_read_begin(data);
if (data->clock_mode == VDSO_CLOCK_NONE)
return -ENOSYS;
ts->tv_sec = data->xtime_sec;
ns = get_ns(data);
} while (vdso_data_read_retry(data, start_seq));
ts->tv_nsec = 0;
timespec_add_ns(ts, ns);
return 0;
}
static __always_inline int do_monotonic(struct timespec *ts,
const union mips_vdso_data *data)
{
u32 start_seq;
u64 ns;
u64 to_mono_sec;
u64 to_mono_nsec;
do {
start_seq = vdso_data_read_begin(data);
if (data->clock_mode == VDSO_CLOCK_NONE)
return -ENOSYS;
ts->tv_sec = data->xtime_sec;
ns = get_ns(data);
to_mono_sec = data->wall_to_mono_sec;
to_mono_nsec = data->wall_to_mono_nsec;
} while (vdso_data_read_retry(data, start_seq));
ts->tv_sec += to_mono_sec;
ts->tv_nsec = 0;
timespec_add_ns(ts, ns + to_mono_nsec);
return 0;
}
#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
/*
* This is behind the ifdef so that we don't provide the symbol when there's no
* possibility of there being a usable clocksource, because there's nothing we
* can do without it. When libc fails the symbol lookup it should fall back on
* the standard syscall path.
*/
int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
{
const union mips_vdso_data *data = get_vdso_data();
struct timespec ts;
int ret;
ret = do_realtime(&ts, data);
if (ret)
return gettimeofday_fallback(tv, tz);
if (tv) {
tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec / 1000;
}
if (tz) {
tz->tz_minuteswest = data->tz_minuteswest;
tz->tz_dsttime = data->tz_dsttime;
}
return 0;
}
#endif /* CONFIG_MIPS_CLOCK_VSYSCALL */
int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
{
const union mips_vdso_data *data = get_vdso_data();
int ret = -1;
switch (clkid) {
case CLOCK_REALTIME_COARSE:
ret = do_realtime_coarse(ts, data);
break;
case CLOCK_MONOTONIC_COARSE:
ret = do_monotonic_coarse(ts, data);
break;
case CLOCK_REALTIME:
ret = do_realtime(ts, data);
break;
case CLOCK_MONOTONIC:
ret = do_monotonic(ts, data);
break;
default:
break;
}
if (ret)
ret = clock_gettime_fallback(clkid, ts);
return ret;
}
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