qcacmn: Print HP/TP Stats
Extend txrx_stats to print current HP/TP Status for UMAC rings. Change-Id: I50332f7507fdf1841dee51f0b1e97ef4ea68f04f CRs-Fixed: 2332191
This commit is contained in:

committed by
nshrivas

parent
6609dbbddd
commit
443b9b4da2
@@ -5977,27 +5977,88 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
|
||||
reo_error);
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_srng_get_str_from_ring_type() - Return string name for a ring
|
||||
* @ring_type: Ring
|
||||
*
|
||||
* Return: char const pointer
|
||||
*/
|
||||
static inline const
|
||||
char *dp_srng_get_str_from_hal_ring_type(enum hal_ring_type ring_type)
|
||||
{
|
||||
switch (ring_type) {
|
||||
case REO_DST:
|
||||
return "Reo_dst";
|
||||
case REO_EXCEPTION:
|
||||
return "Reo_exception";
|
||||
case REO_CMD:
|
||||
return "Reo_cmd";
|
||||
case REO_REINJECT:
|
||||
return "Reo_reinject";
|
||||
case REO_STATUS:
|
||||
return "Reo_status";
|
||||
case WBM2SW_RELEASE:
|
||||
return "wbm2sw_release";
|
||||
case TCL_DATA:
|
||||
return "tcl_data";
|
||||
case TCL_CMD:
|
||||
return "tcl_cmd";
|
||||
case TCL_STATUS:
|
||||
return "tcl_status";
|
||||
case SW2WBM_RELEASE:
|
||||
return "sw2wbm_release";
|
||||
case RXDMA_BUF:
|
||||
return "Rxdma_buf";
|
||||
case RXDMA_DST:
|
||||
return "Rxdma_dst";
|
||||
case RXDMA_MONITOR_BUF:
|
||||
return "Rxdma_monitor_buf";
|
||||
case RXDMA_MONITOR_DESC:
|
||||
return "Rxdma_monitor_desc";
|
||||
case RXDMA_MONITOR_STATUS:
|
||||
return "Rxdma_monitor_status";
|
||||
default:
|
||||
dp_err("Invalid ring type");
|
||||
break;
|
||||
}
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
/**
|
||||
* dp_print_ring_stat_from_hal(): Print hal level ring stats
|
||||
* @soc: DP_SOC handle
|
||||
* @srng: DP_SRNG handle
|
||||
* @ring_name: SRNG name
|
||||
* @ring_type: srng src/dst ring
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void
|
||||
dp_print_ring_stat_from_hal(struct dp_soc *soc, struct dp_srng *srng,
|
||||
char *ring_name)
|
||||
enum hal_ring_type ring_type)
|
||||
{
|
||||
uint32_t tailp;
|
||||
uint32_t headp;
|
||||
int32_t hw_headp = -1;
|
||||
int32_t hw_tailp = -1;
|
||||
const char *ring_name;
|
||||
struct hal_soc *hal_soc = (struct hal_soc *)soc->hal_soc;
|
||||
|
||||
if (soc && srng && srng->hal_srng) {
|
||||
hal_api_get_tphp(soc->hal_soc, srng->hal_srng, &tailp, &headp);
|
||||
DP_PRINT_STATS("%s : Head pointer = %d Tail Pointer = %d",
|
||||
ring_name = dp_srng_get_str_from_hal_ring_type(ring_type);
|
||||
|
||||
hal_get_sw_hptp(soc->hal_soc, srng->hal_srng, &tailp, &headp);
|
||||
|
||||
DP_PRINT_STATS("%s:SW:Head pointer = %d Tail Pointer = %d\n",
|
||||
ring_name, headp, tailp);
|
||||
|
||||
hal_get_hw_hptp(hal_soc, srng->hal_srng, &hw_headp,
|
||||
&hw_tailp, ring_type);
|
||||
|
||||
DP_PRINT_STATS("%s:HW:Head pointer = %d Tail Pointer = %d\n",
|
||||
ring_name, hw_headp, hw_tailp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6014,18 +6075,18 @@ void dp_print_mon_ring_stat_from_hal(struct dp_pdev *pdev, uint8_t mac_id)
|
||||
if (pdev->soc->wlan_cfg_ctx->rxdma1_enable) {
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rxdma_mon_buf_ring[mac_id],
|
||||
"Rxdma Mon Buf Ring");
|
||||
RXDMA_MONITOR_BUF);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rxdma_mon_dst_ring[mac_id],
|
||||
"Rxdma Mon Dst Ring");
|
||||
RXDMA_MONITOR_DST);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rxdma_mon_desc_ring[mac_id],
|
||||
"Rxdma mon desc Ring");
|
||||
RXDMA_MONITOR_DESC);
|
||||
}
|
||||
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rxdma_mon_status_ring[mac_id],
|
||||
"Rxdma Mon Status Ring");
|
||||
RXDMA_MONITOR_STATUS);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6038,77 +6099,67 @@ static inline void
|
||||
dp_print_ring_stats(struct dp_pdev *pdev)
|
||||
{
|
||||
uint32_t i;
|
||||
char ring_name[STR_MAXLEN + 1];
|
||||
int mac_id;
|
||||
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->reo_exception_ring,
|
||||
"Reo Exception Ring");
|
||||
REO_EXCEPTION);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->reo_reinject_ring,
|
||||
"Reo Inject Ring");
|
||||
REO_REINJECT);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->reo_cmd_ring,
|
||||
"Reo Command Ring");
|
||||
REO_CMD);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->reo_status_ring,
|
||||
"Reo Status Ring");
|
||||
REO_STATUS);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->rx_rel_ring,
|
||||
"Rx Release ring");
|
||||
WBM2SW_RELEASE);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->tcl_cmd_ring,
|
||||
"Tcl command Ring");
|
||||
TCL_CMD);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->tcl_status_ring,
|
||||
"Tcl Status Ring");
|
||||
TCL_STATUS);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->wbm_desc_rel_ring,
|
||||
"Wbm Desc Rel Ring");
|
||||
for (i = 0; i < MAX_REO_DEST_RINGS; i++) {
|
||||
snprintf(ring_name, STR_MAXLEN, "Reo Dest Ring %d", i);
|
||||
SW2WBM_RELEASE);
|
||||
for (i = 0; i < MAX_REO_DEST_RINGS; i++)
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->reo_dest_ring[i],
|
||||
ring_name);
|
||||
}
|
||||
REO_DST);
|
||||
|
||||
for (i = 0; i < pdev->soc->num_tcl_data_rings; i++) {
|
||||
snprintf(ring_name, STR_MAXLEN, "Tcl Data Ring %d", i);
|
||||
for (i = 0; i < pdev->soc->num_tcl_data_rings; i++)
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->tcl_data_ring[i],
|
||||
ring_name);
|
||||
}
|
||||
for (i = 0; i < MAX_TCL_DATA_RINGS; i++) {
|
||||
snprintf(ring_name, STR_MAXLEN, "Tx Comp Ring %d", i);
|
||||
TCL_DATA);
|
||||
for (i = 0; i < MAX_TCL_DATA_RINGS; i++)
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->soc->tx_comp_ring[i],
|
||||
ring_name);
|
||||
}
|
||||
WBM2SW_RELEASE);
|
||||
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rx_refill_buf_ring,
|
||||
"Rx Refill Buf Ring");
|
||||
RXDMA_BUF);
|
||||
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rx_refill_buf_ring2,
|
||||
"Second Rx Refill Buf Ring");
|
||||
RXDMA_BUF);
|
||||
|
||||
for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) {
|
||||
dp_print_mon_ring_stat_from_hal(pdev, mac_id);
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_RXDMA_RINGS_PER_PDEV; i++) {
|
||||
snprintf(ring_name, STR_MAXLEN, "Rxdma err dst ring %d", i);
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rxdma_err_dst_ring[i],
|
||||
ring_name);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_RX_MAC_RINGS; i++) {
|
||||
snprintf(ring_name, STR_MAXLEN, "Rx mac buf ring %d", i);
|
||||
for (i = 0; i < MAX_RX_MAC_RINGS; i++)
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rx_mac_buf_ring[i],
|
||||
ring_name);
|
||||
}
|
||||
RXDMA_BUF);
|
||||
|
||||
for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++)
|
||||
dp_print_mon_ring_stat_from_hal(pdev, mac_id);
|
||||
|
||||
for (i = 0; i < NUM_RXDMA_RINGS_PER_PDEV; i++)
|
||||
dp_print_ring_stat_from_hal(pdev->soc,
|
||||
&pdev->rxdma_err_dst_ring[i],
|
||||
RXDMA_DST);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -615,7 +615,7 @@ dp_rx_mon_status_srng_process(struct dp_soc *soc, uint32_t mac_id,
|
||||
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
uint32_t hp, tp;
|
||||
hal_api_get_tphp(hal_soc, mon_status_srng,
|
||||
hal_get_sw_hptp(hal_soc, mon_status_srng,
|
||||
&tp, &hp);
|
||||
QDF_TRACE(QDF_MODULE_ID_DP,
|
||||
QDF_TRACE_LEVEL_ERROR,
|
||||
|
@@ -22,7 +22,6 @@
|
||||
#include "qdf_types.h"
|
||||
#include "qdf_util.h"
|
||||
#include "hal_internal.h"
|
||||
|
||||
#define MAX_UNWINDOWED_ADDRESS 0x80000
|
||||
#ifdef QCA_WIFI_QCA6390
|
||||
#define WINDOW_ENABLE_BIT 0x40000000
|
||||
@@ -178,6 +177,27 @@ static inline uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_read_address_32_mb() - Read 32-bit value from the register
|
||||
* @soc: soc handle
|
||||
* @addr: register address to read
|
||||
*
|
||||
* Return: 32-bit value
|
||||
*/
|
||||
static inline uint32_t hal_read_address_32_mb(struct hal_soc *soc,
|
||||
void __iomem *addr)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t ret;
|
||||
|
||||
if (!soc->use_register_windowing)
|
||||
return qdf_ioread32(addr);
|
||||
|
||||
offset = addr - soc->dev_base_addr;
|
||||
ret = hal_read32_mb(soc, offset);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset)
|
||||
{
|
||||
@@ -208,6 +228,20 @@ static inline uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t hal_read_address_32_mb(struct hal_soc *soc,
|
||||
void __iomem *addr)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t ret;
|
||||
|
||||
if (!soc->use_register_windowing)
|
||||
return qdf_ioread32(addr);
|
||||
|
||||
offset = addr - soc->dev_base_addr;
|
||||
ret = hal_read32_mb(soc, offset);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "hif_io32.h"
|
||||
@@ -749,7 +783,7 @@ static inline uint32_t hal_srng_src_done_val(void *hal_soc, void *hal_ring)
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_api_get_tphp - Get head and tail pointer location for any ring
|
||||
* hal_get_sw_hptp - Get SW head and tail pointer location for any ring
|
||||
* @hal_soc: Opaque HAL SOC handle
|
||||
* @hal_ring: Source ring pointer
|
||||
* @tailp: Tail Pointer
|
||||
@@ -757,7 +791,7 @@ static inline uint32_t hal_srng_src_done_val(void *hal_soc, void *hal_ring)
|
||||
*
|
||||
* Return: Update tail pointer and head pointer in arguments.
|
||||
*/
|
||||
static inline void hal_api_get_tphp(void *hal_soc, void *hal_ring,
|
||||
static inline void hal_get_sw_hptp(void *hal_soc, void *hal_ring,
|
||||
uint32_t *tailp, uint32_t *headp)
|
||||
{
|
||||
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
||||
@@ -1242,6 +1276,23 @@ static inline void hal_srng_src_hw_init(struct hal_soc *hal,
|
||||
hal->ops->hal_srng_src_hw_init(hal, srng);
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_get_hw_hptp() - Get HW head and tail pointer value for any ring
|
||||
* @hal_soc: Opaque HAL SOC handle
|
||||
* @hal_ring: Source ring pointer
|
||||
* @headp: Head Pointer
|
||||
* @tailp: Tail Pointer
|
||||
* @ring_type: Ring
|
||||
*
|
||||
* Return: Update tail pointer and head pointer in arguments.
|
||||
*/
|
||||
static inline void hal_get_hw_hptp(struct hal_soc *hal, void *hal_ring,
|
||||
uint32_t *headp, uint32_t *tailp,
|
||||
uint8_t ring_type)
|
||||
{
|
||||
hal->ops->hal_get_hw_hptp(hal, hal_ring, headp, tailp, ring_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_reo_setup - Initialize HW REO block
|
||||
*
|
||||
|
@@ -1381,6 +1381,47 @@ static void hal_reo_setup_generic(void *hal_soc,
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_get_hw_hptp_generic() - Get HW head and tail pointer value for any ring
|
||||
* @hal_soc: Opaque HAL SOC handle
|
||||
* @hal_ring: Source ring pointer
|
||||
* @headp: Head Pointer
|
||||
* @tailp: Tail Pointer
|
||||
* @ring: Ring type
|
||||
*
|
||||
* Return: Update tail pointer and head pointer in arguments.
|
||||
*/
|
||||
static inline
|
||||
void hal_get_hw_hptp_generic(struct hal_soc *soc, void *hal_ring,
|
||||
uint32_t *headp, uint32_t *tailp,
|
||||
uint8_t ring)
|
||||
{
|
||||
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
||||
struct hal_hw_srng_config *ring_config;
|
||||
enum hal_ring_type ring_type = (enum hal_ring_type)ring;
|
||||
|
||||
if (!soc || !srng) {
|
||||
QDF_TRACE(QDF_MODULE_ID_HAL, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s: Context is Null", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ring_config = HAL_SRNG_CONFIG(soc, ring_type);
|
||||
if (!ring_config->lmac_ring) {
|
||||
if (srng->ring_dir == HAL_SRNG_SRC_RING) {
|
||||
*headp =
|
||||
(SRNG_SRC_REG_READ(srng, HP)) / srng->entry_size;
|
||||
*tailp =
|
||||
(SRNG_SRC_REG_READ(srng, TP)) / srng->entry_size;
|
||||
} else {
|
||||
*headp =
|
||||
(SRNG_DST_REG_READ(srng, HP)) / srng->entry_size;
|
||||
*tailp =
|
||||
(SRNG_DST_REG_READ(srng, TP)) / srng->entry_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_srng_src_hw_init - Private function to initialize SRNG
|
||||
* source ring HW
|
||||
|
@@ -239,6 +239,9 @@
|
||||
#define SRNG_SRC_REG_READ(_srng, _reg) \
|
||||
SRNG_REG_READ(_srng, _reg, SRC)
|
||||
|
||||
#define SRNG_DST_REG_READ(_srng, _reg) \
|
||||
SRNG_REG_READ(_srng, _reg, DST)
|
||||
|
||||
#define _SRNG_FM(_reg_fld) _reg_fld ## _BMSK
|
||||
#define _SRNG_FS(_reg_fld) _reg_fld ## _SHFT
|
||||
|
||||
|
@@ -275,6 +275,9 @@ struct hal_hw_txrx_ops {
|
||||
struct hal_srng *srng);
|
||||
void (*hal_srng_src_hw_init)(void *hal,
|
||||
struct hal_srng *srng);
|
||||
void (*hal_get_hw_hptp)(struct hal_soc *hal, void *hal_ring,
|
||||
uint32_t *headp, uint32_t *tailp,
|
||||
uint8_t ring_type);
|
||||
void (*hal_reo_setup)(void *hal_soc, void *reoparams);
|
||||
void (*hal_setup_link_idle_list)(void *hal_soc,
|
||||
qdf_dma_addr_t scatter_bufs_base_paddr[],
|
||||
|
@@ -112,6 +112,7 @@ struct hal_hw_txrx_ops qca6290_hal_hw_txrx_ops = {
|
||||
/* init and setup */
|
||||
hal_srng_dst_hw_init_generic,
|
||||
hal_srng_src_hw_init_generic,
|
||||
hal_get_hw_hptp_generic,
|
||||
hal_reo_setup_generic,
|
||||
hal_setup_link_idle_list_generic,
|
||||
|
||||
|
@@ -112,6 +112,7 @@ struct hal_hw_txrx_ops qca6390_hal_hw_txrx_ops = {
|
||||
/* init and setup */
|
||||
hal_srng_dst_hw_init_generic,
|
||||
hal_srng_src_hw_init_generic,
|
||||
hal_get_hw_hptp_generic,
|
||||
hal_reo_setup_generic,
|
||||
hal_setup_link_idle_list_generic,
|
||||
|
||||
|
@@ -108,6 +108,7 @@ struct hal_hw_txrx_ops qca8074_hal_hw_txrx_ops = {
|
||||
/* init and setup */
|
||||
hal_srng_dst_hw_init_generic,
|
||||
hal_srng_src_hw_init_generic,
|
||||
hal_get_hw_hptp_generic,
|
||||
hal_reo_setup_generic,
|
||||
hal_setup_link_idle_list_generic,
|
||||
|
||||
|
@@ -108,6 +108,7 @@ struct hal_hw_txrx_ops qca8074v2_hal_hw_txrx_ops = {
|
||||
/* init and setup */
|
||||
hal_srng_dst_hw_init_generic,
|
||||
hal_srng_src_hw_init_generic,
|
||||
hal_get_hw_hptp_generic,
|
||||
hal_reo_setup_generic,
|
||||
hal_setup_link_idle_list_generic,
|
||||
|
||||
|
@@ -332,6 +332,7 @@ typedef void (*qdf_timer_func_t)(void *);
|
||||
* @QDF_MODULE_ID_EPPING: EPPING module ID
|
||||
* @QDF_MODULE_ID_QVIT: QVIT module ID
|
||||
* @QDF_MODULE_ID_DP: Data-path module ID
|
||||
* @QDF_MODULE_ID_HAL: Hal abstraction module ID
|
||||
* @QDF_MODULE_ID_SOC: SOC module ID
|
||||
* @QDF_MODULE_ID_OS_IF: OS-interface module ID
|
||||
* @QDF_MODULE_ID_TARGET_IF: targer interface module ID
|
||||
@@ -436,6 +437,7 @@ typedef enum {
|
||||
QDF_MODULE_ID_EPPING,
|
||||
QDF_MODULE_ID_QVIT,
|
||||
QDF_MODULE_ID_DP,
|
||||
QDF_MODULE_ID_HAL,
|
||||
QDF_MODULE_ID_SOC,
|
||||
QDF_MODULE_ID_OS_IF,
|
||||
QDF_MODULE_ID_TARGET_IF,
|
||||
|
@@ -2806,6 +2806,7 @@ struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
|
||||
[QDF_MODULE_ID_EPPING] = {"EPPING"},
|
||||
[QDF_MODULE_ID_QVIT] = {"QVIT"},
|
||||
[QDF_MODULE_ID_DP] = {"DP"},
|
||||
[QDF_MODULE_ID_HAL] = {"HAL"},
|
||||
[QDF_MODULE_ID_SOC] = {"SOC"},
|
||||
[QDF_MODULE_ID_OS_IF] = {"OSIF"},
|
||||
[QDF_MODULE_ID_TARGET_IF] = {"TIF"},
|
||||
@@ -3258,6 +3259,7 @@ static void set_default_trace_levels(struct category_info *cinfo)
|
||||
[QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE,
|
||||
[QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE,
|
||||
[QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL,
|
||||
[QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE,
|
||||
[QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE,
|
||||
[QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE,
|
||||
[QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO,
|
||||
|
@@ -1080,7 +1080,7 @@ QDF_STATUS target_if_direct_buf_rx_print_ring_stat(
|
||||
mod_param = &dbr_pdev_obj->dbr_mod_param[mod_idx];
|
||||
dbr_ring_cfg = mod_param->dbr_ring_cfg;
|
||||
srng = dbr_ring_cfg->srng;
|
||||
hal_api_get_tphp(hal_soc, srng, &tp, &hp);
|
||||
hal_get_sw_hptp(hal_soc, srng, &tp, &hp);
|
||||
direct_buf_rx_err("|%11d|%14s|%10x|%10x|",
|
||||
mod_idx,
|
||||
g_dbr_module_name[mod_idx].module_name_str,
|
||||
|
Reference in New Issue
Block a user