Commit 1377e026 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://lia64.bkbits.net/to-linus-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents 6d588f51 cec5d408
...@@ -1374,7 +1374,7 @@ msgctl32 (int first, int second, void *uptr) ...@@ -1374,7 +1374,7 @@ msgctl32 (int first, int second, void *uptr)
break; break;
old_fs = get_fs(); old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
err = sys_msgctl(first, second, &m64); err = sys_msgctl(first, second, (struct msqid_ds *)&m64);
set_fs(old_fs); set_fs(old_fs);
break; break;
...@@ -1382,7 +1382,7 @@ msgctl32 (int first, int second, void *uptr) ...@@ -1382,7 +1382,7 @@ msgctl32 (int first, int second, void *uptr)
case MSG_STAT: case MSG_STAT:
old_fs = get_fs(); old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
err = sys_msgctl(first, second, (void *) &m64); err = sys_msgctl(first, second, (struct msqid_ds *)&m64);
set_fs(old_fs); set_fs(old_fs);
if (version == IPC_64) { if (version == IPC_64) {
...@@ -1518,7 +1518,7 @@ shmctl32 (int first, int second, void *uptr) ...@@ -1518,7 +1518,7 @@ shmctl32 (int first, int second, void *uptr)
break; break;
old_fs = get_fs(); old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
err = sys_shmctl(first, second, &s64); err = sys_shmctl(first, second, (struct shmid_ds *)&s64);
set_fs(old_fs); set_fs(old_fs);
break; break;
...@@ -1526,7 +1526,7 @@ shmctl32 (int first, int second, void *uptr) ...@@ -1526,7 +1526,7 @@ shmctl32 (int first, int second, void *uptr)
case SHM_STAT: case SHM_STAT:
old_fs = get_fs(); old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
err = sys_shmctl(first, second, (void *) &s64); err = sys_shmctl(first, second, (struct shmid_ds *)&s64);
set_fs(old_fs); set_fs(old_fs);
if (err < 0) if (err < 0)
break; break;
...@@ -1694,6 +1694,10 @@ sys32_time (int *tloc) ...@@ -1694,6 +1694,10 @@ sys32_time (int *tloc)
return i; return i;
} }
asmlinkage long
compat_sys_wait4 (compat_pid_t pid, compat_uint_t * stat_addr, int options,
struct compat_rusage *ru);
asmlinkage long asmlinkage long
sys32_waitpid (int pid, unsigned int *stat_addr, int options) sys32_waitpid (int pid, unsigned int *stat_addr, int options)
{ {
......
...@@ -168,7 +168,6 @@ efivar_create_proc_entry(unsigned long variable_name_size, ...@@ -168,7 +168,6 @@ efivar_create_proc_entry(unsigned long variable_name_size,
efi_char16_t *variable_name, efi_char16_t *variable_name,
efi_guid_t *vendor_guid) efi_guid_t *vendor_guid)
{ {
int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
char *short_name; char *short_name;
efivar_entry_t *new_efivar; efivar_entry_t *new_efivar;
...@@ -344,12 +343,73 @@ efivar_write(struct file *file, const char *buffer, ...@@ -344,12 +343,73 @@ efivar_write(struct file *file, const char *buffer,
return size; return size;
} }
/*
* The EFI system table contains pointers to the SAL system table,
* HCDP, ACPI, SMBIOS, etc, that may be useful to applications.
*/
static ssize_t
efi_systab_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
void *data;
u8 *proc_buffer;
ssize_t size, length;
int ret;
const int max_nr_entries = 7; /* num ptrs to tables we could expose */
const int max_line_len = 80;
if (!efi.systab)
return 0;
proc_buffer = kmalloc(max_nr_entries * max_line_len, GFP_KERNEL);
if (!proc_buffer)
return -ENOMEM;
length = 0;
if (efi.mps)
length += sprintf(proc_buffer + length, "MPS=0x%lx\n", __pa(efi.mps));
if (efi.acpi20)
length += sprintf(proc_buffer + length, "ACPI20=0x%lx\n", __pa(efi.acpi20));
if (efi.acpi)
length += sprintf(proc_buffer + length, "ACPI=0x%lx\n", __pa(efi.acpi));
if (efi.smbios)
length += sprintf(proc_buffer + length, "SMBIOS=0x%lx\n", __pa(efi.smbios));
if (efi.sal_systab)
length += sprintf(proc_buffer + length, "SAL=0x%lx\n", __pa(efi.sal_systab));
if (efi.hcdp)
length += sprintf(proc_buffer + length, "HCDP=0x%lx\n", __pa(efi.hcdp));
if (efi.boot_info)
length += sprintf(proc_buffer + length, "BOOTINFO=0x%lx\n", __pa(efi.boot_info));
if (*ppos >= length) {
ret = 0;
goto out;
}
data = proc_buffer + file->f_pos;
size = length - file->f_pos;
if (size > count)
size = count;
if (copy_to_user(buffer, data, size)) {
ret = -EFAULT;
goto out;
}
*ppos += size;
ret = size;
out:
kfree(proc_buffer);
return ret;
}
static struct proc_dir_entry *efi_systab_entry;
static struct file_operations efi_systab_fops = {
.read = efi_systab_read,
};
static int __init static int __init
efivars_init(void) efivars_init(void)
{ {
efi_status_t status; efi_status_t status;
efi_guid_t vendor_guid; efi_guid_t vendor_guid;
efi_char16_t *variable_name = kmalloc(1024, GFP_KERNEL); efi_char16_t *variable_name = kmalloc(1024, GFP_KERNEL);
...@@ -365,6 +425,10 @@ efivars_init(void) ...@@ -365,6 +425,10 @@ efivars_init(void)
if (!efi_dir) if (!efi_dir)
efi_dir = proc_mkdir("efi", NULL); efi_dir = proc_mkdir("efi", NULL);
efi_systab_entry = create_proc_entry("systab", S_IRUSR | S_IRGRP, efi_dir);
if (efi_systab_entry)
efi_systab_entry->proc_fops = &efi_systab_fops;
efi_vars_dir = proc_mkdir("vars", efi_dir); efi_vars_dir = proc_mkdir("vars", efi_dir);
/* Per EFI spec, the maximum storage allocated for both /* Per EFI spec, the maximum storage allocated for both
...@@ -408,6 +472,8 @@ efivars_exit(void) ...@@ -408,6 +472,8 @@ efivars_exit(void)
efivar_entry_t *efivar; efivar_entry_t *efivar;
spin_lock(&efivars_lock); spin_lock(&efivars_lock);
if (efi_systab_entry)
remove_proc_entry(efi_systab_entry->name, efi_dir);
list_for_each_safe(pos, n, &efivar_list) { list_for_each_safe(pos, n, &efivar_list) {
efivar = efivar_entry(pos); efivar = efivar_entry(pos);
remove_proc_entry(efivar->entry->name, efi_vars_dir); remove_proc_entry(efivar->entry->name, efi_vars_dir);
......
...@@ -113,7 +113,7 @@ END(ia64_execve) ...@@ -113,7 +113,7 @@ END(ia64_execve)
* u64 tls) * u64 tls)
*/ */
GLOBAL_ENTRY(sys_clone2) GLOBAL_ENTRY(sys_clone2)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6)
alloc r16=ar.pfs,6,2,6,0 alloc r16=ar.pfs,6,2,6,0
DO_SAVE_SWITCH_STACK DO_SAVE_SWITCH_STACK
adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp
...@@ -142,7 +142,7 @@ END(sys_clone2) ...@@ -142,7 +142,7 @@ END(sys_clone2)
* Deprecated. Use sys_clone2() instead. * Deprecated. Use sys_clone2() instead.
*/ */
GLOBAL_ENTRY(sys_clone) GLOBAL_ENTRY(sys_clone)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
alloc r16=ar.pfs,5,2,6,0 alloc r16=ar.pfs,5,2,6,0
DO_SAVE_SWITCH_STACK DO_SAVE_SWITCH_STACK
adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp
......
...@@ -115,6 +115,7 @@ static struct irqaction mca_wkup_irqaction = { ...@@ -115,6 +115,7 @@ static struct irqaction mca_wkup_irqaction = {
.name = "mca_wkup" .name = "mca_wkup"
}; };
#ifdef CONFIG_ACPI
static struct irqaction mca_cpe_irqaction = { static struct irqaction mca_cpe_irqaction = {
.handler = ia64_mca_cpe_int_handler, .handler = ia64_mca_cpe_int_handler,
.flags = SA_INTERRUPT, .flags = SA_INTERRUPT,
...@@ -126,6 +127,7 @@ static struct irqaction mca_cpep_irqaction = { ...@@ -126,6 +127,7 @@ static struct irqaction mca_cpep_irqaction = {
.flags = SA_INTERRUPT, .flags = SA_INTERRUPT,
.name = "cpe_poll" .name = "cpe_poll"
}; };
#endif /* CONFIG_ACPI */
#define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */ #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */
#define MIN_CPE_POLL_INTERVAL (2*60*HZ) /* 2 minutes */ #define MIN_CPE_POLL_INTERVAL (2*60*HZ) /* 2 minutes */
...@@ -434,6 +436,7 @@ ia64_mca_check_errors (void) ...@@ -434,6 +436,7 @@ ia64_mca_check_errors (void)
device_initcall(ia64_mca_check_errors); device_initcall(ia64_mca_check_errors);
#ifdef CONFIG_ACPI
/* /*
* ia64_mca_register_cpev * ia64_mca_register_cpev
* *
...@@ -458,6 +461,7 @@ ia64_mca_register_cpev (int cpev) ...@@ -458,6 +461,7 @@ ia64_mca_register_cpev (int cpev)
IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error " IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error "
"vector %#x setup and enabled\n", cpev); "vector %#x setup and enabled\n", cpev);
} }
#endif /* CONFIG_ACPI */
#endif /* PLATFORM_MCA_HANDLERS */ #endif /* PLATFORM_MCA_HANDLERS */
...@@ -750,6 +754,7 @@ ia64_mca_init(void) ...@@ -750,6 +754,7 @@ ia64_mca_init(void)
/* Setup the MCA wakeup interrupt vector */ /* Setup the MCA wakeup interrupt vector */
register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
#ifdef CONFIG_ACPI
/* Setup the CPE interrupt vector */ /* Setup the CPE interrupt vector */
{ {
irq_desc_t *desc; irq_desc_t *desc;
...@@ -767,6 +772,7 @@ ia64_mca_init(void) ...@@ -767,6 +772,7 @@ ia64_mca_init(void)
ia64_mca_register_cpev(cpev); ia64_mca_register_cpev(cpev);
} }
} }
#endif
/* Initialize the areas set aside by the OS to buffer the /* Initialize the areas set aside by the OS to buffer the
* platform/processor error states for MCA/INIT/CMC * platform/processor error states for MCA/INIT/CMC
...@@ -1279,11 +1285,13 @@ ia64_mca_late_init(void) ...@@ -1279,11 +1285,13 @@ ia64_mca_late_init(void)
init_timer(&cpe_poll_timer); init_timer(&cpe_poll_timer);
cpe_poll_timer.function = ia64_mca_cpe_poll; cpe_poll_timer.function = ia64_mca_cpe_poll;
#ifdef CONFIG_ACPI
/* If platform doesn't support CPEI, get the timer going. */ /* If platform doesn't support CPEI, get the timer going. */
if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) { if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) {
register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
ia64_mca_cpe_poll(0UL); ia64_mca_cpe_poll(0UL);
} }
#endif
return 0; return 0;
} }
...@@ -1398,6 +1406,9 @@ ia64_log_init(int sal_info_type) ...@@ -1398,6 +1406,9 @@ ia64_log_init(int sal_info_type)
// SAL will tell us the maximum size of any error record of this type // SAL will tell us the maximum size of any error record of this type
max_size = ia64_sal_get_state_info_size(sal_info_type); max_size = ia64_sal_get_state_info_size(sal_info_type);
if (!max_size)
/* alloc_bootmem() doesn't like zero-sized allocations! */
return;
// set up OS data structures to hold error info // set up OS data structures to hold error info
IA64_LOG_ALLOCATE(sal_info_type, max_size); IA64_LOG_ALLOCATE(sal_info_type, max_size);
......
...@@ -45,7 +45,7 @@ void ...@@ -45,7 +45,7 @@ void
ia64_do_show_stack (struct unw_frame_info *info, void *arg) ia64_do_show_stack (struct unw_frame_info *info, void *arg)
{ {
unsigned long ip, sp, bsp; unsigned long ip, sp, bsp;
char buf[80]; /* don't make it so big that it overflows the stack! */ char buf[128]; /* don't make it so big that it overflows the stack! */
printk("\nCall Trace:\n"); printk("\nCall Trace:\n");
do { do {
...@@ -55,7 +55,9 @@ ia64_do_show_stack (struct unw_frame_info *info, void *arg) ...@@ -55,7 +55,9 @@ ia64_do_show_stack (struct unw_frame_info *info, void *arg)
unw_get_sp(info, &sp); unw_get_sp(info, &sp);
unw_get_bsp(info, &bsp); unw_get_bsp(info, &bsp);
snprintf(buf, sizeof(buf), " [<%016lx>] %%s\n\t\t\t\tsp=%016lx bsp=%016lx\n", snprintf(buf, sizeof(buf),
" [<%016lx>] %%s\n"
" sp=%016lx bsp=%016lx\n",
ip, sp, bsp); ip, sp, bsp);
print_symbol(buf, ip); print_symbol(buf, ip);
} while (unw_unwind(info) >= 0); } while (unw_unwind(info) >= 0);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/sn/sgi.h> #include <asm/sn/sgi.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/topology.h>
#include <asm/sn/intr.h> #include <asm/sn/intr.h>
#include <asm/sn/router.h> #include <asm/sn/router.h>
#include <asm/sn/pda.h> #include <asm/sn/pda.h>
...@@ -127,7 +128,7 @@ typedef struct irqpda_s irqpda_t; ...@@ -127,7 +128,7 @@ typedef struct irqpda_s irqpda_t;
* Check if given a compact node id the corresponding node has all the * Check if given a compact node id the corresponding node has all the
* cpus disabled. * cpus disabled.
*/ */
#define is_headless_node(cnode) (!test_bit(cnode, &node_has_active_cpus)) #define is_headless_node(cnode) (!node_to_cpumask(cnode))
/* /*
* Check if given a node vertex handle the corresponding node has all the * Check if given a node vertex handle the corresponding node has all the
......
...@@ -257,96 +257,138 @@ ...@@ -257,96 +257,138 @@
extern long __ia64_syscall (long a0, long a1, long a2, long a3, long a4, long nr); extern long __ia64_syscall (long a0, long a1, long a2, long a3, long a4, long nr);
#define _syscall0(type,name) \ #ifdef __KERNEL_SYSCALLS__
type \
name (void) \ #include <linux/string.h>
{ \ #include <linux/signal.h>
register long dummy1 __asm__ ("out0"); \ #include <asm/ptrace.h>
register long dummy2 __asm__ ("out1"); \ #include <linux/stringify.h>
register long dummy3 __asm__ ("out2"); \
register long dummy4 __asm__ ("out3"); \ static inline long
register long dummy5 __asm__ ("out4"); \ open (const char * name, int mode, int flags)
\ {
return __ia64_syscall(dummy1, dummy2, dummy3, dummy4, dummy5, \ extern long sys_open (const char *, int, int);
__NR_##name); \ return sys_open(name, mode, flags);
}
static inline long
dup (int fd)
{
extern long sys_dup (int);
return sys_dup(fd);
} }
#define _syscall1(type,name,type1,arg1) \ static inline long
type \ close (int fd)
name (type1 arg1) \ {
{ \ extern long sys_close(unsigned int);
register long dummy2 __asm__ ("out1"); \ return sys_close(fd);
register long dummy3 __asm__ ("out2"); \
register long dummy4 __asm__ ("out3"); \
register long dummy5 __asm__ ("out4"); \
\
return __ia64_syscall((long) arg1, dummy2, dummy3, dummy4, \
dummy5, __NR_##name); \
} }
#define _syscall2(type,name,type1,arg1,type2,arg2) \ static inline off_t
type \ lseek (int fd, off_t off, int whence)
name (type1 arg1, type2 arg2) \ {
{ \ extern off_t sys_lseek (int, off_t, int);
register long dummy3 __asm__ ("out2"); \ return sys_lseek(fd, off, whence);
register long dummy4 __asm__ ("out3"); \
register long dummy5 __asm__ ("out4"); \
\
return __ia64_syscall((long) arg1, (long) arg2, dummy3, dummy4, \
dummy5, __NR_##name); \
} }
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ static inline long
type \ _exit (int value)
name (type1 arg1, type2 arg2, type3 arg3) \ {
{ \ extern long sys_exit (int);
register long dummy4 __asm__ ("out3"); \ return sys_exit(value);
register long dummy5 __asm__ ("out4"); \
\
return __ia64_syscall((long) arg1, (long) arg2, (long) arg3, \
dummy4, dummy5, __NR_##name); \
} }
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ #define exit(x) _exit(x)
type \
name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ static inline long
{ \ write (int fd, const char * buf, size_t nr)
register long dummy5 __asm__ ("out4"); \ {
\ extern long sys_write (int, const char *, size_t);
return __ia64_syscall((long) arg1, (long) arg2, (long) arg3, \ return sys_write(fd, buf, nr);
(long) arg4, dummy5, __NR_##name); \
} }
#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ static inline long
type \ read (int fd, char * buf, size_t nr)
name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ {
{ \ extern long sys_read (int, char *, size_t);
return __ia64_syscall((long) arg1, (long) arg2, (long) arg3, \ return sys_read(fd, buf, nr);
(long) arg4, (long) arg5, __NR_##name); \
} }
#ifdef __KERNEL_SYSCALLS__
static inline long
setsid (void)
{
extern long sys_setsid (void);
return sys_setsid();
}
struct rusage; struct rusage;
static inline _syscall0(pid_t,setsid) static inline pid_t
static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count) waitpid (int pid, int * wait_stat, int flags)
static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) {
static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count) extern asmlinkage long sys_wait4 (pid_t, unsigned int *, int, struct rusage *);
static inline _syscall1(int,dup,int,fd)
static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp) return sys_wait4(pid, wait_stat, flags, NULL);
static inline _syscall3(int,open,const char *,file,int,flag,int,mode) }
static inline _syscall1(int,close,int,fd)
static inline _syscall4(pid_t,wait4,pid_t,pid,int *,wait_stat,int,options,struct rusage*, rusage)
static inline _syscall2(pid_t,clone,unsigned long,flags,void*,sp);
#define __NR__exit __NR_exit
static inline _syscall1(int,_exit,int,exitcode) static inline int
execve (const char *filename, char *const av[], char *const ep[])
{
register long r8 asm("r8");
register long r10 asm("r10");
register long r15 asm("r15") = __NR_execve;
register long out0 asm("out0") = (long)filename;
register long out1 asm("out1") = (long)av;
register long out2 asm("out2") = (long)ep;
asm volatile ("break " __stringify(__BREAK_SYSCALL) ";;\n\t"
: "=r" (r8), "=r" (r10), "=r" (r15), "=r" (out0), "=r" (out1), "=r" (out2)
: "2" (r15), "3" (out0), "4" (out1), "5" (out2)
: "memory", "out3", "out4", "out5", "out6", "out7",
/* Non-stacked integer registers, minus r8, r10, r15, r13 */
"r2", "r3", "r9", "r11", "r12", "r14", "r16", "r17", "r18",
"r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",
"r28", "r29", "r30", "r31",
/* Predicate registers. */
"p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",
/* Non-rotating fp registers. */
"f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
/* Branch registers. */
"b6", "b7" );
return r8;
}
static inline pid_t static inline pid_t
waitpid (int pid, int *wait_stat, int flags) clone (unsigned long flags, void *sp)
{ {
return wait4(pid, wait_stat, flags, NULL); register long r8 asm("r8");
register long r10 asm("r10");
register long r15 asm("r15") = __NR_clone;
register long out0 asm("out0") = (long)flags;
register long out1 asm("out1") = (long)sp;
long retval;
/* clone clobbers current, hence the "r13" in the clobbers list */
asm volatile ( "break " __stringify(__BREAK_SYSCALL) ";;\n\t"
: "=r" (r8), "=r" (r10), "=r" (r15), "=r" (out0), "=r" (out1)
: "2" (r15), "3" (out0), "4" (out1)
: "memory", "out2", "out3", "out4", "out5", "out6", "out7", "r13",
/* Non-stacked integer registers, minus r8, r10, r15, r13 */
"r2", "r3", "r9", "r11", "r12", "r14", "r16", "r17", "r18",
"r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",
"r28", "r29", "r30", "r31",
/* Predicate registers. */
"p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",
/* Non-rotating fp registers. */
"f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
/* Branch registers. */
"b6", "b7" );
retval = r8;
return retval;;
} }
#endif /* __KERNEL_SYSCALLS__ */ #endif /* __KERNEL_SYSCALLS__ */
......
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