brintos

brintos / linux-shallow public Read only

0
0
Text · 7.3 KiB · 061952c Raw
325 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Huawei HiNIC PCI Express Linux driver3 * Copyright(c) 2017 Huawei Technologies Co., Ltd4 */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 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 136static 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 172static const struct file_operations hinic_dbg_cmd_fops = {173	.owner = THIS_MODULE,174	.open  = simple_open,175	.read  = hinic_dbg_cmd_read,176};177 178static 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 204static 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 212int 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 228void hinic_sq_debug_rem(struct hinic_sq *sq)229{230	if (sq->dbg)231		rem_dbg_files(sq->dbg);232}233 234int 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 250void hinic_rq_debug_rem(struct hinic_rq *rq)251{252	if (rq->dbg)253		rem_dbg_files(rq->dbg);254}255 256int 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 265void 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 271void 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 276void hinic_sq_dbgfs_uninit(struct hinic_dev *nic_dev)277{278	debugfs_remove_recursive(nic_dev->sq_dbgfs);279}280 281void 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 286void hinic_rq_dbgfs_uninit(struct hinic_dev *nic_dev)287{288	debugfs_remove_recursive(nic_dev->rq_dbgfs);289}290 291void 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 297void 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 303void 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 309void 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 315void hinic_dbg_register_debugfs(const char *debugfs_dir_name)316{317	hinic_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL);318}319 320void hinic_dbg_unregister_debugfs(void)321{322	debugfs_remove_recursive(hinic_dbgfs_root);323	hinic_dbgfs_root = NULL;324}325