[IA64] multi-core/multi-thread identification
Version 3 - rediffed to apply on top of Ashok's hotplug cpu patch. /proc/cpuinfo output in step with x86. This is an updated MC/MT identification patch based on the previous discussions on list. Add the Multi-core and Multi-threading detection for IPF. - Add new core and threading related fields in /proc/cpuinfo. Physical id Core id Thread id Siblings - setup the cpu_core_map and cpu_sibling_map appropriately - Handles Hot plug CPU Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: Gordon Jin <gordon.jin@intel.com> Signed-off-by: Rohit Seth <rohit.seth@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
This commit is contained in:
parent
6118ec847e
commit
e927ecb05e
@ -4,10 +4,15 @@
|
||||
* Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
* Stephane Eranian <eranian@hpl.hp.com>
|
||||
* Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
|
||||
* Copyright (C) 2000, 2004 Intel Corp
|
||||
* Rohit Seth <rohit.seth@intel.com>
|
||||
* Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
* Gordon Jin <gordon.jin@intel.com>
|
||||
* Copyright (C) 1999 VA Linux Systems
|
||||
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
|
||||
*
|
||||
* 12/26/04 S.Siddha, G.Jin, R.Seth
|
||||
* Add multi-threading and multi-core detection
|
||||
* 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo().
|
||||
* 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map
|
||||
* 03/31/00 R.Seth cpu_initialized and current->processor fixes
|
||||
@ -296,6 +301,34 @@ mark_bsp_online (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void
|
||||
check_for_logical_procs (void)
|
||||
{
|
||||
pal_logical_to_physical_t info;
|
||||
s64 status;
|
||||
|
||||
status = ia64_pal_logical_to_phys(0, &info);
|
||||
if (status == -1) {
|
||||
printk(KERN_INFO "No logical to physical processor mapping "
|
||||
"available\n");
|
||||
return;
|
||||
}
|
||||
if (status) {
|
||||
printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
|
||||
status);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Total number of siblings that BSP has. Though not all of them
|
||||
* may have booted successfully. The correct number of siblings
|
||||
* booted is in info.overview_num_log.
|
||||
*/
|
||||
smp_num_siblings = info.overview_tpc;
|
||||
smp_num_cpucores = info.overview_cpp;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init
|
||||
setup_arch (char **cmdline_p)
|
||||
{
|
||||
@ -356,6 +389,19 @@ setup_arch (char **cmdline_p)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
cpu_physical_id(0) = hard_smp_processor_id();
|
||||
|
||||
cpu_set(0, cpu_sibling_map[0]);
|
||||
cpu_set(0, cpu_core_map[0]);
|
||||
|
||||
check_for_logical_procs();
|
||||
if (smp_num_cpucores > 1)
|
||||
printk(KERN_INFO
|
||||
"cpu package is Multi-Core capable: number of cores=%d\n",
|
||||
smp_num_cpucores);
|
||||
if (smp_num_siblings > 1)
|
||||
printk(KERN_INFO
|
||||
"cpu package is Multi-Threading capable: number of siblings=%d\n",
|
||||
smp_num_siblings);
|
||||
#endif
|
||||
|
||||
cpu_init(); /* initialize the bootstrap CPU */
|
||||
@ -459,12 +505,23 @@ show_cpuinfo (struct seq_file *m, void *v)
|
||||
"cpu regs : %u\n"
|
||||
"cpu MHz : %lu.%06lu\n"
|
||||
"itc MHz : %lu.%06lu\n"
|
||||
"BogoMIPS : %lu.%02lu\n\n",
|
||||
"BogoMIPS : %lu.%02lu\n",
|
||||
cpunum, c->vendor, family, c->model, c->revision, c->archrev,
|
||||
features, c->ppn, c->number,
|
||||
c->proc_freq / 1000000, c->proc_freq % 1000000,
|
||||
c->itc_freq / 1000000, c->itc_freq % 1000000,
|
||||
lpj*HZ/500000, (lpj*HZ/5000) % 100);
|
||||
#ifdef CONFIG_SMP
|
||||
if (c->threads_per_core > 1 || c->cores_per_socket > 1)
|
||||
seq_printf(m,
|
||||
"physical id: %u\n"
|
||||
"core id : %u\n"
|
||||
"thread id : %u\n",
|
||||
c->socket_id, c->core_id, c->thread_id);
|
||||
seq_printf(m, "siblings : %u\n", c->num_log);
|
||||
#endif
|
||||
seq_printf(m,"\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -533,6 +590,14 @@ identify_cpu (struct cpuinfo_ia64 *c)
|
||||
memcpy(c->vendor, cpuid.field.vendor, 16);
|
||||
#ifdef CONFIG_SMP
|
||||
c->cpu = smp_processor_id();
|
||||
|
||||
/* below default values will be overwritten by identify_siblings()
|
||||
* for Multi-Threading/Multi-Core capable cpu's
|
||||
*/
|
||||
c->threads_per_core = c->cores_per_socket = c->num_log = 1;
|
||||
c->socket_id = -1;
|
||||
|
||||
identify_siblings(c);
|
||||
#endif
|
||||
c->ppn = cpuid.field.ppn;
|
||||
c->number = cpuid.field.number;
|
||||
|
@ -3,6 +3,11 @@
|
||||
*
|
||||
* Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
* Copyright (C) 2001, 2004-2005 Intel Corp
|
||||
* Rohit Seth <rohit.seth@intel.com>
|
||||
* Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
* Gordon Jin <gordon.jin@intel.com>
|
||||
* Ashok Raj <ashok.raj@intel.com>
|
||||
*
|
||||
* 01/05/16 Rohit Seth <rohit.seth@intel.com> Moved SMP booting functions from smp.c to here.
|
||||
* 01/04/27 David Mosberger <davidm@hpl.hp.com> Added ITC synching code.
|
||||
@ -10,6 +15,11 @@
|
||||
* smp_boot_cpus()/smp_commence() is replaced by
|
||||
* smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
|
||||
* 04/06/21 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
|
||||
* 04/12/26 Jin Gordon <gordon.jin@intel.com>
|
||||
* 04/12/26 Rohit Seth <rohit.seth@intel.com>
|
||||
* Add multi-threading and multi-core detection
|
||||
* 05/01/30 Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
* Setup cpu_sibling_map and cpu_core_map
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
|
||||
@ -122,6 +132,11 @@ EXPORT_SYMBOL(cpu_online_map);
|
||||
cpumask_t cpu_possible_map;
|
||||
EXPORT_SYMBOL(cpu_possible_map);
|
||||
|
||||
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
|
||||
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
|
||||
int smp_num_siblings = 1;
|
||||
int smp_num_cpucores = 1;
|
||||
|
||||
/* which logical CPU number maps to which CPU (physical APIC ID) */
|
||||
volatile int ia64_cpu_to_sapicid[NR_CPUS];
|
||||
EXPORT_SYMBOL(ia64_cpu_to_sapicid);
|
||||
@ -598,7 +613,68 @@ void __devinit smp_prepare_boot_cpu(void)
|
||||
cpu_set(smp_processor_id(), cpu_callin_map);
|
||||
}
|
||||
|
||||
/*
|
||||
* mt_info[] is a temporary store for all info returned by
|
||||
* PAL_LOGICAL_TO_PHYSICAL, to be copied into cpuinfo_ia64 when the
|
||||
* specific cpu comes.
|
||||
*/
|
||||
static struct {
|
||||
__u32 socket_id;
|
||||
__u16 core_id;
|
||||
__u16 thread_id;
|
||||
__u16 proc_fixed_addr;
|
||||
__u8 valid;
|
||||
}mt_info[NR_CPUS] __devinit;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static inline void
|
||||
remove_from_mtinfo(int cpu)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_cpu(i)
|
||||
if (mt_info[i].valid && mt_info[i].socket_id ==
|
||||
cpu_data(cpu)->socket_id)
|
||||
mt_info[i].valid = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
clear_cpu_sibling_map(int cpu)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_cpu_mask(i, cpu_sibling_map[cpu])
|
||||
cpu_clear(cpu, cpu_sibling_map[i]);
|
||||
for_each_cpu_mask(i, cpu_core_map[cpu])
|
||||
cpu_clear(cpu, cpu_core_map[i]);
|
||||
|
||||
cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_siblinginfo(int cpu)
|
||||
{
|
||||
int last = 0;
|
||||
|
||||
if (cpu_data(cpu)->threads_per_core == 1 &&
|
||||
cpu_data(cpu)->cores_per_socket == 1) {
|
||||
cpu_clear(cpu, cpu_core_map[cpu]);
|
||||
cpu_clear(cpu, cpu_sibling_map[cpu]);
|
||||
return;
|
||||
}
|
||||
|
||||
last = (cpus_weight(cpu_core_map[cpu]) == 1 ? 1 : 0);
|
||||
|
||||
/* remove it from all sibling map's */
|
||||
clear_cpu_sibling_map(cpu);
|
||||
|
||||
/* if this cpu is the last in the core group, remove all its info
|
||||
* from mt_info structure
|
||||
*/
|
||||
if (last)
|
||||
remove_from_mtinfo(cpu);
|
||||
}
|
||||
|
||||
extern void fixup_irqs(void);
|
||||
/* must be called with cpucontrol mutex held */
|
||||
int __cpu_disable(void)
|
||||
@ -611,6 +687,7 @@ int __cpu_disable(void)
|
||||
if (cpu == 0)
|
||||
return -EBUSY;
|
||||
|
||||
remove_siblinginfo(cpu);
|
||||
fixup_irqs();
|
||||
local_flush_tlb_all();
|
||||
cpu_clear(cpu, cpu_callin_map);
|
||||
@ -663,6 +740,23 @@ smp_cpus_done (unsigned int dummy)
|
||||
(int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
|
||||
}
|
||||
|
||||
static inline void __devinit
|
||||
set_cpu_sibling_map(int cpu)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_online_cpu(i) {
|
||||
if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) {
|
||||
cpu_set(i, cpu_core_map[cpu]);
|
||||
cpu_set(cpu, cpu_core_map[i]);
|
||||
if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
|
||||
cpu_set(i, cpu_sibling_map[cpu]);
|
||||
cpu_set(cpu, cpu_sibling_map[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __devinit
|
||||
__cpu_up (unsigned int cpu)
|
||||
{
|
||||
@ -685,6 +779,15 @@ __cpu_up (unsigned int cpu)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (cpu_data(cpu)->threads_per_core == 1 &&
|
||||
cpu_data(cpu)->cores_per_socket == 1) {
|
||||
cpu_set(cpu, cpu_sibling_map[cpu]);
|
||||
cpu_set(cpu, cpu_core_map[cpu]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_cpu_sibling_map(cpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -712,3 +815,106 @@ init_smp_config(void)
|
||||
ia64_sal_strerror(sal_ret));
|
||||
}
|
||||
|
||||
static inline int __devinit
|
||||
check_for_mtinfo_index(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for_each_cpu(i)
|
||||
if (!mt_info[i].valid)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search the mt_info to find out if this socket's cid/tid information is
|
||||
* cached or not. If the socket exists, fill in the core_id and thread_id
|
||||
* in cpuinfo
|
||||
*/
|
||||
static int __devinit
|
||||
check_for_new_socket(__u16 logical_address, struct cpuinfo_ia64 *c)
|
||||
{
|
||||
int i;
|
||||
__u32 sid = c->socket_id;
|
||||
|
||||
for_each_cpu(i) {
|
||||
if (mt_info[i].valid && mt_info[i].proc_fixed_addr == logical_address
|
||||
&& mt_info[i].socket_id == sid) {
|
||||
c->core_id = mt_info[i].core_id;
|
||||
c->thread_id = mt_info[i].thread_id;
|
||||
return 1; /* not a new socket */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* identify_siblings(cpu) gets called from identify_cpu. This populates the
|
||||
* information related to logical execution units in per_cpu_data structure.
|
||||
*/
|
||||
void __devinit
|
||||
identify_siblings(struct cpuinfo_ia64 *c)
|
||||
{
|
||||
s64 status;
|
||||
u16 pltid;
|
||||
u64 proc_fixed_addr;
|
||||
int count, i;
|
||||
pal_logical_to_physical_t info;
|
||||
|
||||
if (smp_num_cpucores == 1 && smp_num_siblings == 1)
|
||||
return;
|
||||
|
||||
if ((status = ia64_pal_logical_to_phys(0, &info)) != PAL_STATUS_SUCCESS) {
|
||||
printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
|
||||
status);
|
||||
return;
|
||||
}
|
||||
if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) {
|
||||
printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
|
||||
return;
|
||||
}
|
||||
if ((status = ia64_pal_fixed_addr(&proc_fixed_addr)) != PAL_STATUS_SUCCESS) {
|
||||
printk(KERN_ERR "ia64_pal_fixed_addr failed with %ld\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
c->socket_id = (pltid << 8) | info.overview_ppid;
|
||||
c->cores_per_socket = info.overview_cpp;
|
||||
c->threads_per_core = info.overview_tpc;
|
||||
count = c->num_log = info.overview_num_log;
|
||||
|
||||
/* If the thread and core id information is already cached, then
|
||||
* we will simply update cpu_info and return. Otherwise, we will
|
||||
* do the PAL calls and cache core and thread id's of all the siblings.
|
||||
*/
|
||||
if (check_for_new_socket(proc_fixed_addr, c))
|
||||
return;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
int index;
|
||||
|
||||
if (i && (status = ia64_pal_logical_to_phys(i, &info))
|
||||
!= PAL_STATUS_SUCCESS) {
|
||||
printk(KERN_ERR "ia64_pal_logical_to_phys failed"
|
||||
" with %ld\n", status);
|
||||
return;
|
||||
}
|
||||
if (info.log2_la == proc_fixed_addr) {
|
||||
c->core_id = info.log1_cid;
|
||||
c->thread_id = info.log1_tid;
|
||||
}
|
||||
|
||||
index = check_for_mtinfo_index();
|
||||
/* We will not do the mt_info caching optimization in this case.
|
||||
*/
|
||||
if (index < 0)
|
||||
continue;
|
||||
|
||||
mt_info[index].valid = 1;
|
||||
mt_info[index].socket_id = c->socket_id;
|
||||
mt_info[index].core_id = info.log1_cid;
|
||||
mt_info[index].thread_id = info.log1_tid;
|
||||
mt_info[index].proc_fixed_addr = info.log2_la;
|
||||
}
|
||||
}
|
||||
|
@ -67,6 +67,7 @@
|
||||
#define PAL_REGISTER_INFO 39 /* return AR and CR register information*/
|
||||
#define PAL_SHUTDOWN 40 /* enter processor shutdown state */
|
||||
#define PAL_PREFETCH_VISIBILITY 41 /* Make Processor Prefetches Visible */
|
||||
#define PAL_LOGICAL_TO_PHYSICAL 42 /* returns information on logical to physical processor mapping */
|
||||
|
||||
#define PAL_COPY_PAL 256 /* relocate PAL procedures and PAL PMI */
|
||||
#define PAL_HALT_INFO 257 /* return the low power capabilities of processor */
|
||||
@ -1559,6 +1560,73 @@ ia64_pal_prefetch_visibility (s64 trans_type)
|
||||
return iprv.status;
|
||||
}
|
||||
|
||||
/* data structure for getting information on logical to physical mappings */
|
||||
typedef union pal_log_overview_u {
|
||||
struct {
|
||||
u64 num_log :16, /* Total number of logical
|
||||
* processors on this die
|
||||
*/
|
||||
tpc :8, /* Threads per core */
|
||||
reserved3 :8, /* Reserved */
|
||||
cpp :8, /* Cores per processor */
|
||||
reserved2 :8, /* Reserved */
|
||||
ppid :8, /* Physical processor ID */
|
||||
reserved1 :8; /* Reserved */
|
||||
} overview_bits;
|
||||
u64 overview_data;
|
||||
} pal_log_overview_t;
|
||||
|
||||
typedef union pal_proc_n_log_info1_u{
|
||||
struct {
|
||||
u64 tid :16, /* Thread id */
|
||||
reserved2 :16, /* Reserved */
|
||||
cid :16, /* Core id */
|
||||
reserved1 :16; /* Reserved */
|
||||
} ppli1_bits;
|
||||
u64 ppli1_data;
|
||||
} pal_proc_n_log_info1_t;
|
||||
|
||||
typedef union pal_proc_n_log_info2_u {
|
||||
struct {
|
||||
u64 la :16, /* Logical address */
|
||||
reserved :48; /* Reserved */
|
||||
} ppli2_bits;
|
||||
u64 ppli2_data;
|
||||
} pal_proc_n_log_info2_t;
|
||||
|
||||
typedef struct pal_logical_to_physical_s
|
||||
{
|
||||
pal_log_overview_t overview;
|
||||
pal_proc_n_log_info1_t ppli1;
|
||||
pal_proc_n_log_info2_t ppli2;
|
||||
} pal_logical_to_physical_t;
|
||||
|
||||
#define overview_num_log overview.overview_bits.num_log
|
||||
#define overview_tpc overview.overview_bits.tpc
|
||||
#define overview_cpp overview.overview_bits.cpp
|
||||
#define overview_ppid overview.overview_bits.ppid
|
||||
#define log1_tid ppli1.ppli1_bits.tid
|
||||
#define log1_cid ppli1.ppli1_bits.cid
|
||||
#define log2_la ppli2.ppli2_bits.la
|
||||
|
||||
/* Get information on logical to physical processor mappings. */
|
||||
static inline s64
|
||||
ia64_pal_logical_to_phys(u64 proc_number, pal_logical_to_physical_t *mapping)
|
||||
{
|
||||
struct ia64_pal_retval iprv;
|
||||
|
||||
PAL_CALL(iprv, PAL_LOGICAL_TO_PHYSICAL, proc_number, 0, 0);
|
||||
|
||||
if (iprv.status == PAL_STATUS_SUCCESS)
|
||||
{
|
||||
if (proc_number == 0)
|
||||
mapping->overview.overview_data = iprv.v0;
|
||||
mapping->ppli1.ppli1_data = iprv.v1;
|
||||
mapping->ppli2.ppli2_data = iprv.v2;
|
||||
}
|
||||
|
||||
return iprv.status;
|
||||
}
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_IA64_PAL_H */
|
||||
|
@ -148,6 +148,13 @@ struct cpuinfo_ia64 {
|
||||
#ifdef CONFIG_SMP
|
||||
__u64 loops_per_jiffy;
|
||||
int cpu;
|
||||
__u32 socket_id; /* physical processor socket id */
|
||||
__u16 core_id; /* core id */
|
||||
__u16 thread_id; /* thread id */
|
||||
__u16 num_log; /* Total number of logical processors on
|
||||
* this socket that were successfully booted */
|
||||
__u8 cores_per_socket; /* Cores per processor socket */
|
||||
__u8 threads_per_core; /* Threads per core */
|
||||
#endif
|
||||
|
||||
/* CPUID-derived information: */
|
||||
|
@ -91,6 +91,7 @@ extern spinlock_t sal_lock;
|
||||
#define SAL_PCI_CONFIG_READ 0x01000010
|
||||
#define SAL_PCI_CONFIG_WRITE 0x01000011
|
||||
#define SAL_FREQ_BASE 0x01000012
|
||||
#define SAL_PHYSICAL_ID_INFO 0x01000013
|
||||
|
||||
#define SAL_UPDATE_PAL 0x01000020
|
||||
|
||||
@ -815,6 +816,17 @@ ia64_sal_update_pal (u64 param_buf, u64 scratch_buf, u64 scratch_buf_size,
|
||||
return isrv.status;
|
||||
}
|
||||
|
||||
/* Get physical processor die mapping in the platform. */
|
||||
static inline s64
|
||||
ia64_sal_physical_id_info(u16 *splid)
|
||||
{
|
||||
struct ia64_sal_retval isrv;
|
||||
SAL_CALL(isrv, SAL_PHYSICAL_ID_INFO, 0, 0, 0, 0, 0, 0, 0);
|
||||
if (splid)
|
||||
*splid = isrv.v0;
|
||||
return isrv.status;
|
||||
}
|
||||
|
||||
extern unsigned long sal_platform_features;
|
||||
|
||||
extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *);
|
||||
|
@ -56,6 +56,10 @@ extern struct smp_boot_data {
|
||||
extern char no_int_routing __devinitdata;
|
||||
|
||||
extern cpumask_t cpu_online_map;
|
||||
extern cpumask_t cpu_core_map[NR_CPUS];
|
||||
extern cpumask_t cpu_sibling_map[NR_CPUS];
|
||||
extern int smp_num_siblings;
|
||||
extern int smp_num_cpucores;
|
||||
extern void __iomem *ipi_base_addr;
|
||||
extern unsigned char smp_int_redirect;
|
||||
|
||||
@ -124,6 +128,7 @@ extern int smp_call_function_single (int cpuid, void (*func) (void *info), void
|
||||
extern void smp_send_reschedule (int cpu);
|
||||
extern void lock_ipi_calllock(void);
|
||||
extern void unlock_ipi_calllock(void);
|
||||
extern void identify_siblings (struct cpuinfo_ia64 *);
|
||||
|
||||
#else
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user