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 ret = ~0; 89 int err; 90 91 read_data = kzalloc(sizeof(*read_data), GFP_KERNEL); 92 if (!read_data) 93 return ~0; 94 95 read_data->node = TBL_ID_FUNC_CFG_SM_NODE; 96 read_data->inst = TBL_ID_FUNC_CFG_SM_INST; 97 read_data->entry_size = HINIC_FUNCTION_CONFIGURE_TABLE_SIZE; 98 read_data->lt_index = HINIC_HWIF_FUNC_IDX(nic_dev->hwdev->hwif); 99 read_data->len = HINIC_FUNCTION_CONFIGURE_TABLE_SIZE; 100 101 err = hinic_port_msg_cmd(nic_dev->hwdev, HINIC_PORT_CMD_RD_LINE_TBL, read_data, 102 sizeof(*read_data), read_data, &out_size); 103 if (err || out_size != sizeof(*read_data) || read_data->status) { 104 netif_err(nic_dev, drv, nic_dev->netdev, 105 "Failed to get func table, err: %d, status: 0x%x, out size: 0x%x\n", 106 err, read_data->status, out_size); 107 kfree(read_data); 108 return ~0; 109 } 110 111 funcfg_table_elem = (struct tag_sml_funcfg_tbl *)read_data->data; 112 113 switch (idx) { 114 case VALID: 115 ret = funcfg_table_elem->dw0.bs.valid; 116 break; 117 case RX_MODE: 118 ret = funcfg_table_elem->dw0.bs.nic_rx_mode; 119 break; 120 case MTU: 121 ret = funcfg_table_elem->dw1.bs.mtu; 122 break; 123 case RQ_DEPTH: 124 ret = funcfg_table_elem->dw13.bs.cfg_rq_depth; 125 break; 126 case QUEUE_NUM: 127 ret = funcfg_table_elem->dw13.bs.cfg_q_num; 128 break; 129 } 130 131 kfree(read_data); 132 133 return ret; 134 } 135 136 static ssize_t hinic_dbg_cmd_read(struct file *filp, char __user *buffer, size_t count, 137 loff_t *ppos) 138 { 139 struct hinic_debug_priv *dbg; 140 char ret_buf[20]; 141 int *desc; 142 u64 out; 143 int ret; 144 145 desc = filp->private_data; 146 dbg = container_of(desc, struct hinic_debug_priv, field_id[*desc]); 147 148 switch (dbg->type) { 149 case HINIC_DBG_SQ_INFO: 150 out = hinic_dbg_get_sq_info(dbg->dev, dbg->object, *desc); 151 break; 152 153 case HINIC_DBG_RQ_INFO: 154 out = hinic_dbg_get_rq_info(dbg->dev, dbg->object, *desc); 155 break; 156 157 case HINIC_DBG_FUNC_TABLE: 158 out = hinic_dbg_get_func_table(dbg->dev, *desc); 159 break; 160 161 default: 162 netif_warn(dbg->dev, drv, dbg->dev->netdev, "Invalid hinic debug cmd: %d\n", 163 dbg->type); 164 return -EINVAL; 165 } 166 167 ret = snprintf(ret_buf, sizeof(ret_buf), "0x%llx\n", out); 168 169 return simple_read_from_buffer(buffer, count, ppos, ret_buf, ret); 170 } 171 172 static const struct file_operations hinic_dbg_cmd_fops = { 173 .owner = THIS_MODULE, 174 .open = simple_open, 175 .read = hinic_dbg_cmd_read, 176 }; 177 178 static int create_dbg_files(struct hinic_dev *dev, enum hinic_dbg_type type, void *data, 179 struct dentry *root, struct hinic_debug_priv **dbg, char **field, 180 int nfile) 181 { 182 struct hinic_debug_priv *tmp; 183 int i; 184 185 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); 186 if (!tmp) 187 return -ENOMEM; 188 189 tmp->dev = dev; 190 tmp->object = data; 191 tmp->type = type; 192 tmp->root = root; 193 194 for (i = 0; i < nfile; i++) { 195 tmp->field_id[i] = i; 196 debugfs_create_file(field[i], 0400, root, &tmp->field_id[i], &hinic_dbg_cmd_fops); 197 } 198 199 *dbg = tmp; 200 201 return 0; 202 } 203 204 static void rem_dbg_files(struct hinic_debug_priv *dbg) 205 { 206 if (dbg->type != HINIC_DBG_FUNC_TABLE) 207 debugfs_remove_recursive(dbg->root); 208 209 kfree(dbg); 210 } 211 212 int hinic_sq_debug_add(struct hinic_dev *dev, u16 sq_id) 213 { 214 struct hinic_sq *sq; 215 struct dentry *root; 216 char sub_dir[16]; 217 218 sq = dev->txqs[sq_id].sq; 219 220 sprintf(sub_dir, "0x%x", sq_id); 221 222 root = debugfs_create_dir(sub_dir, dev->sq_dbgfs); 223 224 return create_dbg_files(dev, HINIC_DBG_SQ_INFO, sq, root, &sq->dbg, sq_fields, 225 ARRAY_SIZE(sq_fields)); 226 } 227 228 void hinic_sq_debug_rem(struct hinic_sq *sq) 229 { 230 if (sq->dbg) 231 rem_dbg_files(sq->dbg); 232 } 233 234 int hinic_rq_debug_add(struct hinic_dev *dev, u16 rq_id) 235 { 236 struct hinic_rq *rq; 237 struct dentry *root; 238 char sub_dir[16]; 239 240 rq = dev->rxqs[rq_id].rq; 241 242 sprintf(sub_dir, "0x%x", rq_id); 243 244 root = debugfs_create_dir(sub_dir, dev->rq_dbgfs); 245 246 return create_dbg_files(dev, HINIC_DBG_RQ_INFO, rq, root, &rq->dbg, rq_fields, 247 ARRAY_SIZE(rq_fields)); 248 } 249 250 void hinic_rq_debug_rem(struct hinic_rq *rq) 251 { 252 if (rq->dbg) 253 rem_dbg_files(rq->dbg); 254 } 255 256 int hinic_func_table_debug_add(struct hinic_dev *dev) 257 { 258 if (HINIC_IS_VF(dev->hwdev->hwif)) 259 return 0; 260 261 return create_dbg_files(dev, HINIC_DBG_FUNC_TABLE, dev, dev->func_tbl_dbgfs, &dev->dbg, 262 func_table_fields, ARRAY_SIZE(func_table_fields)); 263 } 264 265 void hinic_func_table_debug_rem(struct hinic_dev *dev) 266 { 267 if (!HINIC_IS_VF(dev->hwdev->hwif) && dev->dbg) 268 rem_dbg_files(dev->dbg); 269 } 270 271 void hinic_sq_dbgfs_init(struct hinic_dev *nic_dev) 272 { 273 nic_dev->sq_dbgfs = debugfs_create_dir("SQs", nic_dev->dbgfs_root); 274 } 275 276 void hinic_sq_dbgfs_uninit(struct hinic_dev *nic_dev) 277 { 278 debugfs_remove_recursive(nic_dev->sq_dbgfs); 279 } 280 281 void hinic_rq_dbgfs_init(struct hinic_dev *nic_dev) 282 { 283 nic_dev->rq_dbgfs = debugfs_create_dir("RQs", nic_dev->dbgfs_root); 284 } 285 286 void hinic_rq_dbgfs_uninit(struct hinic_dev *nic_dev) 287 { 288 debugfs_remove_recursive(nic_dev->rq_dbgfs); 289 } 290 291 void hinic_func_tbl_dbgfs_init(struct hinic_dev *nic_dev) 292 { 293 if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) 294 nic_dev->func_tbl_dbgfs = debugfs_create_dir("func_table", nic_dev->dbgfs_root); 295 } 296 297 void hinic_func_tbl_dbgfs_uninit(struct hinic_dev *nic_dev) 298 { 299 if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) 300 debugfs_remove_recursive(nic_dev->func_tbl_dbgfs); 301 } 302 303 void hinic_dbg_init(struct hinic_dev *nic_dev) 304 { 305 nic_dev->dbgfs_root = debugfs_create_dir(pci_name(nic_dev->hwdev->hwif->pdev), 306 hinic_dbgfs_root); 307 } 308 309 void hinic_dbg_uninit(struct hinic_dev *nic_dev) 310 { 311 debugfs_remove_recursive(nic_dev->dbgfs_root); 312 nic_dev->dbgfs_root = NULL; 313 } 314 315 void hinic_dbg_register_debugfs(const char *debugfs_dir_name) 316 { 317 hinic_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL); 318 } 319 320 void hinic_dbg_unregister_debugfs(void) 321 { 322 debugfs_remove_recursive(hinic_dbgfs_root); 323 hinic_dbgfs_root = NULL; 324 } 325