Commit 0355dea3 authored by wenglianfa's avatar wenglianfa Committed by Juan Zhou
Browse files

RDMA/hns: Support SRQ Context tracing by debugfs

driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8GHD9



--------------------------------------------------------------------------

Support SRQ Context tracing by debugfs

Example:

$echo 0 > sys/kernel/debug/hns_roce/hns_0/srq/srqn
$cat sys/kernel/debug/hns_roce/hns_0/srq/srqn
0
$cat  sys/kernel/debug/hns_roce/hns_0/srq/srqc
[{
	"srqn": 0,
	"ifindex": 0,
	"ifname": "hns_0",
	"data": [ 149,0,0,0,0,0,0,0,0,0,0,0,20,84,
		  21,82,0,254,61,31,0,0,0,0,3,0,0,
		  1,0,10,62,31,0,0,0,0,6,159,15,0,
		  0,0,64,5,0,0,0,0,0,0,0,0,0,0,0,9,
		  0,0,0,0,0,0,0,0 ]
}]

Signed-off-by: default avatarwenglianfa <wenglianfa@huawei.com>
parent b6643496
Loading
Loading
Loading
Loading
+120 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@ static struct dentry *hns_roce_dbgfs_root;

#define KB 1024

#define SRQN_BUF_SIZE 12

static int hns_debugfs_seqfile_open(struct inode *inode, struct file *f)
{
	struct hns_debugfs_seqfile *seqfile = inode->i_private;
@@ -21,6 +23,107 @@ static int hns_debugfs_seqfile_open(struct inode *inode, struct file *f)
	return single_open(f, seqfile->read, seqfile->data);
}

static ssize_t srqn_debugfs_store(struct file *file, const char __user *user_buf,
				  size_t size, loff_t *ppos)
{
	struct hns_roce_dev *hr_dev = file->private_data;
	struct hns_srq_debugfs *dbgfs = &hr_dev->dbgfs.srq_root;
	atomic_t *atomic_srqn = &dbgfs->atomic_srqn;
	u32 max = hr_dev->srq_table.srq_ida.max;
	u32 num;
	int ret;

	if (size > SRQN_BUF_SIZE)
		return -EINVAL;

	ret = kstrtou32_from_user(user_buf, size, 0, &num);
	if (ret)
		return ret;

	if (num > max)
		return -ERANGE;

	atomic_set(atomic_srqn, (int)num);

	return size;
}

static ssize_t srqn_debugfs_show(struct file *file, char __user *user_buf,
				 size_t size, loff_t *ppos)
{
	struct hns_roce_dev *hr_dev = file->private_data;
	struct hns_srq_debugfs *dbgfs = &hr_dev->dbgfs.srq_root;
	u32 srqn = (u32)atomic_read(&dbgfs->atomic_srqn);
	char buf[SRQN_BUF_SIZE];
	int ret;

	ret = snprintf(buf, sizeof(buf), "%u\n", srqn);
	if (ret < 0)
		return ret;

	return simple_read_from_buffer(user_buf, size, ppos, buf, ret);
}

static void print_json_srqc(struct ib_device *device,
			    struct seq_file *file,
			    uint8_t *data,
			    u32 srqn,
			    int size)
{
	int i = 0;

	seq_puts(file, "[ {\n");
	seq_printf(file, "\t\"srqn\": %u,\n", srqn);
	seq_printf(file, "\t\"ifindex\": %u,\n", device->index);
	seq_printf(file, "\t\"ifname\": \"%s\",\n", dev_name(&device->dev));
	seq_puts(file, "\t\"data\": [ ");
	while (i < size - 1) {
		seq_printf(file, "%d,", data[i]);
		i++;
	}
	seq_printf(file, "%d", data[i]);
	seq_puts(file, " ]\n");
	seq_puts(file, "} ]\n");
}

