Commit 253ac3a9 authored by Luo bin's avatar Luo bin Committed by David S. Miller

hinic: add support to query sq info

add debugfs node for querying sq info, for example:
cat /sys/kernel/debug/hinic/0000:15:00.0/SQs/0x0/sq_pi
Signed-off-by: default avatarLuo bin <luobin9@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c30a3c95
...@@ -4,4 +4,5 @@ obj-$(CONFIG_HINIC) += hinic.o ...@@ -4,4 +4,5 @@ obj-$(CONFIG_HINIC) += hinic.o
hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \ hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \
hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \ hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \
hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \ hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \
hinic_common.o hinic_ethtool.o hinic_devlink.o hinic_hw_mbox.o hinic_sriov.o hinic_common.o hinic_ethtool.o hinic_devlink.o hinic_hw_mbox.o \
hinic_sriov.o hinic_debugfs.o
// SPDX-License-Identifier: GPL-2.0-only
/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*/
#include <linux/debugfs.h>
#include <linux/device.h>
#include "hinic_debugfs.h"
static struct dentry *hinic_dbgfs_root;
enum sq_dbg_info {
GLB_SQ_ID,
SQ_PI,
SQ_CI,
SQ_FI,
SQ_MSIX_ENTRY,
};
static char *sq_fields[] = {"glb_sq_id", "sq_pi", "sq_ci", "sq_fi", "sq_msix_entry"};
static u64 hinic_dbg_get_sq_info(struct hinic_dev *nic_dev, struct hinic_sq *sq, int idx)
{
struct hinic_wq *wq = sq->wq;
switch (idx) {
case GLB_SQ_ID:
return nic_dev->hwdev->func_to_io.global_qpn + sq->qid;
case SQ_PI:
return atomic_read(&wq->prod_idx) & wq->mask;
case SQ_CI:
return atomic_read(&wq->cons_idx) & wq->mask;
case SQ_FI:
return be16_to_cpu(*(__be16 *)(sq->hw_ci_addr)) & wq->mask;
case SQ_MSIX_ENTRY:
return sq->msix_entry;
}
return 0;
}
static ssize_t hinic_dbg_cmd_read(struct file *filp, char __user *buffer, size_t count,
loff_t *ppos)
{
struct hinic_debug_priv *dbg;
char ret_buf[20];
int *desc;
u64 out;
int ret;
desc = filp->private_data;
dbg = container_of(desc, struct hinic_debug_priv, field_id[*desc]);
switch (dbg->type) {
case HINIC_DBG_SQ_INFO:
out = hinic_dbg_get_sq_info(dbg->dev, dbg->object, *desc);
break;
default:
netif_warn(dbg->dev, drv, dbg->dev->netdev, "Invalid hinic debug cmd: %d\n",
dbg->type);
return -EINVAL;
}
ret = snprintf(ret_buf, sizeof(ret_buf), "0x%llx\n", out);
return simple_read_from_buffer(buffer, count, ppos, ret_buf, ret);
}
static const struct file_operations hinic_dbg_cmd_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = hinic_dbg_cmd_read,
};
static int create_dbg_files(struct hinic_dev *dev, enum hinic_dbg_type type, void *data,
struct dentry *root, struct hinic_debug_priv **dbg, char **field,
int nfile)
{
struct hinic_debug_priv *tmp;
int i;
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
tmp->dev = dev;
tmp->object = data;
tmp->type = type;
tmp->root = root;
for (i = 0; i < nfile; i++) {
tmp->field_id[i] = i;
debugfs_create_file(field[i], 0400, root, &tmp->field_id[i], &hinic_dbg_cmd_fops);
}
*dbg = tmp;
return 0;
}
static void rem_dbg_files(struct hinic_debug_priv *dbg)
{
debugfs_remove_recursive(dbg->root);
kfree(dbg);
}
int hinic_sq_debug_add(struct hinic_dev *dev, u16 sq_id)
{
struct hinic_sq *sq;
struct dentry *root;
char sub_dir[16];
sq = dev->txqs[sq_id].sq;
sprintf(sub_dir, "0x%x", sq_id);
root = debugfs_create_dir(sub_dir, dev->sq_dbgfs);
return create_dbg_files(dev, HINIC_DBG_SQ_INFO, sq, root, &sq->dbg, sq_fields,
ARRAY_SIZE(sq_fields));
}
void hinic_sq_debug_rem(struct hinic_sq *sq)
{
if (sq->dbg)
rem_dbg_files(sq->dbg);
}
void hinic_sq_dbgfs_init(struct hinic_dev *nic_dev)
{
nic_dev->sq_dbgfs = debugfs_create_dir("SQs", nic_dev->dbgfs_root);
}
void hinic_sq_dbgfs_uninit(struct hinic_dev *nic_dev)
{
debugfs_remove_recursive(nic_dev->sq_dbgfs);
}
void hinic_dbg_init(struct hinic_dev *nic_dev)
{
nic_dev->dbgfs_root = debugfs_create_dir(pci_name(nic_dev->hwdev->hwif->pdev),
hinic_dbgfs_root);
}
void hinic_dbg_uninit(struct hinic_dev *nic_dev)
{
debugfs_remove_recursive(nic_dev->dbgfs_root);
nic_dev->dbgfs_root = NULL;
}
void hinic_dbg_register_debugfs(const char *debugfs_dir_name)
{
hinic_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
}
void hinic_dbg_unregister_debugfs(void)
{
debugfs_remove_recursive(hinic_dbgfs_root);
hinic_dbgfs_root = NULL;
}
/* SPDX-License-Identifier: GPL-2.0-only */
/* Huawei HiNIC PCI Express Linux driver
* Copyright(c) 2017 Huawei Technologies Co., Ltd
*/
#ifndef HINIC_DEBUGFS_H
#define HINIC_DEBUGFS_H
#include "hinic_dev.h"
int hinic_sq_debug_add(struct hinic_dev *dev, u16 sq_id);
void hinic_sq_debug_rem(struct hinic_sq *sq);
void hinic_sq_dbgfs_init(struct hinic_dev *nic_dev);
void hinic_sq_dbgfs_uninit(struct hinic_dev *nic_dev);
void hinic_dbg_init(struct hinic_dev *nic_dev);
void hinic_dbg_uninit(struct hinic_dev *nic_dev);
void hinic_dbg_register_debugfs(const char *debugfs_dir_name);
void hinic_dbg_unregister_debugfs(void);
#endif
...@@ -58,6 +58,18 @@ struct hinic_intr_coal_info { ...@@ -58,6 +58,18 @@ struct hinic_intr_coal_info {
u8 resend_timer_cfg; u8 resend_timer_cfg;
}; };
enum hinic_dbg_type {
HINIC_DBG_SQ_INFO,
};
struct hinic_debug_priv {
struct hinic_dev *dev;
void *object;
enum hinic_dbg_type type;
struct dentry *root;
int field_id[64];
};
struct hinic_dev { struct hinic_dev {
struct net_device *netdev; struct net_device *netdev;
struct hinic_hwdev *hwdev; struct hinic_hwdev *hwdev;
...@@ -97,6 +109,9 @@ struct hinic_dev { ...@@ -97,6 +109,9 @@ struct hinic_dev {
int lb_test_rx_idx; int lb_test_rx_idx;
int lb_pkt_len; int lb_pkt_len;
u8 *lb_test_rx_buf; u8 *lb_test_rx_buf;
struct dentry *dbgfs_root;
struct dentry *sq_dbgfs;
struct devlink *devlink; struct devlink *devlink;
bool cable_unplugged; bool cable_unplugged;
bool module_unrecognized; bool module_unrecognized;
......
...@@ -465,6 +465,7 @@ int hinic_hwdev_ifup(struct hinic_hwdev *hwdev, u16 sq_depth, u16 rq_depth) ...@@ -465,6 +465,7 @@ int hinic_hwdev_ifup(struct hinic_hwdev *hwdev, u16 sq_depth, u16 rq_depth)
func_to_io->hwdev = hwdev; func_to_io->hwdev = hwdev;
func_to_io->sq_depth = sq_depth; func_to_io->sq_depth = sq_depth;
func_to_io->rq_depth = rq_depth; func_to_io->rq_depth = rq_depth;
func_to_io->global_qpn = base_qpn;
err = hinic_io_init(func_to_io, hwif, nic_cap->max_qps, num_ceqs, err = hinic_io_init(func_to_io, hwif, nic_cap->max_qps, num_ceqs,
ceq_msix_entries); ceq_msix_entries);
......
...@@ -305,6 +305,7 @@ static int init_qp(struct hinic_func_to_io *func_to_io, ...@@ -305,6 +305,7 @@ static int init_qp(struct hinic_func_to_io *func_to_io,
func_to_io->sq_db[q_id] = db_base; func_to_io->sq_db[q_id] = db_base;
qp->sq.qid = q_id;
err = hinic_init_sq(&qp->sq, hwif, &func_to_io->sq_wq[q_id], err = hinic_init_sq(&qp->sq, hwif, &func_to_io->sq_wq[q_id],
sq_msix_entry, sq_msix_entry,
CI_ADDR(func_to_io->ci_addr_base, q_id), CI_ADDR(func_to_io->ci_addr_base, q_id),
......
...@@ -59,6 +59,7 @@ struct hinic_nic_cfg { ...@@ -59,6 +59,7 @@ struct hinic_nic_cfg {
struct hinic_func_to_io { struct hinic_func_to_io {
struct hinic_hwif *hwif; struct hinic_hwif *hwif;
struct hinic_hwdev *hwdev; struct hinic_hwdev *hwdev;
u16 global_qpn;
struct hinic_ceqs ceqs; struct hinic_ceqs ceqs;
struct hinic_wqs wqs; struct hinic_wqs wqs;
......
...@@ -81,6 +81,8 @@ struct hinic_sq { ...@@ -81,6 +81,8 @@ struct hinic_sq {
struct hinic_wq *wq; struct hinic_wq *wq;
u16 qid;
u32 irq; u32 irq;
u16 msix_entry; u16 msix_entry;
...@@ -90,6 +92,7 @@ struct hinic_sq { ...@@ -90,6 +92,7 @@ struct hinic_sq {
void __iomem *db_base; void __iomem *db_base;
struct sk_buff **saved_skb; struct sk_buff **saved_skb;
struct hinic_debug_priv *dbg;
}; };
struct hinic_rq { struct hinic_rq {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include "hinic_debugfs.h"
#include "hinic_hw_qp.h" #include "hinic_hw_qp.h"
#include "hinic_hw_dev.h" #include "hinic_hw_dev.h"
#include "hinic_devlink.h" #include "hinic_devlink.h"
...@@ -153,6 +154,8 @@ static int create_txqs(struct hinic_dev *nic_dev) ...@@ -153,6 +154,8 @@ static int create_txqs(struct hinic_dev *nic_dev)
if (!nic_dev->txqs) if (!nic_dev->txqs)
return -ENOMEM; return -ENOMEM;
hinic_sq_dbgfs_init(nic_dev);
for (i = 0; i < num_txqs; i++) { for (i = 0; i < num_txqs; i++) {
struct hinic_sq *sq = hinic_hwdev_get_sq(nic_dev->hwdev, i); struct hinic_sq *sq = hinic_hwdev_get_sq(nic_dev->hwdev, i);
...@@ -162,13 +165,27 @@ static int create_txqs(struct hinic_dev *nic_dev) ...@@ -162,13 +165,27 @@ static int create_txqs(struct hinic_dev *nic_dev)
"Failed to init Txq\n"); "Failed to init Txq\n");
goto err_init_txq; goto err_init_txq;
} }
err = hinic_sq_debug_add(nic_dev, i);
if (err) {
netif_err(nic_dev, drv, netdev,
"Failed to add SQ%d debug\n", i);
goto err_add_sq_dbg;
}
} }
return 0; return 0;
err_add_sq_dbg:
hinic_clean_txq(&nic_dev->txqs[i]);
err_init_txq: err_init_txq:
for (j = 0; j < i; j++) for (j = 0; j < i; j++) {
hinic_sq_debug_rem(nic_dev->txqs[j].sq);
hinic_clean_txq(&nic_dev->txqs[j]); hinic_clean_txq(&nic_dev->txqs[j]);
}
hinic_sq_dbgfs_uninit(nic_dev);
devm_kfree(&netdev->dev, nic_dev->txqs); devm_kfree(&netdev->dev, nic_dev->txqs);
return err; return err;
...@@ -186,8 +203,12 @@ static void free_txqs(struct hinic_dev *nic_dev) ...@@ -186,8 +203,12 @@ static void free_txqs(struct hinic_dev *nic_dev)
if (!nic_dev->txqs) if (!nic_dev->txqs)
return; return;
for (i = 0; i < num_txqs; i++) for (i = 0; i < num_txqs; i++) {
hinic_sq_debug_rem(nic_dev->txqs[i].sq);
hinic_clean_txq(&nic_dev->txqs[i]); hinic_clean_txq(&nic_dev->txqs[i]);
}
hinic_sq_dbgfs_uninit(nic_dev);
devm_kfree(&netdev->dev, nic_dev->txqs); devm_kfree(&netdev->dev, nic_dev->txqs);
nic_dev->txqs = NULL; nic_dev->txqs = NULL;
...@@ -1260,6 +1281,8 @@ static int nic_dev_init(struct pci_dev *pdev) ...@@ -1260,6 +1281,8 @@ static int nic_dev_init(struct pci_dev *pdev)
goto err_init_intr; goto err_init_intr;
} }
hinic_dbg_init(nic_dev);
err = register_netdev(netdev); err = register_netdev(netdev);
if (err) { if (err) {
dev_err(&pdev->dev, "Failed to register netdev\n"); dev_err(&pdev->dev, "Failed to register netdev\n");
...@@ -1269,6 +1292,7 @@ static int nic_dev_init(struct pci_dev *pdev) ...@@ -1269,6 +1292,7 @@ static int nic_dev_init(struct pci_dev *pdev)
return 0; return 0;
err_reg_netdev: err_reg_netdev:
hinic_dbg_uninit(nic_dev);
hinic_free_intr_coalesce(nic_dev); hinic_free_intr_coalesce(nic_dev);
err_init_intr: err_init_intr:
err_set_pfc: err_set_pfc:
...@@ -1391,6 +1415,8 @@ static void hinic_remove(struct pci_dev *pdev) ...@@ -1391,6 +1415,8 @@ static void hinic_remove(struct pci_dev *pdev)
unregister_netdev(netdev); unregister_netdev(netdev);
hinic_dbg_uninit(nic_dev);
hinic_free_intr_coalesce(nic_dev); hinic_free_intr_coalesce(nic_dev);
hinic_port_del_mac(nic_dev, netdev->dev_addr, 0); hinic_port_del_mac(nic_dev, netdev->dev_addr, 0);
...@@ -1445,4 +1471,17 @@ static struct pci_driver hinic_driver = { ...@@ -1445,4 +1471,17 @@ static struct pci_driver hinic_driver = {
.sriov_configure = hinic_pci_sriov_configure, .sriov_configure = hinic_pci_sriov_configure,
}; };
module_pci_driver(hinic_driver); static int __init hinic_module_init(void)
{
hinic_dbg_register_debugfs(HINIC_DRV_NAME);
return pci_register_driver(&hinic_driver);
}
static void __exit hinic_module_exit(void)
{
pci_unregister_driver(&hinic_driver);
hinic_dbg_unregister_debugfs();
}
module_init(hinic_module_init);
module_exit(hinic_module_exit);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment