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 11 static struct dentry *hinic_dbgfs_root; 12 13 enum sq_dbg_info { 14 GLB_SQ_ID, 15 SQ_PI, 16 SQ_CI, 17 SQ_FI, 18 SQ_MSIX_ENTRY, 19 }; 20 21 static char *sq_fields[] = {"glb_sq_id", "sq_pi", "sq_ci", "sq_fi", "sq_msix_entry"}; 22 23 static 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 43 enum 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 51 static char *rq_fields[] = {"glb_rq_id", "rq_hw_pi", "rq_sw_ci", "rq_sw_pi", "rq_msix_entry"}; 52 53 static 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 73 enum func_tbl_info { 74 VALID, 75 RX_MODE, 76 MTU, 77 RQ_DEPTH, 78 QUEUE_NUM, 79 }; 80 81 static char *func_table_fields[] = {"valid", "rx_mode", "mtu", "rq_depth", "cfg_q_num"}; 82 83 static 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 130 static 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 166 static const struct file_operations hinic_dbg_cmd_fops = { 167 .owner = THIS_MODULE, 168 .open = simple_open, 169 .read = hinic_dbg_cmd_read, 170 }; 171 172 static 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 198 static 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 206 int 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 222 void hinic_sq_debug_rem(struct hinic_sq *sq) 223 { 224 if (sq->dbg) 225 rem_dbg_files(sq->dbg); 226 } 227 228 int 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 244 void hinic_rq_debug_rem(struct hinic_rq *rq) 245 { 246 if (rq->dbg) 247 rem_dbg_files(rq->dbg); 248 } 249 250 int 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 259 void 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 265 void 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 270 void hinic_sq_dbgfs_uninit(struct hinic_dev *nic_dev) 271 { 272 debugfs_remove_recursive(nic_dev->sq_dbgfs); 273 } 274 275 void 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 280 void hinic_rq_dbgfs_uninit(struct hinic_dev *nic_dev) 281 { 282 debugfs_remove_recursive(nic_dev->rq_dbgfs); 283 } 284 285 void 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 291 void 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 297 void 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 303 void 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 309 void hinic_dbg_register_debugfs(const char *debugfs_dir_name) 310 { 311 hinic_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL); 312 } 313 314 void hinic_dbg_unregister_debugfs(void) 315 { 316 debugfs_remove_recursive(hinic_dbgfs_root); 317 hinic_dbgfs_root = NULL; 318 } 319