From: wenglianfa wenglianfa@huawei.com
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: wenglianfa wenglianfa@huawei.com --- drivers/infiniband/hw/hns/hns_roce_debugfs.c | 120 +++++++++++++++++++ drivers/infiniband/hw/hns/hns_roce_debugfs.h | 8 ++ drivers/infiniband/hw/hns/hns_roce_device.h | 2 + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 25 ++++ drivers/infiniband/hw/hns/hns_roce_srq.c | 12 ++ 5 files changed, 167 insertions(+)
diff --git a/drivers/infiniband/hw/hns/hns_roce_debugfs.c b/drivers/infiniband/hw/hns/hns_roce_debugfs.c index 4be024470b05..cff0ebbce004 100644 --- a/drivers/infiniband/hw/hns/hns_roce_debugfs.c +++ b/drivers/infiniband/hw/hns/hns_roce_debugfs.c @@ -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) diff --git a/drivers/infiniband/hw/hns/hns_roce_debugfs.h b/drivers/infiniband/hw/hns/hns_roce_debugfs.h index 0b0cac241733..3c1f428b47e2 100644 --- a/drivers/infiniband/hw/hns/hns_roce_debugfs.h +++ b/drivers/infiniband/hw/hns/hns_roce_debugfs.h @@ -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; diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index 89837e003776..743453accfd7 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -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 */ diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 1829b90b8ba8..bd2d8e447c19 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -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, diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c index e135d2bbe049..1e8b7a65519f 100644 --- a/drivers/infiniband/hw/hns/hns_roce_srq.c +++ b/drivers/infiniband/hw/hns/hns_roce_srq.c @@ -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) {