Commit 8d2b6b3a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sh-for-linus' of git://github.com/pmundt/linux-sh

Pull SuperH updates from Paul Mundt.

The bulk of this is the UAPI disintegration for SH.

* tag 'sh-for-linus' of git://github.com/pmundt/linux-sh:
  sh: Fix up more fallout from pointless ARM __iomem churn.
  sh: Wire up kcmp syscall.
  UAPI: (Scripted) Disintegrate arch/sh/include/asm
parents 90a24a4a 0dd4d5cb
include include/asm-generic/Kbuild.asm
generic-y += bitsperlong.h generic-y += bitsperlong.h
generic-y += cputime.h generic-y += cputime.h
...@@ -34,13 +33,3 @@ generic-y += termbits.h ...@@ -34,13 +33,3 @@ generic-y += termbits.h
generic-y += termios.h generic-y += termios.h
generic-y += ucontext.h generic-y += ucontext.h
generic-y += xor.h generic-y += xor.h
header-y += cachectl.h
header-y += cpu-features.h
header-y += hw_breakpoint.h
header-y += posix_types_32.h
header-y += posix_types_64.h
header-y += ptrace_32.h
header-y += ptrace_64.h
header-y += unistd_32.h
header-y += unistd_64.h
#ifndef __ASM_SH_HW_BREAKPOINT_H #ifndef __ASM_SH_HW_BREAKPOINT_H
#define __ASM_SH_HW_BREAKPOINT_H #define __ASM_SH_HW_BREAKPOINT_H
#ifdef __KERNEL__ #include <uapi/asm/hw_breakpoint.h>
#define __ARCH_HW_BREAKPOINT_H #define __ARCH_HW_BREAKPOINT_H
#include <linux/kdebug.h> #include <linux/kdebug.h>
...@@ -66,5 +67,4 @@ extern int register_sh_ubc(struct sh_ubc *); ...@@ -66,5 +67,4 @@ extern int register_sh_ubc(struct sh_ubc *);
extern struct pmu perf_ops_bp; extern struct pmu perf_ops_bp;
#endif /* __KERNEL__ */
#endif /* __ASM_SH_HW_BREAKPOINT_H */ #endif /* __ASM_SH_HW_BREAKPOINT_H */
#ifdef __KERNEL__
# ifdef CONFIG_SUPERH32 # ifdef CONFIG_SUPERH32
# include <asm/posix_types_32.h> # include <asm/posix_types_32.h>
# else # else
# include <asm/posix_types_64.h> # include <asm/posix_types_64.h>
# endif # endif
#else
# ifdef __SH5__
# include <asm/posix_types_64.h>
# else
# include <asm/posix_types_32.h>
# endif
#endif /* __KERNEL__ */
#ifndef __ASM_SH_PTRACE_H
#define __ASM_SH_PTRACE_H
/* /*
* Copyright (C) 1999, 2000 Niibe Yutaka * Copyright (C) 1999, 2000 Niibe Yutaka
*/ */
#ifndef __ASM_SH_PTRACE_H
#define __ASM_SH_PTRACE_H
#define PTRACE_GETREGS 12 /* General registers */
#define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14 /* FPU registers */
#define PTRACE_SETFPREGS 15
#define PTRACE_GETFDPIC 31 /* get the ELF fdpic loadmap address */
#define PTRACE_GETFDPIC_EXEC 0 /* [addr] request the executable loadmap */
#define PTRACE_GETFDPIC_INTERP 1 /* [addr] request the interpreter loadmap */
#define PTRACE_GETDSPREGS 55 /* DSP registers */
#define PTRACE_SETDSPREGS 56
#define PT_TEXT_END_ADDR 240
#define PT_TEXT_ADDR 244 /* &(struct user)->start_code */
#define PT_DATA_ADDR 248 /* &(struct user)->start_data */
#define PT_TEXT_LEN 252
#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
#include <asm/ptrace_64.h>
#else
#include <asm/ptrace_32.h>
#endif
#ifdef __KERNEL__
#include <linux/stringify.h> #include <linux/stringify.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <asm/addrspace.h> #include <asm/addrspace.h>
#include <asm/page.h> #include <asm/page.h>
#include <uapi/asm/ptrace.h>
#define user_mode(regs) (((regs)->sr & 0x40000000)==0) #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
#define kernel_stack_pointer(_regs) ((unsigned long)(_regs)->regs[15]) #define kernel_stack_pointer(_regs) ((unsigned long)(_regs)->regs[15])
...@@ -140,6 +114,4 @@ static inline unsigned long profile_pc(struct pt_regs *regs) ...@@ -140,6 +114,4 @@ static inline unsigned long profile_pc(struct pt_regs *regs)
#define profile_pc profile_pc #define profile_pc profile_pc
#include <asm-generic/ptrace.h> #include <asm-generic/ptrace.h>
#endif /* __KERNEL__ */
#endif /* __ASM_SH_PTRACE_H */ #endif /* __ASM_SH_PTRACE_H */
#ifndef __ASM_SH_PTRACE_32_H #ifndef __ASM_SH_PTRACE_32_H
#define __ASM_SH_PTRACE_32_H #define __ASM_SH_PTRACE_32_H
/* #include <uapi/asm/ptrace_32.h>
* GCC defines register number like this:
* -----------------------------
* 0 - 15 are integer registers
* 17 - 22 are control/special registers
* 24 - 39 fp registers
* 40 - 47 xd registers
* 48 - fpscr register
* -----------------------------
*
* We follows above, except:
* 16 --- program counter (PC)
* 22 --- syscall #
* 23 --- floating point communication register
*/
#define REG_REG0 0
#define REG_REG15 15
#define REG_PC 16
#define REG_PR 17
#define REG_SR 18
#define REG_GBR 19
#define REG_MACH 20
#define REG_MACL 21
#define REG_SYSCALL 22
#define REG_FPREG0 23
#define REG_FPREG15 38
#define REG_XFREG0 39
#define REG_XFREG15 54
#define REG_FPSCR 55
#define REG_FPUL 56
/*
* This struct defines the way the registers are stored on the
* kernel stack during a system call or other kernel entry.
*/
struct pt_regs {
unsigned long regs[16];
unsigned long pc;
unsigned long pr;
unsigned long sr;
unsigned long gbr;
unsigned long mach;
unsigned long macl;
long tra;
};
/*
* This struct defines the way the DSP registers are stored on the
* kernel stack during a system call or other kernel entry.
*/
struct pt_dspregs {
unsigned long a1;
unsigned long a0g;
unsigned long a1g;
unsigned long m0;
unsigned long m1;
unsigned long a0;
unsigned long x0;
unsigned long x1;
unsigned long y0;
unsigned long y1;
unsigned long dsr;
unsigned long rs;
unsigned long re;
unsigned long mod;
};
#ifdef __KERNEL__
#define MAX_REG_OFFSET offsetof(struct pt_regs, tra) #define MAX_REG_OFFSET offsetof(struct pt_regs, tra)
static inline long regs_return_value(struct pt_regs *regs) static inline long regs_return_value(struct pt_regs *regs)
...@@ -81,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs) ...@@ -81,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs)
return regs->regs[0]; return regs->regs[0];
} }
#endif /* __KERNEL__ */
#endif /* __ASM_SH_PTRACE_32_H */ #endif /* __ASM_SH_PTRACE_32_H */
#ifndef __ASM_SH_PTRACE_64_H #ifndef __ASM_SH_PTRACE_64_H
#define __ASM_SH_PTRACE_64_H #define __ASM_SH_PTRACE_64_H
struct pt_regs { #include <uapi/asm/ptrace_64.h>
unsigned long long pc;
unsigned long long sr;
long long syscall_nr;
unsigned long long regs[63];
unsigned long long tregs[8];
unsigned long long pad[2];
};
#ifdef __KERNEL__
#define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7]) #define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7])
static inline long regs_return_value(struct pt_regs *regs) static inline long regs_return_value(struct pt_regs *regs)
...@@ -18,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs) ...@@ -18,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs)
return regs->regs[3]; return regs->regs[3];
} }
#endif /* __KERNEL__ */
#endif /* __ASM_SH_PTRACE_64_H */ #endif /* __ASM_SH_PTRACE_64_H */
#ifndef _SH_SETUP_H #ifndef _SH_SETUP_H
#define _SH_SETUP_H #define _SH_SETUP_H
#include <asm-generic/setup.h> #include <uapi/asm/setup.h>
#ifdef __KERNEL__
/* /*
* This is set up by the setup-routine at boot-time * This is set up by the setup-routine at boot-time
*/ */
...@@ -22,6 +21,4 @@ void sh_mv_setup(void); ...@@ -22,6 +21,4 @@ void sh_mv_setup(void);
void check_for_initrd(void); void check_for_initrd(void);
void per_cpu_trap_init(void); void per_cpu_trap_init(void);
#endif /* __KERNEL__ */
#endif /* _SH_SETUP_H */ #endif /* _SH_SETUP_H */
#ifndef __ASM_SH_TYPES_H #ifndef __ASM_SH_TYPES_H
#define __ASM_SH_TYPES_H #define __ASM_SH_TYPES_H
#include <asm-generic/types.h> #include <uapi/asm/types.h>
/* /*
* These aren't exported outside the kernel to avoid name space clashes * These aren't exported outside the kernel to avoid name space clashes
*/ */
#ifdef __KERNEL__
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#ifdef CONFIG_SUPERH32 #ifdef CONFIG_SUPERH32
...@@ -18,6 +17,4 @@ typedef u64 reg_size_t; ...@@ -18,6 +17,4 @@ typedef u64 reg_size_t;
#endif #endif
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* __ASM_SH_TYPES_H */ #endif /* __ASM_SH_TYPES_H */
#ifdef __KERNEL__
# ifdef CONFIG_SUPERH32 # ifdef CONFIG_SUPERH32
# include <asm/unistd_32.h> # include <asm/unistd_32.h>
# else # else
...@@ -38,10 +37,4 @@ ...@@ -38,10 +37,4 @@
*/ */
# define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") # define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#else #include <uapi/asm/unistd.h>
# ifdef __SH5__
# include <asm/unistd_64.h>
# else
# include <asm/unistd_32.h>
# endif
#endif
# UAPI Header export list # UAPI Header export list
include include/uapi/asm-generic/Kbuild.asm include include/uapi/asm-generic/Kbuild.asm
header-y += auxvec.h
header-y += byteorder.h
header-y += cachectl.h
header-y += cpu-features.h
header-y += hw_breakpoint.h
header-y += ioctls.h
header-y += posix_types.h
header-y += posix_types_32.h
header-y += posix_types_64.h
header-y += ptrace.h
header-y += ptrace_32.h
header-y += ptrace_64.h
header-y += setup.h
header-y += sigcontext.h
header-y += signal.h
header-y += sockios.h
header-y += stat.h
header-y += swab.h
header-y += types.h
header-y += unistd.h
header-y += unistd_32.h
header-y += unistd_64.h
#ifndef __KERNEL__
# ifdef __SH5__
# include <asm/posix_types_64.h>
# else
# include <asm/posix_types_32.h>
# endif
#endif /* __KERNEL__ */
/*
* Copyright (C) 1999, 2000 Niibe Yutaka
*/
#ifndef _UAPI__ASM_SH_PTRACE_H
#define _UAPI__ASM_SH_PTRACE_H
#define PTRACE_GETREGS 12 /* General registers */
#define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14 /* FPU registers */
#define PTRACE_SETFPREGS 15
#define PTRACE_GETFDPIC 31 /* get the ELF fdpic loadmap address */
#define PTRACE_GETFDPIC_EXEC 0 /* [addr] request the executable loadmap */
#define PTRACE_GETFDPIC_INTERP 1 /* [addr] request the interpreter loadmap */
#define PTRACE_GETDSPREGS 55 /* DSP registers */
#define PTRACE_SETDSPREGS 56
#define PT_TEXT_END_ADDR 240
#define PT_TEXT_ADDR 244 /* &(struct user)->start_code */
#define PT_DATA_ADDR 248 /* &(struct user)->start_data */
#define PT_TEXT_LEN 252
#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
#include <asm/ptrace_64.h>
#else
#include <asm/ptrace_32.h>
#endif
#endif /* _UAPI__ASM_SH_PTRACE_H */
#ifndef _UAPI__ASM_SH_PTRACE_32_H
#define _UAPI__ASM_SH_PTRACE_32_H
/*
* GCC defines register number like this:
* -----------------------------
* 0 - 15 are integer registers
* 17 - 22 are control/special registers
* 24 - 39 fp registers
* 40 - 47 xd registers
* 48 - fpscr register
* -----------------------------
*
* We follows above, except:
* 16 --- program counter (PC)
* 22 --- syscall #
* 23 --- floating point communication register
*/
#define REG_REG0 0
#define REG_REG15 15
#define REG_PC 16
#define REG_PR 17
#define REG_SR 18
#define REG_GBR 19
#define REG_MACH 20
#define REG_MACL 21
#define REG_SYSCALL 22
#define REG_FPREG0 23
#define REG_FPREG15 38
#define REG_XFREG0 39
#define REG_XFREG15 54
#define REG_FPSCR 55
#define REG_FPUL 56
/*
* This struct defines the way the registers are stored on the
* kernel stack during a system call or other kernel entry.
*/
struct pt_regs {
unsigned long regs[16];
unsigned long pc;
unsigned long pr;
unsigned long sr;
unsigned long gbr;
unsigned long mach;
unsigned long macl;
long tra;
};
/*
* This struct defines the way the DSP registers are stored on the
* kernel stack during a system call or other kernel entry.
*/
struct pt_dspregs {
unsigned long a1;
unsigned long a0g;
unsigned long a1g;
unsigned long m0;
unsigned long m1;
unsigned long a0;
unsigned long x0;
unsigned long x1;
unsigned long y0;
unsigned long y1;
unsigned long dsr;
unsigned long rs;
unsigned long re;
unsigned long mod;
};
#endif /* _UAPI__ASM_SH_PTRACE_32_H */
#ifndef _UAPI__ASM_SH_PTRACE_64_H
#define _UAPI__ASM_SH_PTRACE_64_H
struct pt_regs {
unsigned long long pc;
unsigned long long sr;
long long syscall_nr;
unsigned long long regs[63];
unsigned long long tregs[8];
unsigned long long pad[2];
};
#endif /* _UAPI__ASM_SH_PTRACE_64_H */
#include <asm-generic/setup.h>
#include <asm-generic/types.h>
#ifndef __KERNEL__
# ifdef __SH5__
# include <asm/unistd_64.h>
# else
# include <asm/unistd_32.h>
# endif
#endif
...@@ -378,7 +378,8 @@ ...@@ -378,7 +378,8 @@
#define __NR_setns 364 #define __NR_setns 364
#define __NR_process_vm_readv 365 #define __NR_process_vm_readv 365
#define __NR_process_vm_writev 366 #define __NR_process_vm_writev 366
#define __NR_kcmp 367
#define NR_syscalls 367 #define NR_syscalls 368
#endif /* __ASM_SH_UNISTD_32_H */ #endif /* __ASM_SH_UNISTD_32_H */
...@@ -398,7 +398,8 @@ ...@@ -398,7 +398,8 @@
#define __NR_setns 375 #define __NR_setns 375
#define __NR_process_vm_readv 376 #define __NR_process_vm_readv 376
#define __NR_process_vm_writev 377 #define __NR_process_vm_writev 377
#define __NR_kcmp 378
#define NR_syscalls 378 #define NR_syscalls 379
#endif /* __ASM_SH_UNISTD_64_H */ #endif /* __ASM_SH_UNISTD_64_H */
...@@ -384,3 +384,4 @@ ENTRY(sys_call_table) ...@@ -384,3 +384,4 @@ ENTRY(sys_call_table)
.long sys_setns .long sys_setns
.long sys_process_vm_readv /* 365 */ .long sys_process_vm_readv /* 365 */
.long sys_process_vm_writev .long sys_process_vm_writev
.long sys_kcmp
...@@ -404,3 +404,4 @@ sys_call_table: ...@@ -404,3 +404,4 @@ sys_call_table:
.long sys_setns /* 375 */ .long sys_setns /* 375 */
.long sys_process_vm_readv .long sys_process_vm_readv
.long sys_process_vm_writev .long sys_process_vm_writev
.long sys_kcmp
...@@ -75,54 +75,61 @@ unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle ...@@ -75,54 +75,61 @@ unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle
static unsigned long test_8(unsigned long addr, unsigned long h, static unsigned long test_8(unsigned long addr, unsigned long h,
unsigned long ignore) unsigned long ignore)
{ {
return intc_get_field_from_handle(__raw_readb(addr), h); void __iomem *ptr = (void __iomem *)addr;
return intc_get_field_from_handle(__raw_readb(ptr), h);
} }
static unsigned long test_16(unsigned long addr, unsigned long h, static unsigned long test_16(unsigned long addr, unsigned long h,
unsigned long ignore) unsigned long ignore)
{ {
return intc_get_field_from_handle(__raw_readw(addr), h); void __iomem *ptr = (void __iomem *)addr;
return intc_get_field_from_handle(__raw_readw(ptr), h);
} }
static unsigned long test_32(unsigned long addr, unsigned long h, static unsigned long test_32(unsigned long addr, unsigned long h,
unsigned long ignore) unsigned long ignore)
{ {
return intc_get_field_from_handle(__raw_readl(addr), h); void __iomem *ptr = (void __iomem *)addr;
return intc_get_field_from_handle(__raw_readl(ptr), h);
} }
static unsigned long write_8(unsigned long addr, unsigned long h, static unsigned long write_8(unsigned long addr, unsigned long h,
unsigned long data) unsigned long data)
{ {
__raw_writeb(intc_set_field_from_handle(0, data, h), addr); void __iomem *ptr = (void __iomem *)addr;
(void)__raw_readb(addr); /* Defeat write posting */ __raw_writeb(intc_set_field_from_handle(0, data, h), ptr);
(void)__raw_readb(ptr); /* Defeat write posting */
return 0; return 0;
} }
static unsigned long write_16(unsigned long addr, unsigned long h, static unsigned long write_16(unsigned long addr, unsigned long h,
unsigned long data) unsigned long data)
{ {
__raw_writew(intc_set_field_from_handle(0, data, h), addr); void __iomem *ptr = (void __iomem *)addr;
(void)__raw_readw(addr); /* Defeat write posting */ __raw_writew(intc_set_field_from_handle(0, data, h), ptr);
(void)__raw_readw(ptr); /* Defeat write posting */
return 0; return 0;
} }
static unsigned long write_32(unsigned long addr, unsigned long h, static unsigned long write_32(unsigned long addr, unsigned long h,
unsigned long data) unsigned long data)
{ {
__raw_writel(intc_set_field_from_handle(0, data, h), addr); void __iomem *ptr = (void __iomem *)addr;
(void)__raw_readl(addr); /* Defeat write posting */ __raw_writel(intc_set_field_from_handle(0, data, h), ptr);
(void)__raw_readl(ptr); /* Defeat write posting */
return 0; return 0;
} }
static unsigned long modify_8(unsigned long addr, unsigned long h, static unsigned long modify_8(unsigned long addr, unsigned long h,
unsigned long data) unsigned long data)
{ {
void __iomem *ptr = (void __iomem *)addr;
unsigned long flags; unsigned long flags;
unsigned int value; unsigned int value;
local_irq_save(flags); local_irq_save(flags);
value = intc_set_field_from_handle(__raw_readb(addr), data, h); value = intc_set_field_from_handle(__raw_readb(ptr), data, h);
__raw_writeb(value, addr); __raw_writeb(value, ptr);
(void)__raw_readb(addr); /* Defeat write posting */ (void)__raw_readb(ptr); /* Defeat write posting */
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
} }
...@@ -130,12 +137,13 @@ static unsigned long modify_8(unsigned long addr, unsigned long h, ...@@ -130,12 +137,13 @@ static unsigned long modify_8(unsigned long addr, unsigned long h,
static unsigned long modify_16(unsigned long addr, unsigned long h, static unsigned long modify_16(unsigned long addr, unsigned long h,
unsigned long data) unsigned long data)
{ {
void __iomem *ptr = (void __iomem *)addr;
unsigned long flags; unsigned long flags;
unsigned int value; unsigned int value;
local_irq_save(flags); local_irq_save(flags);
value = intc_set_field_from_handle(__raw_readw(addr), data, h); value = intc_set_field_from_handle(__raw_readw(ptr), data, h);
__raw_writew(value, addr); __raw_writew(value, ptr);
(void)__raw_readw(addr); /* Defeat write posting */ (void)__raw_readw(ptr); /* Defeat write posting */
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
} }
...@@ -143,12 +151,13 @@ static unsigned long modify_16(unsigned long addr, unsigned long h, ...@@ -143,12 +151,13 @@ static unsigned long modify_16(unsigned long addr, unsigned long h,
static unsigned long modify_32(unsigned long addr, unsigned long h, static unsigned long modify_32(unsigned long addr, unsigned long h,
unsigned long data) unsigned long data)
{ {
void __iomem *ptr = (void __iomem *)addr;
unsigned long flags; unsigned long flags;
unsigned int value; unsigned int value;
local_irq_save(flags); local_irq_save(flags);
value = intc_set_field_from_handle(__raw_readl(addr), data, h); value = intc_set_field_from_handle(__raw_readl(ptr), data, h);
__raw_writel(value, addr); __raw_writel(value, ptr);
(void)__raw_readl(addr); /* Defeat write posting */ (void)__raw_readl(ptr); /* Defeat write posting */
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
} }
......
...@@ -83,7 +83,7 @@ static void intc_mask_ack(struct irq_data *data) ...@@ -83,7 +83,7 @@ static void intc_mask_ack(struct irq_data *data)
unsigned int irq = data->irq; unsigned int irq = data->irq;
struct intc_desc_int *d = get_intc_desc(irq); struct intc_desc_int *d = get_intc_desc(irq);
unsigned long handle = intc_get_ack_handle(irq); unsigned long handle = intc_get_ack_handle(irq);
unsigned long addr; void __iomem *addr;
intc_disable(data); intc_disable(data);
...@@ -91,7 +91,7 @@ static void intc_mask_ack(struct irq_data *data) ...@@ -91,7 +91,7 @@ static void intc_mask_ack(struct irq_data *data)
if (handle) { if (handle) {
unsigned int value; unsigned int value;
addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); addr = (void __iomem *)INTC_REG(d, _INTC_ADDR_D(handle), 0);
value = intc_set_field_from_handle(0, 1, handle); value = intc_set_field_from_handle(0, 1, handle);
switch (_INTC_FN(handle)) { switch (_INTC_FN(handle)) {
......
...@@ -530,7 +530,8 @@ static inline int sci_rxd_in(struct uart_port *port) ...@@ -530,7 +530,8 @@ static inline int sci_rxd_in(struct uart_port *port)
if (s->cfg->port_reg <= 0) if (s->cfg->port_reg <= 0)
return 1; return 1;
return !!__raw_readb(s->cfg->port_reg); /* Cast for ARM damage */
return !!__raw_readb((void __iomem *)s->cfg->port_reg);
} }
/* ********************************************************************** * /* ********************************************************************** *
......
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