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 { ...@@ -99,7 +99,7 @@ pll: pll-controller@18050000 {
miscintc: interrupt-controller@18060010 { miscintc: interrupt-controller@18060010 {
compatible = "qca,ar7240-misc-intc"; compatible = "qca,ar7240-misc-intc";
reg = <0x18060010 0x4>; reg = <0x18060010 0x8>;
interrupt-parent = <&cpuintc>; interrupt-parent = <&cpuintc>;
interrupts = <6>; interrupts = <6>;
......
...@@ -160,7 +160,6 @@ void __init prom_meminit(void) ...@@ -160,7 +160,6 @@ void __init prom_meminit(void)
void __init prom_free_prom_memory(void) void __init prom_free_prom_memory(void)
{ {
unsigned long addr;
int i; int i;
if (prom_flags & PROM_FLAG_DONT_FREE_TEMP) if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <asm/octeon/octeon-feature.h> #include <asm/octeon/octeon-feature.h>
#include <asm/octeon/cvmx-ipd-defs.h> #include <asm/octeon/cvmx-ipd-defs.h>
#include <asm/octeon/cvmx-pip-defs.h>
enum cvmx_ipd_mode { enum cvmx_ipd_mode {
CVMX_IPD_OPC_MODE_STT = 0LL, /* All blocks DRAM, not cached in L2 */ CVMX_IPD_OPC_MODE_STT = 0LL, /* All blocks DRAM, not cached in L2 */
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
# endif # endif
#define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_CLONE #define __ARCH_WANT_SYS_CLONE
#define __ARCH_WANT_SYS_CLONE3
/* whitelists for checksyscalls */ /* whitelists for checksyscalls */
#define __IGNORE_fadvise64_64 #define __IGNORE_fadvise64_64
......
...@@ -24,7 +24,8 @@ static char r4kwar[] __initdata = ...@@ -24,7 +24,8 @@ static char r4kwar[] __initdata =
static char daddiwar[] __initdata = static char daddiwar[] __initdata =
"Enable CPU_DADDI_WORKAROUNDS to rectify."; "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( asm volatile(
".set push\n\t" ".set push\n\t"
...@@ -38,7 +39,8 @@ static inline void align_mod(const int align, const int mod) ...@@ -38,7 +39,8 @@ static inline void align_mod(const int align, const int mod)
: "n"(align), "n"(mod)); : "n"(align), "n"(mod));
} }
static __always_inline void mult_sh_align_mod(long *v1, long *v2, long *w, static __always_inline __init
void mult_sh_align_mod(long *v1, long *v2, long *w,
const int align, const int mod) const int align, const int mod)
{ {
unsigned long flags; unsigned long flags;
...@@ -113,7 +115,7 @@ static __always_inline void mult_sh_align_mod(long *v1, long *v2, long *w, ...@@ -113,7 +115,7 @@ static __always_inline void mult_sh_align_mod(long *v1, long *v2, long *w,
*w = lw; *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]; long v1[8], v2[8], w[8];
int bug, fix, i; int bug, fix, i;
...@@ -176,7 +178,7 @@ asmlinkage void __init do_daddi_ov(struct pt_regs *regs) ...@@ -176,7 +178,7 @@ asmlinkage void __init do_daddi_ov(struct pt_regs *regs)
exception_exit(prev_state); exception_exit(prev_state);
} }
static inline void check_daddi(void) static __init void check_daddi(void)
{ {
extern asmlinkage void handle_daddi_ov(void); extern asmlinkage void handle_daddi_ov(void);
unsigned long flags; unsigned long flags;
...@@ -242,7 +244,7 @@ static inline void check_daddi(void) ...@@ -242,7 +244,7 @@ static inline void check_daddi(void)
int daddiu_bug = IS_ENABLED(CONFIG_CPU_MIPSR6) ? 0 : -1; 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; long v, w, tmp;
......
...@@ -108,6 +108,9 @@ void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type) ...@@ -108,6 +108,9 @@ void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type)
return; return;
} }
if (start < PHYS_OFFSET)
return;
memblock_add(start, size); memblock_add(start, size);
/* Reserve any memory except the ordinary RAM ranges. */ /* Reserve any memory except the ordinary RAM ranges. */
switch (type) { switch (type) {
...@@ -321,7 +324,7 @@ static void __init bootmem_init(void) ...@@ -321,7 +324,7 @@ static void __init bootmem_init(void)
* Reserve any memory between the start of RAM and PHYS_OFFSET * Reserve any memory between the start of RAM and PHYS_OFFSET
*/ */
if (ramstart > 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) { if (PFN_UP(ramstart) > ARCH_PFN_OFFSET) {
pr_info("Wasting %lu bytes for tracking %lu unused pages\n", 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, ...@@ -80,6 +80,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
save_static_function(sys_fork); save_static_function(sys_fork);
save_static_function(sys_clone); save_static_function(sys_clone);
save_static_function(sys_clone3);
SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
{ {
......
...@@ -373,4 +373,4 @@ ...@@ -373,4 +373,4 @@
432 n32 fsmount sys_fsmount 432 n32 fsmount sys_fsmount
433 n32 fspick sys_fspick 433 n32 fspick sys_fspick
434 n32 pidfd_open sys_pidfd_open 434 n32 pidfd_open sys_pidfd_open
# 435 reserved for clone3 435 n32 clone3 __sys_clone3
...@@ -349,4 +349,4 @@ ...@@ -349,4 +349,4 @@
432 n64 fsmount sys_fsmount 432 n64 fsmount sys_fsmount
433 n64 fspick sys_fspick 433 n64 fspick sys_fspick
434 n64 pidfd_open sys_pidfd_open 434 n64 pidfd_open sys_pidfd_open
# 435 reserved for clone3 435 n64 clone3 __sys_clone3
...@@ -422,4 +422,4 @@ ...@@ -422,4 +422,4 @@
432 o32 fsmount sys_fsmount 432 o32 fsmount sys_fsmount
433 o32 fspick sys_fspick 433 o32 fspick sys_fspick
434 o32 pidfd_open sys_pidfd_open 434 o32 pidfd_open sys_pidfd_open
# 435 reserved for clone3 435 o32 clone3 __sys_clone3
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/memblock.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
...@@ -64,26 +65,24 @@ void __init prom_init_memory(void) ...@@ -64,26 +65,24 @@ void __init prom_init_memory(void)
node_id = loongson_memmap->map[i].node_id; node_id = loongson_memmap->map[i].node_id;
mem_type = loongson_memmap->map[i].mem_type; mem_type = loongson_memmap->map[i].mem_type;
if (node_id == 0) { if (node_id != 0)
continue;
switch (mem_type) { switch (mem_type) {
case SYSTEM_RAM_LOW: case SYSTEM_RAM_LOW:
add_memory_region(loongson_memmap->map[i].mem_start, memblock_add(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20, (u64)loongson_memmap->map[i].mem_size << 20);
BOOT_MEM_RAM);
break; break;
case SYSTEM_RAM_HIGH: case SYSTEM_RAM_HIGH:
add_memory_region(loongson_memmap->map[i].mem_start, memblock_add(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20, (u64)loongson_memmap->map[i].mem_size << 20);
BOOT_MEM_RAM);
break; break;
case SYSTEM_RAM_RESERVED: case SYSTEM_RAM_RESERVED:
add_memory_region(loongson_memmap->map[i].mem_start, memblock_reserve(loongson_memmap->map[i].mem_start,
(u64)loongson_memmap->map[i].mem_size << 20, (u64)loongson_memmap->map[i].mem_size << 20);
BOOT_MEM_RESERVED);
break; break;
} }
} }
}
} }
#endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */ #endif /* CONFIG_LEFI_FIRMWARE_INTERFACE */
......
...@@ -110,7 +110,7 @@ static int __init serial_init(void) ...@@ -110,7 +110,7 @@ static int __init serial_init(void)
} }
module_init(serial_init); module_init(serial_init);
static void __init serial_exit(void) static void __exit serial_exit(void)
{ {
platform_device_unregister(&uart8250_device); platform_device_unregister(&uart8250_device);
} }
......
...@@ -142,8 +142,6 @@ static void __init szmem(unsigned int node) ...@@ -142,8 +142,6 @@ static void __init szmem(unsigned int node)
(u32)node_id, mem_type, mem_start, mem_size); (u32)node_id, mem_type, mem_start, mem_size);
pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n", pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
start_pfn, end_pfn, num_physpages); 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), memblock_add_node(PFN_PHYS(start_pfn),
PFN_PHYS(end_pfn - start_pfn), node); PFN_PHYS(end_pfn - start_pfn), node);
break; break;
...@@ -156,16 +154,12 @@ static void __init szmem(unsigned int node) ...@@ -156,16 +154,12 @@ static void __init szmem(unsigned int node)
(u32)node_id, mem_type, mem_start, mem_size); (u32)node_id, mem_type, mem_start, mem_size);
pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n", pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
start_pfn, end_pfn, num_physpages); 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), memblock_add_node(PFN_PHYS(start_pfn),
PFN_PHYS(end_pfn - start_pfn), node); PFN_PHYS(end_pfn - start_pfn), node);
break; break;
case SYSTEM_RAM_RESERVED: case SYSTEM_RAM_RESERVED:
pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", 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); (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), memblock_reserve(((node_id << 44) + mem_start),
mem_size << 20); mem_size << 20);
break; break;
...@@ -191,8 +185,6 @@ static void __init node_mem_init(unsigned int node) ...@@ -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_start_pfn = start_pfn;
NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
free_bootmem_with_active_regions(node, end_pfn);
if (node == 0) { if (node == 0) {
/* kernel end address */ /* kernel end address */
unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end)); unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end));
...@@ -209,8 +201,6 @@ static void __init node_mem_init(unsigned int node) ...@@ -209,8 +201,6 @@ static void __init node_mem_init(unsigned int node)
memblock_reserve((node_addrspace_offset | 0xfe000000), memblock_reserve((node_addrspace_offset | 0xfe000000),
32 << 20); 32 << 20);
} }
sparse_memory_present_with_active_regions(node);
} }
static __init void prom_meminit(void) static __init void prom_meminit(void)
...@@ -227,6 +217,7 @@ static __init void prom_meminit(void) ...@@ -227,6 +217,7 @@ static __init void prom_meminit(void)
cpumask_clear(&__node_data[(node)]->cpumask); cpumask_clear(&__node_data[(node)]->cpumask);
} }
} }
memblocks_present();
max_low_pfn = PHYS_PFN(memblock_end_of_DRAM()); max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) { for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
......
...@@ -61,6 +61,7 @@ int init_debug = 1; ...@@ -61,6 +61,7 @@ int init_debug = 1;
/* memory blocks */ /* memory blocks */
struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; 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_base[MAX_PROM_MEM] __initdata;
static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata; static phys_addr_t prom_mem_size[MAX_PROM_MEM] __initdata;
static unsigned int nr_prom_mem __initdata; static unsigned int nr_prom_mem __initdata;
...@@ -358,7 +359,7 @@ void __init prom_meminit(void) ...@@ -358,7 +359,7 @@ void __init prom_meminit(void)
p++; p++;
if (type == BOOT_MEM_ROM_DATA) { 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"); pr_err("Too many ROM DATA regions");
continue; continue;
} }
...@@ -377,7 +378,6 @@ void __init prom_free_prom_memory(void) ...@@ -377,7 +378,6 @@ void __init prom_free_prom_memory(void)
char *ptr; char *ptr;
int len = 0; int len = 0;
int i; int i;
unsigned long addr;
/* /*
* preserve environment variables and command line from pmon/bbload * preserve environment variables and command line from pmon/bbload
......
...@@ -59,7 +59,7 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg ...@@ -59,7 +59,7 @@ CFLAGS_REMOVE_vgettimeofday.o = -pg
ifndef CONFIG_CPU_MIPSR6 ifndef CONFIG_CPU_MIPSR6
ifeq ($(call ld-ifversion, -lt, 225000000, y),y) ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
$(warning MIPS VDSO requires binutils >= 2.25) $(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 ccflags-vdso += -DDISABLE_MIPS_VDSO
endif endif
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