cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hinic_debugfs.c (7402B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* Huawei HiNIC PCI Express Linux driver
      3 * Copyright(c) 2017 Huawei Technologies Co., Ltd
      4 */
      5
      6#include <linux/debugfs.h>
      7#include <linux/device.h>
      8
      9#include "hinic_debugfs.h"
     10
     11static struct dentry *hinic_dbgfs_root;
     12
     13enum sq_dbg_info {
     14	GLB_SQ_ID,
     15	SQ_PI,
     16	SQ_CI,
     17	SQ_FI,
     18	SQ_MSIX_ENTRY,
     19};
     20
     21static char *sq_fields[] = {"glb_sq_id", "sq_pi", "sq_ci", "sq_fi", "sq_msix_entry"};
     22
     23static u64 hinic_dbg_get_sq_info(struct hinic_dev *nic_dev, struct hinic_sq *sq, int idx)
     24{
     25	struct hinic_wq *wq = sq->wq;
     26
     27	switch (idx) {
     28	case GLB_SQ_ID:
     29		return nic_dev->hwdev->func_to_io.global_qpn + sq->qid;
     30	case SQ_PI:
     31		return atomic_read(&wq->prod_idx) & wq->mask;
     32	case SQ_CI:
     33		return atomic_read(&wq->cons_idx) & wq->mask;
     34	case SQ_FI:
     35		return be16_to_cpu(*(__be16 *)(sq->hw_ci_addr)) & wq->mask;
     36	case SQ_MSIX_ENTRY:
     37		return sq->msix_entry;
     38	}
     39
     40	return 0;
     41}
     42
     43enum rq_dbg_info {
     44	GLB_RQ_ID,
     45	RQ_HW_PI,
     46	RQ_SW_CI,
     47	RQ_SW_PI,
     48	RQ_MSIX_ENTRY,
     49};
     50
     51static char *rq_fields[] = {"glb_rq_id", "rq_hw_pi", "rq_sw_ci", "rq_sw_pi", "rq_msix_entry"};
     52
     53static u64 hinic_dbg_get_rq_info(struct hinic_dev *nic_dev, struct hinic_rq *rq, int idx)
     54{
     55	struct hinic_wq *wq = rq->wq;
     56
     57	switch (idx) {
     58	case GLB_RQ_ID:
     59		return nic_dev->hwdev->func_to_io.global_qpn + rq->qid;
     60	case RQ_HW_PI:
     61		return be16_to_cpu(*(__be16 *)(rq->pi_virt_addr)) & wq->mask;
     62	case RQ_SW_CI:
     63		return atomic_read(&wq->cons_idx) & wq->mask;
     64	case RQ_SW_PI:
     65		return atomic_read(&wq->prod_idx) & wq->mask;
     66	case RQ_MSIX_ENTRY:
     67		return rq->msix_entry;
     68	}
     69
     70	return 0;
     71}
     72
     73enum func_tbl_info {
     74	VALID,
     75	RX_MODE,
     76	MTU,
     77	RQ_DEPTH,
     78	QUEUE_NUM,
     79};
     80
     81static char *func_table_fields[] = {"valid", "rx_mode", "mtu", "rq_depth", "cfg_q_num"};
     82
     83static int hinic_dbg_get_func_table(struct hinic_dev *nic_dev, int idx)
     84{
     85	struct tag_sml_funcfg_tbl *funcfg_table_elem;
     86	struct hinic_cmd_lt_rd *read_data;
     87	u16 out_size = sizeof(*read_data);
     88	int err;
     89
     90	read_data = kzalloc(sizeof(*read_data), GFP_KERNEL);
     91	if (!read_data)
     92		return ~0;
     93
     94	read_data->node = TBL_ID_FUNC_CFG_SM_NODE;
     95	read_data->inst = TBL_ID_FUNC_CFG_SM_INST;
     96	read_data->entry_size = HINIC_FUNCTION_CONFIGURE_TABLE_SIZE;
     97	read_data->lt_index = HINIC_HWIF_FUNC_IDX(nic_dev->hwdev->hwif);
     98	read_data->len = HINIC_FUNCTION_CONFIGURE_TABLE_SIZE;
     99
    100	err = hinic_port_msg_cmd(nic_dev->hwdev, HINIC_PORT_CMD_RD_LINE_TBL, read_data,
    101				 sizeof(*read_data), read_data, &out_size);
    102	if (err || out_size != sizeof(*read_data) || read_data->status) {
    103		netif_err(nic_dev, drv, nic_dev->netdev,
    104			  "Failed to get func table, err: %d, status: 0x%x, out size: 0x%x\n",
    105			  err, read_data->status, out_size);
    106		kfree(read_data);
    107		return ~0;
    108	}
    109
    110	funcfg_table_elem = (struct tag_sml_funcfg_tbl *)read_data->data;
    111
    112	switch (idx) {
    113	case VALID:
    114		return funcfg_table_elem->dw0.bs.valid;
    115	case RX_MODE:
    116		return funcfg_table_elem->dw0.bs.nic_rx_mode;
    117	case MTU:
    118		return funcfg_table_elem->dw1.bs.mtu;
    119	case RQ_DEPTH:
    120		return funcfg_table_elem->dw13.bs.cfg_rq_depth;
    121	case QUEUE_NUM:
    122		return funcfg_table_elem->dw13.bs.cfg_q_num;
    123	}
    124
    125	kfree(read_data);
    126
    127	return ~0;
    128}
    129
    130static ssize_t hinic_dbg_cmd_read(struct file *filp, char __user *buffer, size_t count,
    131				  loff_t *ppos)
    132{
    133	struct hinic_debug_priv *dbg;
    134	char ret_buf[20];
    135	int *desc;
    136	u64 out;
    137	int ret;
    138
    139	desc = filp->private_data;
    140	dbg = container_of(desc, struct hinic_debug_priv, field_id[*desc]);
    141
    142	switch (dbg->type) {
    143	case HINIC_DBG_SQ_INFO:
    144		out = hinic_dbg_get_sq_info(dbg->dev, dbg->object, *desc);
    145		break;
    146
    147	case HINIC_DBG_RQ_INFO:
    148		out = hinic_dbg_get_rq_info(dbg->dev, dbg->object, *desc);
    149		break;
    150
    151	case HINIC_DBG_FUNC_TABLE:
    152		out = hinic_dbg_get_func_table(dbg->dev, *desc);
    153		break;
    154
    155	default:
    156		netif_warn(dbg->dev, drv, dbg->dev->netdev, "Invalid hinic debug cmd: %d\n",
    157			   dbg->type);
    158		return -EINVAL;
    159	}
    160
    161	ret = snprintf(ret_buf, sizeof(ret_buf), "0x%llx\n", out);
    162
    163	return simple_read_from_buffer(buffer, count, ppos, ret_buf, ret);
    164}
    165
    166static const struct file_operations hinic_dbg_cmd_fops = {
    167	.owner = THIS_MODULE,
    168	.open  = simple_open,
    169	.read  = hinic_dbg_cmd_read,
    170};
    171
    172static int create_dbg_files(struct hinic_dev *dev, enum hinic_dbg_type type, void *data,
    173			    struct dentry *root, struct hinic_debug_priv **dbg, char **field,
    174			    int nfile)
    175{
    176	struct hinic_debug_priv *tmp;
    177	int i;
    178
    179	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
    180	if (!tmp)
    181		return -ENOMEM;
    182
    183	tmp->dev = dev;
    184	tmp->object = data;
    185	tmp->type = type;
    186	tmp->root = root;
    187
    188	for (i = 0; i < nfile; i++) {
    189		tmp->field_id[i] = i;
    190		debugfs_create_file(field[i], 0400, root, &tmp->field_id[i], &hinic_dbg_cmd_fops);
    191	}
    192
    193	*dbg = tmp;
    194
    195	return 0;
    196}
    197
    198static void rem_dbg_files(struct hinic_debug_priv *dbg)
    199{
    200	if (dbg->type != HINIC_DBG_FUNC_TABLE)
    201		debugfs_remove_recursive(dbg->root);
    202
    203	kfree(dbg);
    204}
    205
    206int hinic_sq_debug_add(struct hinic_dev *dev, u16 sq_id)
    207{
    208	struct hinic_sq *sq;
    209	struct dentry *root;
    210	char sub_dir[16];
    211
    212	sq = dev->txqs[sq_id].sq;
    213
    214	sprintf(sub_dir, "0x%x", sq_id);
    215
    216	root = debugfs_create_dir(sub_dir, dev->sq_dbgfs);
    217
    218	return create_dbg_files(dev, HINIC_DBG_SQ_INFO, sq, root, &sq->dbg, sq_fields,
    219				ARRAY_SIZE(sq_fields));
    220}
    221
    222void hinic_sq_debug_rem(struct hinic_sq *sq)
    223{
    224	if (sq->dbg)
    225		rem_dbg_files(sq->dbg);
    226}
    227
    228int hinic_rq_debug_add(struct hinic_dev *dev, u16 rq_id)
    229{
    230	struct hinic_rq *rq;
    231	struct dentry *root;
    232	char sub_dir[16];
    233
    234	rq = dev->rxqs[rq_id].rq;
    235
    236	sprintf(sub_dir, "0x%x", rq_id);
    237
    238	root = debugfs_create_dir(sub_dir, dev->rq_dbgfs);
    239
    240	return create_dbg_files(dev, HINIC_DBG_RQ_INFO, rq, root, &rq->dbg, rq_fields,
    241				ARRAY_SIZE(rq_fields));
    242}
    243
    244void hinic_rq_debug_rem(struct hinic_rq *rq)
    245{
    246	if (rq->dbg)
    247		rem_dbg_files(rq->dbg);
    248}
    249
    250int hinic_func_table_debug_add(struct hinic_dev *dev)
    251{
    252	if (HINIC_IS_VF(dev->hwdev->hwif))
    253		return 0;
    254
    255	return create_dbg_files(dev, HINIC_DBG_FUNC_TABLE, dev, dev->func_tbl_dbgfs, &dev->dbg,
    256				func_table_fields, ARRAY_SIZE(func_table_fields));
    257}
    258
    259void hinic_func_table_debug_rem(struct hinic_dev *dev)
    260{
    261	if (!HINIC_IS_VF(dev->hwdev->hwif) && dev->dbg)
    262		rem_dbg_files(dev->dbg);
    263}
    264
    265void hinic_sq_dbgfs_init(struct hinic_dev *nic_dev)
    266{
    267	nic_dev->sq_dbgfs = debugfs_create_dir("SQs", nic_dev->dbgfs_root);
    268}
    269
    270void hinic_sq_dbgfs_uninit(struct hinic_dev *nic_dev)
    271{
    272	debugfs_remove_recursive(nic_dev->sq_dbgfs);
    273}
    274
    275void hinic_rq_dbgfs_init(struct hinic_dev *nic_dev)
    276{
    277	nic_dev->rq_dbgfs = debugfs_create_dir("RQs", nic_dev->dbgfs_root);
    278}
    279
    280void hinic_rq_dbgfs_uninit(struct hinic_dev *nic_dev)
    281{
    282	debugfs_remove_recursive(nic_dev->rq_dbgfs);
    283}
    284
    285void hinic_func_tbl_dbgfs_init(struct hinic_dev *nic_dev)
    286{
    287	if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
    288		nic_dev->func_tbl_dbgfs = debugfs_create_dir("func_table", nic_dev->dbgfs_root);
    289}
    290
    291void hinic_func_tbl_dbgfs_uninit(struct hinic_dev *nic_dev)
    292{
    293	if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
    294		debugfs_remove_recursive(nic_dev->func_tbl_dbgfs);
    295}
    296
    297void hinic_dbg_init(struct hinic_dev *nic_dev)
    298{
    299	nic_dev->dbgfs_root = debugfs_create_dir(pci_name(nic_dev->hwdev->hwif->pdev),
    300						 hinic_dbgfs_root);
    301}
    302
    303void hinic_dbg_uninit(struct hinic_dev *nic_dev)
    304{
    305	debugfs_remove_recursive(nic_dev->dbgfs_root);
    306	nic_dev->dbgfs_root = NULL;
    307}
    308
    309void hinic_dbg_register_debugfs(const char *debugfs_dir_name)
    310{
    311	hinic_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
    312}
    313
    314void hinic_dbg_unregister_debugfs(void)
    315{
    316	debugfs_remove_recursive(hinic_dbgfs_root);
    317	hinic_dbgfs_root = NULL;
    318}