linux/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c
<<
>>
Prefs
   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}
 319