Commit 77b34110 authored by Fuyun Liang's avatar Fuyun Liang Committed by David S. Miller

net: hns3: add support for get_regs

This patch adds get_regs support for ethtool cmd.
Signed-off-by: default avatarFuyun Liang <liangfuyun1@huawei.com>
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b2d3bcfa
...@@ -356,7 +356,8 @@ struct hnae3_ae_ops { ...@@ -356,7 +356,8 @@ struct hnae3_ae_ops {
u32 stringset, u8 *data); u32 stringset, u8 *data);
int (*get_sset_count)(struct hnae3_handle *handle, int stringset); int (*get_sset_count)(struct hnae3_handle *handle, int stringset);
void (*get_regs)(struct hnae3_handle *handle, void *data); void (*get_regs)(struct hnae3_handle *handle, u32 *version,
void *data);
int (*get_regs_len)(struct hnae3_handle *handle); int (*get_regs_len)(struct hnae3_handle *handle);
u32 (*get_rss_key_size)(struct hnae3_handle *handle); u32 (*get_rss_key_size)(struct hnae3_handle *handle);
......
...@@ -1063,6 +1063,27 @@ static int hns3_set_coalesce(struct net_device *netdev, ...@@ -1063,6 +1063,27 @@ static int hns3_set_coalesce(struct net_device *netdev,
return 0; return 0;
} }
static int hns3_get_regs_len(struct net_device *netdev)
{
struct hnae3_handle *h = hns3_get_handle(netdev);
if (!h->ae_algo->ops->get_regs_len)
return -EOPNOTSUPP;
return h->ae_algo->ops->get_regs_len(h);
}
static void hns3_get_regs(struct net_device *netdev,
struct ethtool_regs *cmd, void *data)
{
struct hnae3_handle *h = hns3_get_handle(netdev);
if (!h->ae_algo->ops->get_regs)
return;
h->ae_algo->ops->get_regs(h, &cmd->version, data);
}
static const struct ethtool_ops hns3vf_ethtool_ops = { static const struct ethtool_ops hns3vf_ethtool_ops = {
.get_drvinfo = hns3_get_drvinfo, .get_drvinfo = hns3_get_drvinfo,
.get_ringparam = hns3_get_ringparam, .get_ringparam = hns3_get_ringparam,
...@@ -1103,6 +1124,8 @@ static const struct ethtool_ops hns3_ethtool_ops = { ...@@ -1103,6 +1124,8 @@ static const struct ethtool_ops hns3_ethtool_ops = {
.set_channels = hns3_set_channels, .set_channels = hns3_set_channels,
.get_coalesce = hns3_get_coalesce, .get_coalesce = hns3_get_coalesce,
.set_coalesce = hns3_set_coalesce, .set_coalesce = hns3_set_coalesce,
.get_regs_len = hns3_get_regs_len,
.get_regs = hns3_get_regs,
}; };
void hns3_ethtool_set_ops(struct net_device *netdev) void hns3_ethtool_set_ops(struct net_device *netdev)
......
...@@ -102,6 +102,10 @@ enum hclge_opcode_type { ...@@ -102,6 +102,10 @@ enum hclge_opcode_type {
HCLGE_OPC_STATS_64_BIT = 0x0030, HCLGE_OPC_STATS_64_BIT = 0x0030,
HCLGE_OPC_STATS_32_BIT = 0x0031, HCLGE_OPC_STATS_32_BIT = 0x0031,
HCLGE_OPC_STATS_MAC = 0x0032, HCLGE_OPC_STATS_MAC = 0x0032,
HCLGE_OPC_QUERY_REG_NUM = 0x0040,
HCLGE_OPC_QUERY_32_BIT_REG = 0x0041,
HCLGE_OPC_QUERY_64_BIT_REG = 0x0042,
/* Device management command */ /* Device management command */
/* MAC commond */ /* MAC commond */
......
...@@ -5544,6 +5544,180 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num) ...@@ -5544,6 +5544,180 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
return ret; return ret;
} }
static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit,
u32 *regs_num_64_bit)
{
struct hclge_desc desc;
u32 total_num;
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
dev_err(&hdev->pdev->dev,
"Query register number cmd failed, ret = %d.\n", ret);
return ret;
}
*regs_num_32_bit = le32_to_cpu(desc.data[0]);
*regs_num_64_bit = le32_to_cpu(desc.data[1]);
total_num = *regs_num_32_bit + *regs_num_64_bit;
if (!total_num)
return -EINVAL;
return 0;
}
static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num,
void *data)
{
#define HCLGE_32_BIT_REG_RTN_DATANUM 8
struct hclge_desc *desc;
u32 *reg_val = data;
__le32 *desc_data;
int cmd_num;
int i, k, n;
int ret;
if (regs_num == 0)
return 0;
cmd_num = DIV_ROUND_UP(regs_num + 2, HCLGE_32_BIT_REG_RTN_DATANUM);
desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true);
ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
if (ret) {
dev_err(&hdev->pdev->dev,
"Query 32 bit register cmd failed, ret = %d.\n", ret);
kfree(desc);
return ret;
}
for (i = 0; i < cmd_num; i++) {
if (i == 0) {
desc_data = (__le32 *)(&desc[i].data[0]);
n = HCLGE_32_BIT_REG_RTN_DATANUM - 2;
} else {
desc_data = (__le32 *)(&desc[i]);
n = HCLGE_32_BIT_REG_RTN_DATANUM;
}
for (k = 0; k < n; k++) {
*reg_val++ = le32_to_cpu(*desc_data++);
regs_num--;
if (!regs_num)
break;
}
}
kfree(desc);
return 0;
}
static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num,
void *data)
{
#define HCLGE_64_BIT_REG_RTN_DATANUM 4
struct hclge_desc *desc;
u64 *reg_val = data;
__le64 *desc_data;
int cmd_num;
int i, k, n;
int ret;
if (regs_num == 0)
return 0;
cmd_num = DIV_ROUND_UP(regs_num + 1, HCLGE_64_BIT_REG_RTN_DATANUM);
desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true);
ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
if (ret) {
dev_err(&hdev->pdev->dev,
"Query 64 bit register cmd failed, ret = %d.\n", ret);
kfree(desc);
return ret;
}
for (i = 0; i < cmd_num; i++) {
if (i == 0) {
desc_data = (__le64 *)(&desc[i].data[0]);
n = HCLGE_64_BIT_REG_RTN_DATANUM - 1;
} else {
desc_data = (__le64 *)(&desc[i]);
n = HCLGE_64_BIT_REG_RTN_DATANUM;
}
for (k = 0; k < n; k++) {
*reg_val++ = le64_to_cpu(*desc_data++);
regs_num--;
if (!regs_num)
break;
}
}
kfree(desc);
return 0;
}
static int hclge_get_regs_len(struct hnae3_handle *handle)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
u32 regs_num_32_bit, regs_num_64_bit;
int ret;
ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
if (ret) {
dev_err(&hdev->pdev->dev,
"Get register number failed, ret = %d.\n", ret);
return -EOPNOTSUPP;
}
return regs_num_32_bit * sizeof(u32) + regs_num_64_bit * sizeof(u64);
}
static void hclge_get_regs(struct hnae3_handle *handle, u32 *version,
void *data)
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
u32 regs_num_32_bit, regs_num_64_bit;
int ret;
*version = hdev->fw_version;
ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
if (ret) {
dev_err(&hdev->pdev->dev,
"Get register number failed, ret = %d.\n", ret);
return;
}
ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, data);
if (ret) {
dev_err(&hdev->pdev->dev,
"Get 32 bit register failed, ret = %d.\n", ret);
return;
}
data = (u32 *)data + regs_num_32_bit;
ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit,
data);
if (ret)
dev_err(&hdev->pdev->dev,
"Get 64 bit register failed, ret = %d.\n", ret);
}
static const struct hnae3_ae_ops hclge_ops = { static const struct hnae3_ae_ops hclge_ops = {
.init_ae_dev = hclge_init_ae_dev, .init_ae_dev = hclge_init_ae_dev,
.uninit_ae_dev = hclge_uninit_ae_dev, .uninit_ae_dev = hclge_uninit_ae_dev,
...@@ -5595,6 +5769,8 @@ static const struct hnae3_ae_ops hclge_ops = { ...@@ -5595,6 +5769,8 @@ static const struct hnae3_ae_ops hclge_ops = {
.set_channels = hclge_set_channels, .set_channels = hclge_set_channels,
.get_channels = hclge_get_channels, .get_channels = hclge_get_channels,
.get_flowctrl_adv = hclge_get_flowctrl_adv, .get_flowctrl_adv = hclge_get_flowctrl_adv,
.get_regs_len = hclge_get_regs_len,
.get_regs = hclge_get_regs,
}; };
static struct hnae3_ae_algo ae_algo = { static struct hnae3_ae_algo ae_algo = {
......
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