Commit 8f49efc9 authored by David S. Miller's avatar David S. Miller

Merge branch 'hns3-devlink'

Guangbin Huang says:

====================
net: hns3: add support devlink

This series adds devlink support for the HNS3 ethernet driver.

change log:
V2 -> V3:
1. remove two patches of setting rx/tx buffer size by devlink param.

V1 -> V2:
1. add more detailed descriptions of parameters in document hns3.rst.

RFC -> V1:
1. use DEVLINK_INFO_VERSION_GENERIC_FW instead of "fw-version".
2. add devlink documentation for hns3 driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents cc19862f f2b67226
.. SPDX-License-Identifier: GPL-2.0
====================
hns3 devlink support
====================
This document describes the devlink features implemented by the ``hns3``
device driver.
The ``hns3`` driver supports reloading via ``DEVLINK_CMD_RELOAD``.
Info versions
=============
The ``hns3`` driver reports the following versions
.. list-table:: devlink info versions implemented
:widths: 10 10 80
* - Name
- Type
- Description
* - ``fw``
- running
- Used to represent the firmware version.
...@@ -34,6 +34,7 @@ parameters, info versions, and other features it supports. ...@@ -34,6 +34,7 @@ parameters, info versions, and other features it supports.
:maxdepth: 1 :maxdepth: 1
bnxt bnxt
hns3
ionic ionic
ice ice
mlx4 mlx4
......
...@@ -90,6 +90,7 @@ config HNS_ENET ...@@ -90,6 +90,7 @@ config HNS_ENET
config HNS3 config HNS3
tristate "Hisilicon Network Subsystem Support HNS3 (Framework)" tristate "Hisilicon Network Subsystem Support HNS3 (Framework)"
depends on PCI depends on PCI
select NET_DEVLINK
help help
This selects the framework support for Hisilicon Network Subsystem 3. This selects the framework support for Hisilicon Network Subsystem 3.
This layer facilitates clients like ENET, RoCE and user-space ethernet This layer facilitates clients like ENET, RoCE and user-space ethernet
......
...@@ -7,6 +7,6 @@ ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3 ...@@ -7,6 +7,6 @@ ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3
ccflags-y += -I $(srctree)/$(src) ccflags-y += -I $(srctree)/$(src)
obj-$(CONFIG_HNS3_HCLGE) += hclge.o obj-$(CONFIG_HNS3_HCLGE) += hclge.o
hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o hclge_err.o hclge_debugfs.o hclge_ptp.o hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o hclge_err.o hclge_debugfs.o hclge_ptp.o hclge_devlink.o
hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o
// SPDX-License-Identifier: GPL-2.0+
/* Copyright (c) 2021 Hisilicon Limited. */
#include <net/devlink.h>
#include "hclge_devlink.h"
static int hclge_devlink_info_get(struct devlink *devlink,
struct devlink_info_req *req,
struct netlink_ext_ack *extack)
{
#define HCLGE_DEVLINK_FW_STRING_LEN 32
struct hclge_devlink_priv *priv = devlink_priv(devlink);
char version_str[HCLGE_DEVLINK_FW_STRING_LEN];
struct hclge_dev *hdev = priv->hdev;
int ret;
ret = devlink_info_driver_name_put(req, KBUILD_MODNAME);
if (ret)
return ret;
snprintf(version_str, sizeof(version_str), "%lu.%lu.%lu.%lu",
hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE3_MASK,
HNAE3_FW_VERSION_BYTE3_SHIFT),
hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE2_MASK,
HNAE3_FW_VERSION_BYTE2_SHIFT),
hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE1_MASK,
HNAE3_FW_VERSION_BYTE1_SHIFT),
hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE0_MASK,
HNAE3_FW_VERSION_BYTE0_SHIFT));
return devlink_info_version_running_put(req,
DEVLINK_INFO_VERSION_GENERIC_FW,
version_str);
}
static int hclge_devlink_reload_down(struct devlink *devlink, bool netns_change,
enum devlink_reload_action action,
enum devlink_reload_limit limit,
struct netlink_ext_ack *extack)
{
struct hclge_devlink_priv *priv = devlink_priv(devlink);
struct hclge_dev *hdev = priv->hdev;
struct hnae3_handle *h = &hdev->vport->nic;
struct pci_dev *pdev = hdev->pdev;
int ret;
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) {
dev_err(&pdev->dev, "reset is handling\n");
return -EBUSY;
}
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
rtnl_lock();
ret = hdev->nic_client->ops->reset_notify(h, HNAE3_DOWN_CLIENT);
if (ret) {
rtnl_unlock();
return ret;
}
ret = hdev->nic_client->ops->reset_notify(h,
HNAE3_UNINIT_CLIENT);
rtnl_unlock();
return ret;
default:
return -EOPNOTSUPP;
}
}
static int hclge_devlink_reload_up(struct devlink *devlink,
enum devlink_reload_action action,
enum devlink_reload_limit limit,
u32 *actions_performed,
struct netlink_ext_ack *extack)
{
struct hclge_devlink_priv *priv = devlink_priv(devlink);
struct hclge_dev *hdev = priv->hdev;
struct hnae3_handle *h = &hdev->vport->nic;
int ret;
*actions_performed = BIT(action);
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
rtnl_lock();
ret = hdev->nic_client->ops->reset_notify(h, HNAE3_INIT_CLIENT);
if (ret) {
rtnl_unlock();
return ret;
}
ret = hdev->nic_client->ops->reset_notify(h, HNAE3_UP_CLIENT);
rtnl_unlock();
return ret;
default:
return -EOPNOTSUPP;
}
}
static const struct devlink_ops hclge_devlink_ops = {
.info_get = hclge_devlink_info_get,
.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
.reload_down = hclge_devlink_reload_down,
.reload_up = hclge_devlink_reload_up,
};
int hclge_devlink_init(struct hclge_dev *hdev)
{
struct pci_dev *pdev = hdev->pdev;
struct hclge_devlink_priv *priv;
struct devlink *devlink;
int ret;
devlink = devlink_alloc(&hclge_devlink_ops,
sizeof(struct hclge_devlink_priv));
if (!devlink)
return -ENOMEM;
priv = devlink_priv(devlink);
priv->hdev = hdev;
ret = devlink_register(devlink, &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "failed to register devlink, ret = %d\n",
ret);
goto out_reg_fail;
}
hdev->devlink = devlink;
devlink_reload_enable(devlink);
return 0;
out_reg_fail:
devlink_free(devlink);
return ret;
}
void hclge_devlink_uninit(struct hclge_dev *hdev)
{
struct devlink *devlink = hdev->devlink;
if (!devlink)
return;
devlink_reload_disable(devlink);
devlink_unregister(devlink);
devlink_free(devlink);
hdev->devlink = NULL;
}
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) 2021 Hisilicon Limited. */
#ifndef __HCLGE_DEVLINK_H
#define __HCLGE_DEVLINK_H
#include "hclge_main.h"
struct hclge_devlink_priv {
struct hclge_dev *hdev;
};
int hclge_devlink_init(struct hclge_dev *hdev);
void hclge_devlink_uninit(struct hclge_dev *hdev);
#endif
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "hclge_tm.h" #include "hclge_tm.h"
#include "hclge_err.h" #include "hclge_err.h"
#include "hnae3.h" #include "hnae3.h"
#include "hclge_devlink.h"
#define HCLGE_NAME "hclge" #define HCLGE_NAME "hclge"
#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset))) #define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset)))
...@@ -11482,10 +11483,14 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) ...@@ -11482,10 +11483,14 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
if (ret) if (ret)
goto out; goto out;
ret = hclge_devlink_init(hdev);
if (ret)
goto err_pci_uninit;
/* Firmware command queue initialize */ /* Firmware command queue initialize */
ret = hclge_cmd_queue_init(hdev); ret = hclge_cmd_queue_init(hdev);
if (ret) if (ret)
goto err_pci_uninit; goto err_devlink_uninit;
/* Firmware command initialize */ /* Firmware command initialize */
ret = hclge_cmd_init(hdev); ret = hclge_cmd_init(hdev);
...@@ -11658,6 +11663,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) ...@@ -11658,6 +11663,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
pci_free_irq_vectors(pdev); pci_free_irq_vectors(pdev);
err_cmd_uninit: err_cmd_uninit:
hclge_cmd_uninit(hdev); hclge_cmd_uninit(hdev);
err_devlink_uninit:
hclge_devlink_uninit(hdev);
err_pci_uninit: err_pci_uninit:
pcim_iounmap(pdev, hdev->hw.io_base); pcim_iounmap(pdev, hdev->hw.io_base);
pci_clear_master(pdev); pci_clear_master(pdev);
...@@ -12048,6 +12055,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) ...@@ -12048,6 +12055,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
hclge_cmd_uninit(hdev); hclge_cmd_uninit(hdev);
hclge_misc_irq_uninit(hdev); hclge_misc_irq_uninit(hdev);
hclge_devlink_uninit(hdev);
hclge_pci_uninit(hdev); hclge_pci_uninit(hdev);
mutex_destroy(&hdev->vport_lock); mutex_destroy(&hdev->vport_lock);
hclge_uninit_vport_vlan_table(hdev); hclge_uninit_vport_vlan_table(hdev);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <net/devlink.h>
#include "hclge_cmd.h" #include "hclge_cmd.h"
#include "hclge_ptp.h" #include "hclge_ptp.h"
...@@ -943,6 +944,7 @@ struct hclge_dev { ...@@ -943,6 +944,7 @@ struct hclge_dev {
cpumask_t affinity_mask; cpumask_t affinity_mask;
struct irq_affinity_notify affinity_notify; struct irq_affinity_notify affinity_notify;
struct hclge_ptp *ptp; struct hclge_ptp *ptp;
struct devlink *devlink;
}; };
/* VPort level vlan tag configuration for TX direction */ /* VPort level vlan tag configuration for TX direction */
......
...@@ -7,4 +7,4 @@ ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3 ...@@ -7,4 +7,4 @@ ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3
ccflags-y += -I $(srctree)/$(src) ccflags-y += -I $(srctree)/$(src)
obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o
hclgevf-objs = hclgevf_main.o hclgevf_cmd.o hclgevf_mbx.o hclgevf-objs = hclgevf_main.o hclgevf_cmd.o hclgevf_mbx.o hclgevf_devlink.o
// SPDX-License-Identifier: GPL-2.0+
/* Copyright (c) 2021 Hisilicon Limited. */
#include <net/devlink.h>
#include "hclgevf_devlink.h"
static int hclgevf_devlink_info_get(struct devlink *devlink,
struct devlink_info_req *req,
struct netlink_ext_ack *extack)
{
#define HCLGEVF_DEVLINK_FW_STRING_LEN 32
struct hclgevf_devlink_priv *priv = devlink_priv(devlink);
char version_str[HCLGEVF_DEVLINK_FW_STRING_LEN];
struct hclgevf_dev *hdev = priv->hdev;
int ret;
ret = devlink_info_driver_name_put(req, KBUILD_MODNAME);
if (ret)
return ret;
snprintf(version_str, sizeof(version_str), "%lu.%lu.%lu.%lu",
hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE3_MASK,
HNAE3_FW_VERSION_BYTE3_SHIFT),
hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE2_MASK,
HNAE3_FW_VERSION_BYTE2_SHIFT),
hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE1_MASK,
HNAE3_FW_VERSION_BYTE1_SHIFT),
hnae3_get_field(hdev->fw_version, HNAE3_FW_VERSION_BYTE0_MASK,
HNAE3_FW_VERSION_BYTE0_SHIFT));
return devlink_info_version_running_put(req,
DEVLINK_INFO_VERSION_GENERIC_FW,
version_str);
}
static int hclgevf_devlink_reload_down(struct devlink *devlink,
bool netns_change,
enum devlink_reload_action action,
enum devlink_reload_limit limit,
struct netlink_ext_ack *extack)
{
struct hclgevf_devlink_priv *priv = devlink_priv(devlink);
struct hclgevf_dev *hdev = priv->hdev;
struct hnae3_handle *h = &hdev->nic;
struct pci_dev *pdev = hdev->pdev;
int ret;
if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) {
dev_err(&pdev->dev, "reset is handling\n");
return -EBUSY;
}
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
rtnl_lock();
ret = hdev->nic_client->ops->reset_notify(h, HNAE3_DOWN_CLIENT);
if (ret) {
rtnl_unlock();
return ret;
}
ret = hdev->nic_client->ops->reset_notify(h,
HNAE3_UNINIT_CLIENT);
rtnl_unlock();
return ret;
default:
return -EOPNOTSUPP;
}
}
static int hclgevf_devlink_reload_up(struct devlink *devlink,
enum devlink_reload_action action,
enum devlink_reload_limit limit,
u32 *actions_performed,
struct netlink_ext_ack *extack)
{
struct hclgevf_devlink_priv *priv = devlink_priv(devlink);
struct hclgevf_dev *hdev = priv->hdev;
struct hnae3_handle *h = &hdev->nic;
int ret;
*actions_performed = BIT(action);
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
rtnl_lock();
ret = hdev->nic_client->ops->reset_notify(h, HNAE3_INIT_CLIENT);
if (ret) {
rtnl_unlock();
return ret;
}
ret = hdev->nic_client->ops->reset_notify(h, HNAE3_UP_CLIENT);
rtnl_unlock();
return ret;
default:
return -EOPNOTSUPP;
}
}
static const struct devlink_ops hclgevf_devlink_ops = {
.info_get = hclgevf_devlink_info_get,
.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
.reload_down = hclgevf_devlink_reload_down,
.reload_up = hclgevf_devlink_reload_up,
};
int hclgevf_devlink_init(struct hclgevf_dev *hdev)
{
struct pci_dev *pdev = hdev->pdev;
struct hclgevf_devlink_priv *priv;
struct devlink *devlink;
int ret;
devlink = devlink_alloc(&hclgevf_devlink_ops,
sizeof(struct hclgevf_devlink_priv));
if (!devlink)
return -ENOMEM;
priv = devlink_priv(devlink);
priv->hdev = hdev;
ret = devlink_register(devlink, &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "failed to register devlink, ret = %d\n",
ret);
goto out_reg_fail;
}
hdev->devlink = devlink;
devlink_reload_enable(devlink);
return 0;
out_reg_fail:
devlink_free(devlink);
return ret;
}
void hclgevf_devlink_uninit(struct hclgevf_dev *hdev)
{
struct devlink *devlink = hdev->devlink;
if (!devlink)
return;
devlink_reload_disable(devlink);
devlink_unregister(devlink);
devlink_free(devlink);
hdev->devlink = NULL;
}
/* SPDX-License-Identifier: GPL-2.0+ */
/* Copyright (c) 2021 Hisilicon Limited. */
#ifndef __HCLGEVF_DEVLINK_H
#define __HCLGEVF_DEVLINK_H
#include "hclgevf_main.h"
struct hclgevf_devlink_priv {
struct hclgevf_dev *hdev;
};
int hclgevf_devlink_init(struct hclgevf_dev *hdev);
void hclgevf_devlink_uninit(struct hclgevf_dev *hdev);
#endif
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "hclgevf_main.h" #include "hclgevf_main.h"
#include "hclge_mbx.h" #include "hclge_mbx.h"
#include "hnae3.h" #include "hnae3.h"
#include "hclgevf_devlink.h"
#define HCLGEVF_NAME "hclgevf" #define HCLGEVF_NAME "hclgevf"
...@@ -3337,6 +3338,10 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) ...@@ -3337,6 +3338,10 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
if (ret) if (ret)
return ret; return ret;
ret = hclgevf_devlink_init(hdev);
if (ret)
goto err_devlink_init;
ret = hclgevf_cmd_queue_init(hdev); ret = hclgevf_cmd_queue_init(hdev);
if (ret) if (ret)
goto err_cmd_queue_init; goto err_cmd_queue_init;
...@@ -3441,6 +3446,8 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) ...@@ -3441,6 +3446,8 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
err_cmd_init: err_cmd_init:
hclgevf_cmd_uninit(hdev); hclgevf_cmd_uninit(hdev);
err_cmd_queue_init: err_cmd_queue_init:
hclgevf_devlink_uninit(hdev);
err_devlink_init:
hclgevf_pci_uninit(hdev); hclgevf_pci_uninit(hdev);
clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state); clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
return ret; return ret;
...@@ -3462,6 +3469,7 @@ static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev) ...@@ -3462,6 +3469,7 @@ static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev)
} }
hclgevf_cmd_uninit(hdev); hclgevf_cmd_uninit(hdev);
hclgevf_devlink_uninit(hdev);
hclgevf_pci_uninit(hdev); hclgevf_pci_uninit(hdev);
hclgevf_uninit_mac_list(hdev); hclgevf_uninit_mac_list(hdev);
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/types.h> #include <linux/types.h>
#include <net/devlink.h>
#include "hclge_mbx.h" #include "hclge_mbx.h"
#include "hclgevf_cmd.h" #include "hclgevf_cmd.h"
#include "hnae3.h" #include "hnae3.h"
...@@ -330,6 +331,8 @@ struct hclgevf_dev { ...@@ -330,6 +331,8 @@ struct hclgevf_dev {
u32 flag; u32 flag;
unsigned long serv_processed_cnt; unsigned long serv_processed_cnt;
unsigned long last_serv_processed; unsigned long last_serv_processed;
struct devlink *devlink;
}; };
static inline bool hclgevf_is_reset_pending(struct hclgevf_dev *hdev) static inline bool hclgevf_is_reset_pending(struct hclgevf_dev *hdev)
......
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