static int srqc_debugfs_show(struct seq_file *file, void *offset)
{
	struct hns_roce_dev *hr_dev = file->private;
	struct hns_srq_debugfs *dbgfs = &hr_dev->dbgfs.srq_root;
	int srqc_size = hr_dev->caps.srqc_entry_sz;
	u32 srqn = (u32)atomic_read(&dbgfs->atomic_srqn);
	void *data;
	int ret;

	if (!hns_roce_is_srq_exist(hr_dev, srqn))
		return -EINVAL;

	if (!hr_dev->hw->query_srqc)
		return -EOPNOTSUPP;

	data = kvcalloc(1, srqc_size, GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	ret = hr_dev->hw->query_srqc(hr_dev, srqn, data);
	if (ret)
		goto out;

	print_json_srqc(&hr_dev->ib_dev, file, data, srqn, srqc_size);

out:
	kvfree(data);

	return ret;
}

static const struct file_operations hns_srqn_fops = {
	.owner = THIS_MODULE,
	.open	= simple_open,
	.write	= srqn_debugfs_store,
	.read = srqn_debugfs_show,
};

static const struct file_operations hns_debugfs_seqfile_fops = {
	.owner = THIS_MODULE,
	.open = hns_debugfs_seqfile_open,
@@ -555,6 +658,22 @@ static void create_sw_stat_debugfs(struct hns_roce_dev *hr_dev,
			     sw_stat_debugfs_show, hr_dev);
}

static void create_srq_debugfs(struct hns_roce_dev *hr_dev,
				struct dentry *parent)
{
	struct hns_srq_debugfs *dbgfs = &hr_dev->dbgfs.srq_root;

	atomic_set(&dbgfs->atomic_srqn, 0);

	dbgfs->root = debugfs_create_dir("srq", parent);

	dbgfs->srqn.entry = debugfs_create_file("srqn", 0600, dbgfs->root,
						hr_dev, &hns_srqn_fops);

	init_debugfs_seqfile(&dbgfs->srqc, "srqc", dbgfs->root,
			     srqc_debugfs_show, hr_dev);
}

/* debugfs for device */
void hns_roce_register_debugfs(struct hns_roce_dev *hr_dev)
{
@@ -570,6 +689,7 @@ void hns_roce_register_debugfs(struct hns_roce_dev *hr_dev)
		create_poe_debugfs(hr_dev, dbgfs->root);

	create_sw_stat_debugfs(hr_dev, dbgfs->root);
	create_srq_debugfs(hr_dev, dbgfs->root);
}

void hns_roce_unregister_debugfs(struct hns_roce_dev *hr_dev)
+8 −0
Original line number Diff line number Diff line
@@ -42,12 +42,20 @@ struct hns_sw_stat_debugfs {
	struct hns_debugfs_seqfile sw_stat;
};

struct hns_srq_debugfs {
	struct dentry *root;
	struct hns_debugfs_seqfile srqc;
	struct hns_debugfs_seqfile srqn;
	atomic_t atomic_srqn;
};

/* Debugfs for device */
struct hns_roce_dev_debugfs {
	struct dentry *root;
	struct hns_dca_debugfs dca_root;
	struct hns_poe_debugfs poe_root;
	struct hns_sw_stat_debugfs sw_stat_root;
	struct hns_srq_debugfs srq_root;
};

struct hns_roce_dev;
+2 −0
Original line number Diff line number Diff line
@@ -1063,6 +1063,7 @@ struct hns_roce_hw {
	int (*write_srqc)(struct hns_roce_srq *srq, void *mb_buf);
	int (*query_cqc)(struct hns_roce_dev *hr_dev, u32 cqn, void *buffer);
	int (*query_qpc)(struct hns_roce_dev *hr_dev, u32 qpn, void *buffer);
	int (*query_srqc)(struct hns_roce_dev *hr_dev, u32 srqn, void *buffer);
	int (*query_mpt)(struct hns_roce_dev *hr_dev, u32 key, void *buffer);
	int (*query_sccc)(struct hns_roce_dev *hr_dev, u32 qpn, void *buffer);
	int (*get_dscp)(struct hns_roce_dev *hr_dev, u8 dscp,
@@ -1493,4 +1494,5 @@ void hns_roce_unregister_sysfs(struct hns_roce_dev *hr_dev);
int hns_roce_register_poe_channel(struct hns_roce_dev *hr_dev, u8 channel,
				  u64 poe_addr);
int hns_roce_unregister_poe_channel(struct hns_roce_dev *hr_dev, u8 channel);
bool hns_roce_is_srq_exist(struct hns_roce_dev *hr_dev, u32 srqn);
#endif /* _HNS_ROCE_DEVICE_H */
+25 −0
Original line number Diff line number Diff line
@@ -5773,6 +5773,30 @@ static int hns_roce_v2_query_qpc(struct hns_roce_dev *hr_dev, u32 qpn,
	return ret;
}

static int hns_roce_v2_query_srqc(struct hns_roce_dev *hr_dev, u32 srqn,
				 void *buffer)
{
	struct hns_roce_srq_context *context;
	struct hns_roce_cmd_mailbox *mailbox;
	int ret;

	mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
	if (IS_ERR(mailbox))
		return PTR_ERR(mailbox);

	context  = mailbox->buf;
	ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, HNS_ROCE_CMD_QUERY_SRQC,
				srqn);
	if (ret)
		goto out;

	memcpy(buffer, context, sizeof(*context));

out:
	hns_roce_free_cmd_mailbox(hr_dev, mailbox);
	return ret;
}

static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 qpn,
				  void *buffer)
{
@@ -7350,6 +7374,7 @@ static const struct hns_roce_hw hns_roce_hw_v2 = {
	.query_cqc = hns_roce_v2_query_cqc,
	.query_qpc = hns_roce_v2_query_qpc,
	.query_mpt = hns_roce_v2_query_mpt,
	.query_srqc = hns_roce_v2_query_srqc,
	.query_sccc = hns_roce_v2_query_sccc,
	.get_dscp = hns_roce_hw_v2_get_dscp,
	.hns_roce_dev_ops = &hns_roce_v2_dev_ops,
+12 −0
Original line number Diff line number Diff line
@@ -31,6 +31,18 @@ void hns_roce_srq_event(struct hns_roce_dev *hr_dev, u32 srqn, int event_type)
		complete(&srq->free);
}

bool hns_roce_is_srq_exist(struct hns_roce_dev *hr_dev, u32 srqn)
{
	struct hns_roce_srq_table *srq_table = &hr_dev->srq_table;
	struct hns_roce_srq *srq;

	xa_lock(&srq_table->xa);
	srq = xa_load(&srq_table->xa, srqn);
	xa_unlock(&srq_table->xa);

	return srq != NULL;
}

static void hns_roce_ib_srq_event(struct hns_roce_srq *srq,
				  enum hns_roce_event event_type)
{