Commit 750c721e authored by David S. Miller's avatar David S. Miller

Merge branch 'devlink-Add-support-for-region-access'

Alex Vesker says:

====================
devlink: Add support for region access

This is a proposal which will allow access to driver defined address
regions using devlink. Each device can create its supported address
regions and register them. A device which exposes a region will allow
access to it using devlink.

The suggested implementation will allow exposing regions to the user,
reading and dumping snapshots taken from different regions.
A snapshot represents a memory image of a region taken by the driver.

If a device collects a snapshot of an address region it can be later
exposed using devlink region read or dump commands.
This functionality allows for future analyses on the snapshots to be
done.

The major benefit of this support is not only to provide access to
internal address regions which were inaccessible to the user but also
to provide an additional way to debug complex error states using the
region snapshots.

Implemented commands:
$ devlink region help
$ devlink region show [ DEV/REGION ]
$ devlink region del DEV/REGION snapshot SNAPSHOT_ID
$ devlink region dump DEV/REGION [ snapshot SNAPSHOT_ID ]
$ devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ]
	address ADDRESS length length

Show all of the exposed regions with region sizes:
$ devlink region show
pci/0000:00:05.0/cr-space: size 1048576 snapshot [1 2]
pci/0000:00:05.0/fw-health: size 64 snapshot [1 2]

Delete a snapshot using:
$ devlink region del pci/0000:00:05.0/cr-space snapshot 1

Dump a snapshot:
$ devlink region dump pci/0000:00:05.0/fw-health snapshot 1
0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
0000000000000010 0000 0000 ffff ff04 0029 8c00 0028 8cc8
0000000000000020 0016 0bb8 0016 1720 0000 0000 c00f 3ffc
0000000000000030 bada cce5 bada cce5 bada cce5 bada cce5

Read a specific part of a snapshot:
$ devlink region read pci/0000:00:05.0/fw-health snapshot 1 address 0
	length 16
0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30

For more information you can check devlink-region.8 man page

Future:
There is a plan to extend the support to include a write command
as well as performing read and dump live region

v1->v2:
-Add a parameter to enable devlink region snapshot
-Allocate snapshot memory using kvmalloc
-Introduce destructor function devlink_snapshot_data_dest_t to avoid
 double allocation

v2->v3:
-Fix incorrect comment in devlink.h for DEVLINK_ATTR_REGION_SIZE
 from u32 to u64
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 23c9ef2b 3c641ba4
...@@ -3,7 +3,7 @@ obj-$(CONFIG_MLX4_CORE) += mlx4_core.o ...@@ -3,7 +3,7 @@ obj-$(CONFIG_MLX4_CORE) += mlx4_core.o
mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o fw_qos.o icm.o intf.o \ mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o fw_qos.o icm.o intf.o \
main.o mcg.o mr.o pd.o port.o profile.o qp.o reset.o sense.o \ main.o mcg.o mr.o pd.o port.o profile.o qp.o reset.o sense.o \
srq.o resource_tracker.o srq.o resource_tracker.o crdump.o
obj-$(CONFIG_MLX4_EN) += mlx4_en.o obj-$(CONFIG_MLX4_EN) += mlx4_en.o
......
...@@ -178,10 +178,12 @@ void mlx4_enter_error_state(struct mlx4_dev_persistent *persist) ...@@ -178,10 +178,12 @@ void mlx4_enter_error_state(struct mlx4_dev_persistent *persist)
dev = persist->dev; dev = persist->dev;
mlx4_err(dev, "device is going to be reset\n"); mlx4_err(dev, "device is going to be reset\n");
if (mlx4_is_slave(dev)) if (mlx4_is_slave(dev)) {
err = mlx4_reset_slave(dev); err = mlx4_reset_slave(dev);
else } else {
mlx4_crdump_collect(dev);
err = mlx4_reset_master(dev); err = mlx4_reset_master(dev);
}
if (!err) { if (!err) {
mlx4_err(dev, "device was reset successfully\n"); mlx4_err(dev, "device was reset successfully\n");
......
/*
* Copyright (c) 2018, Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "mlx4.h"
#define BAD_ACCESS 0xBADACCE5
#define HEALTH_BUFFER_SIZE 0x40
#define CR_ENABLE_BIT swab32(BIT(6))
#define CR_ENABLE_BIT_OFFSET 0xF3F04
#define MAX_NUM_OF_DUMPS_TO_STORE (8)
static const char *region_cr_space_str = "cr-space";
static const char *region_fw_health_str = "fw-health";
/* Set to true in case cr enable bit was set to true before crdump */
static bool crdump_enbale_bit_set;
static void crdump_enable_crspace_access(struct mlx4_dev *dev,
u8 __iomem *cr_space)
{
/* Get current enable bit value */
crdump_enbale_bit_set =
readl(cr_space + CR_ENABLE_BIT_OFFSET) & CR_ENABLE_BIT;
/* Enable FW CR filter (set bit6 to 0) */
if (crdump_enbale_bit_set)
writel(readl(cr_space + CR_ENABLE_BIT_OFFSET) & ~CR_ENABLE_BIT,
cr_space + CR_ENABLE_BIT_OFFSET);
/* Enable block volatile crspace accesses */
writel(swab32(1), cr_space + dev->caps.health_buffer_addrs +
HEALTH_BUFFER_SIZE);
}
static void crdump_disable_crspace_access(struct mlx4_dev *dev,
u8 __iomem *cr_space)
{
/* Disable block volatile crspace accesses */
writel(0, cr_space + dev->caps.health_buffer_addrs +
HEALTH_BUFFER_SIZE);
/* Restore FW CR filter value (set bit6 to original value) */
if (crdump_enbale_bit_set)
writel(readl(cr_space + CR_ENABLE_BIT_OFFSET) | CR_ENABLE_BIT,
cr_space + CR_ENABLE_BIT_OFFSET);
}
static void mlx4_crdump_collect_crspace(struct mlx4_dev *dev,
u8 __iomem *cr_space,
u32 id)
{
struct mlx4_fw_crdump *crdump = &dev->persist->crdump;
struct pci_dev *pdev = dev->persist->pdev;
unsigned long cr_res_size;
u8 *crspace_data;
int offset;
int err;
if (!crdump->region_crspace) {
mlx4_err(dev, "crdump: cr-space region is NULL\n");
return;
}
/* Try to collect CR space */
cr_res_size = pci_resource_len(pdev, 0);
crspace_data = kvmalloc(cr_res_size, GFP_KERNEL);
if (crspace_data) {
for (offset = 0; offset < cr_res_size; offset += 4)
*(u32 *)(crspace_data + offset) =
readl(cr_space + offset);
err = devlink_region_snapshot_create(crdump->region_crspace,
cr_res_size, crspace_data,
id, &kvfree);
if (err) {
kvfree(crspace_data);
mlx4_warn(dev, "crdump: devlink create %s snapshot id %d err %d\n",
region_cr_space_str, id, err);
} else {
mlx4_info(dev, "crdump: added snapshot %d to devlink region %s\n",
id, region_cr_space_str);
}
} else {
mlx4_err(dev, "crdump: Failed to allocate crspace buffer\n");
}
}
static void mlx4_crdump_collect_fw_health(struct mlx4_dev *dev,
u8 __iomem *cr_space,
u32 id)
{
struct mlx4_fw_crdump *crdump = &dev->persist->crdump;
u8 *health_data;
int offset;
int err;
if (!crdump->region_fw_health) {
mlx4_err(dev, "crdump: fw-health region is NULL\n");
return;
}
/* Try to collect health buffer */
health_data = kvmalloc(HEALTH_BUFFER_SIZE, GFP_KERNEL);
if (health_data) {
u8 __iomem *health_buf_start =
cr_space + dev->caps.health_buffer_addrs;
for (offset = 0; offset < HEALTH_BUFFER_SIZE; offset += 4)
*(u32 *)(health_data + offset) =
readl(health_buf_start + offset);
err = devlink_region_snapshot_create(crdump->region_fw_health,
HEALTH_BUFFER_SIZE,
health_data,
id, &kvfree);
if (err) {
kvfree(health_data);
mlx4_warn(dev, "crdump: devlink create %s snapshot id %d err %d\n",
region_fw_health_str, id, err);
} else {
mlx4_info(dev, "crdump: added snapshot %d to devlink region %s\n",
id, region_fw_health_str);
}
} else {
mlx4_err(dev, "crdump: Failed to allocate health buffer\n");
}
}
int mlx4_crdump_collect(struct mlx4_dev *dev)
{
struct devlink *devlink = priv_to_devlink(mlx4_priv(dev));
struct mlx4_fw_crdump *crdump = &dev->persist->crdump;
struct pci_dev *pdev = dev->persist->pdev;
unsigned long cr_res_size;
u8 __iomem *cr_space;
u32 id;
if (!dev->caps.health_buffer_addrs) {
mlx4_info(dev, "crdump: FW doesn't support health buffer access, skipping\n");
return 0;
}
if (!crdump->snapshot_enable) {
mlx4_info(dev, "crdump: devlink snapshot disabled, skipping\n");
return 0;
}
cr_res_size = pci_resource_len(pdev, 0);
cr_space = ioremap(pci_resource_start(pdev, 0), cr_res_size);
if (!cr_space) {
mlx4_err(dev, "crdump: Failed to map pci cr region\n");
return -ENODEV;
}
crdump_enable_crspace_access(dev, cr_space);
/* Get the available snapshot ID for the dumps */
id = devlink_region_shapshot_id_get(devlink);
/* Try to capture dumps */
mlx4_crdump_collect_crspace(dev, cr_space, id);
mlx4_crdump_collect_fw_health(dev, cr_space, id);
crdump_disable_crspace_access(dev, cr_space);
iounmap(cr_space);
return 0;
}
int mlx4_crdump_init(struct mlx4_dev *dev)
{
struct devlink *devlink = priv_to_devlink(mlx4_priv(dev));
struct mlx4_fw_crdump *crdump = &dev->persist->crdump;
struct pci_dev *pdev = dev->persist->pdev;
crdump->snapshot_enable = false;
/* Create cr-space region */
crdump->region_crspace =
devlink_region_create(devlink,
region_cr_space_str,
MAX_NUM_OF_DUMPS_TO_STORE,
pci_resource_len(pdev, 0));
if (IS_ERR(crdump->region_crspace))
mlx4_warn(dev, "crdump: create devlink region %s err %ld\n",
region_cr_space_str,
PTR_ERR(crdump->region_crspace));
/* Create fw-health region */
crdump->region_fw_health =
devlink_region_create(devlink,
region_fw_health_str,
MAX_NUM_OF_DUMPS_TO_STORE,
HEALTH_BUFFER_SIZE);
if (IS_ERR(crdump->region_fw_health))
mlx4_warn(dev, "crdump: create devlink region %s err %ld\n",
region_fw_health_str,
PTR_ERR(crdump->region_fw_health));
return 0;
}
void mlx4_crdump_end(struct mlx4_dev *dev)
{
struct mlx4_fw_crdump *crdump = &dev->persist->crdump;
devlink_region_destroy(crdump->region_fw_health);
devlink_region_destroy(crdump->region_crspace);
}
...@@ -825,7 +825,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -825,7 +825,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET 0xcc #define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET 0xcc
#define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET 0xd0 #define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET 0xd0
#define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET 0xd2 #define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET 0xd2
#define QUERY_DEV_CAP_HEALTH_BUFFER_ADDRESS_OFFSET 0xe4
dev_cap->flags2 = 0; dev_cap->flags2 = 0;
mailbox = mlx4_alloc_cmd_mailbox(dev); mailbox = mlx4_alloc_cmd_mailbox(dev);
...@@ -1082,6 +1082,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -1082,6 +1082,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->rl_caps.min_unit = size >> 14; dev_cap->rl_caps.min_unit = size >> 14;
} }
MLX4_GET(dev_cap->health_buffer_addrs, outbox,
QUERY_DEV_CAP_HEALTH_BUFFER_ADDRESS_OFFSET);
MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
if (field32 & (1 << 16)) if (field32 & (1 << 16))
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
......
...@@ -128,6 +128,7 @@ struct mlx4_dev_cap { ...@@ -128,6 +128,7 @@ struct mlx4_dev_cap {
u32 dmfs_high_rate_qpn_base; u32 dmfs_high_rate_qpn_base;
u32 dmfs_high_rate_qpn_range; u32 dmfs_high_rate_qpn_range;
struct mlx4_rate_limit_caps rl_caps; struct mlx4_rate_limit_caps rl_caps;
u32 health_buffer_addrs;
struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1]; struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1];
bool wol_port[MLX4_MAX_PORTS + 1]; bool wol_port[MLX4_MAX_PORTS + 1];
}; };
......
...@@ -191,6 +191,26 @@ static int mlx4_devlink_ierr_reset_set(struct devlink *devlink, u32 id, ...@@ -191,6 +191,26 @@ static int mlx4_devlink_ierr_reset_set(struct devlink *devlink, u32 id,
return 0; return 0;
} }
static int mlx4_devlink_crdump_snapshot_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct mlx4_priv *priv = devlink_priv(devlink);
struct mlx4_dev *dev = &priv->dev;
ctx->val.vbool = dev->persist->crdump.snapshot_enable;
return 0;
}
static int mlx4_devlink_crdump_snapshot_set(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct mlx4_priv *priv = devlink_priv(devlink);
struct mlx4_dev *dev = &priv->dev;
dev->persist->crdump.snapshot_enable = ctx->val.vbool;
return 0;
}
static int static int
mlx4_devlink_max_macs_validate(struct devlink *devlink, u32 id, mlx4_devlink_max_macs_validate(struct devlink *devlink, u32 id,
union devlink_param_value val, union devlink_param_value val,
...@@ -224,6 +244,11 @@ static const struct devlink_param mlx4_devlink_params[] = { ...@@ -224,6 +244,11 @@ static const struct devlink_param mlx4_devlink_params[] = {
DEVLINK_PARAM_GENERIC(MAX_MACS, DEVLINK_PARAM_GENERIC(MAX_MACS,
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
NULL, NULL, mlx4_devlink_max_macs_validate), NULL, NULL, mlx4_devlink_max_macs_validate),
DEVLINK_PARAM_GENERIC(REGION_SNAPSHOT,
BIT(DEVLINK_PARAM_CMODE_RUNTIME) |
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
mlx4_devlink_crdump_snapshot_get,
mlx4_devlink_crdump_snapshot_set, NULL),
DEVLINK_PARAM_DRIVER(MLX4_DEVLINK_PARAM_ID_ENABLE_64B_CQE_EQE, DEVLINK_PARAM_DRIVER(MLX4_DEVLINK_PARAM_ID_ENABLE_64B_CQE_EQE,
"enable_64b_cqe_eqe", DEVLINK_PARAM_TYPE_BOOL, "enable_64b_cqe_eqe", DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
...@@ -270,6 +295,11 @@ static void mlx4_devlink_set_params_init_values(struct devlink *devlink) ...@@ -270,6 +295,11 @@ static void mlx4_devlink_set_params_init_values(struct devlink *devlink)
mlx4_devlink_set_init_value(devlink, mlx4_devlink_set_init_value(devlink,
MLX4_DEVLINK_PARAM_ID_ENABLE_4K_UAR, MLX4_DEVLINK_PARAM_ID_ENABLE_4K_UAR,
value); value);
value.vbool = false;
mlx4_devlink_set_init_value(devlink,
DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
value);
} }
static inline void mlx4_set_num_reserved_uars(struct mlx4_dev *dev, static inline void mlx4_set_num_reserved_uars(struct mlx4_dev *dev,
...@@ -523,6 +553,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) ...@@ -523,6 +553,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz; dev->caps.max_rss_tbl_sz = dev_cap->max_rss_tbl_sz;
dev->caps.wol_port[1] = dev_cap->wol_port[1]; dev->caps.wol_port[1] = dev_cap->wol_port[1];
dev->caps.wol_port[2] = dev_cap->wol_port[2]; dev->caps.wol_port[2] = dev_cap->wol_port[2];
dev->caps.health_buffer_addrs = dev_cap->health_buffer_addrs;
/* Save uar page shift */ /* Save uar page shift */
if (!mlx4_is_slave(dev)) { if (!mlx4_is_slave(dev)) {
...@@ -3806,10 +3837,14 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data, ...@@ -3806,10 +3837,14 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data,
} }
} }
err = mlx4_catas_init(&priv->dev); err = mlx4_crdump_init(&priv->dev);
if (err) if (err)
goto err_release_regions; goto err_release_regions;
err = mlx4_catas_init(&priv->dev);
if (err)
goto err_crdump;
err = mlx4_load_one(pdev, pci_dev_data, total_vfs, nvfs, priv, 0); err = mlx4_load_one(pdev, pci_dev_data, total_vfs, nvfs, priv, 0);
if (err) if (err)
goto err_catas; goto err_catas;
...@@ -3819,6 +3854,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data, ...@@ -3819,6 +3854,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data,
err_catas: err_catas:
mlx4_catas_end(&priv->dev); mlx4_catas_end(&priv->dev);
err_crdump:
mlx4_crdump_end(&priv->dev);
err_release_regions: err_release_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
...@@ -3854,6 +3892,9 @@ static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port, ...@@ -3854,6 +3892,9 @@ static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port,
static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink) static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink)
{ {
struct mlx4_priv *priv = devlink_priv(devlink);
struct mlx4_dev *dev = &priv->dev;
struct mlx4_fw_crdump *crdump = &dev->persist->crdump;
union devlink_param_value saved_value; union devlink_param_value saved_value;
int err; int err;
...@@ -3881,6 +3922,14 @@ static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink) ...@@ -3881,6 +3922,14 @@ static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink)
&saved_value); &saved_value);
if (!err) if (!err)
enable_4k_uar = saved_value.vbool; enable_4k_uar = saved_value.vbool;
err = devlink_param_driverinit_value_get(devlink,
DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
&saved_value);
if (!err && crdump->snapshot_enable != saved_value.vbool) {
crdump->snapshot_enable = saved_value.vbool;
devlink_param_value_changed(devlink,
DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT);
}
} }
static int mlx4_devlink_reload(struct devlink *devlink, static int mlx4_devlink_reload(struct devlink *devlink,
...@@ -4080,6 +4129,7 @@ static void mlx4_remove_one(struct pci_dev *pdev) ...@@ -4080,6 +4129,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
else else
mlx4_info(dev, "%s: interface is down\n", __func__); mlx4_info(dev, "%s: interface is down\n", __func__);
mlx4_catas_end(dev); mlx4_catas_end(dev);
mlx4_crdump_end(dev);
if (dev->flags & MLX4_FLAG_SRIOV && !active_vfs) { if (dev->flags & MLX4_FLAG_SRIOV && !active_vfs) {
mlx4_warn(dev, "Disabling SR-IOV\n"); mlx4_warn(dev, "Disabling SR-IOV\n");
pci_disable_sriov(pdev); pci_disable_sriov(pdev);
......
...@@ -1042,6 +1042,8 @@ void mlx4_start_catas_poll(struct mlx4_dev *dev); ...@@ -1042,6 +1042,8 @@ void mlx4_start_catas_poll(struct mlx4_dev *dev);
void mlx4_stop_catas_poll(struct mlx4_dev *dev); void mlx4_stop_catas_poll(struct mlx4_dev *dev);
int mlx4_catas_init(struct mlx4_dev *dev); int mlx4_catas_init(struct mlx4_dev *dev);
void mlx4_catas_end(struct mlx4_dev *dev); void mlx4_catas_end(struct mlx4_dev *dev);
int mlx4_crdump_init(struct mlx4_dev *dev);
void mlx4_crdump_end(struct mlx4_dev *dev);
int mlx4_restart_one(struct pci_dev *pdev, bool reload, int mlx4_restart_one(struct pci_dev *pdev, bool reload,
struct devlink *devlink); struct devlink *devlink);
int mlx4_register_device(struct mlx4_dev *dev); int mlx4_register_device(struct mlx4_dev *dev);
...@@ -1228,6 +1230,8 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type); ...@@ -1228,6 +1230,8 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
void mlx4_enter_error_state(struct mlx4_dev_persistent *persist); void mlx4_enter_error_state(struct mlx4_dev_persistent *persist);
int mlx4_comm_internal_err(u32 slave_read); int mlx4_comm_internal_err(u32 slave_read);
int mlx4_crdump_collect(struct mlx4_dev *dev);
int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port, int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
enum mlx4_port_type *type); enum mlx4_port_type *type);
void mlx4_do_sense_ports(struct mlx4_dev *dev, void mlx4_do_sense_ports(struct mlx4_dev *dev,
......
...@@ -630,6 +630,7 @@ struct mlx4_caps { ...@@ -630,6 +630,7 @@ struct mlx4_caps {
u32 vf_caps; u32 vf_caps;
bool wol_port[MLX4_MAX_PORTS + 1]; bool wol_port[MLX4_MAX_PORTS + 1];
struct mlx4_rate_limit_caps rl_caps; struct mlx4_rate_limit_caps rl_caps;
u32 health_buffer_addrs;
}; };
struct mlx4_buf_list { struct mlx4_buf_list {
...@@ -851,6 +852,12 @@ struct mlx4_vf_dev { ...@@ -851,6 +852,12 @@ struct mlx4_vf_dev {
u8 n_ports; u8 n_ports;
}; };
struct mlx4_fw_crdump {
bool snapshot_enable;
struct devlink_region *region_crspace;
struct devlink_region *region_fw_health;
};
enum mlx4_pci_status { enum mlx4_pci_status {
MLX4_PCI_STATUS_DISABLED, MLX4_PCI_STATUS_DISABLED,
MLX4_PCI_STATUS_ENABLED, MLX4_PCI_STATUS_ENABLED,
...@@ -871,6 +878,7 @@ struct mlx4_dev_persistent { ...@@ -871,6 +878,7 @@ struct mlx4_dev_persistent {
u8 interface_state; u8 interface_state;
struct mutex pci_status_mutex; /* sync pci state */ struct mutex pci_status_mutex; /* sync pci state */
enum mlx4_pci_status pci_status; enum mlx4_pci_status pci_status;
struct mlx4_fw_crdump crdump;
}; };
struct mlx4_dev { struct mlx4_dev {
......
...@@ -28,6 +28,8 @@ struct devlink { ...@@ -28,6 +28,8 @@ struct devlink {
struct list_head dpipe_table_list; struct list_head dpipe_table_list;
struct list_head resource_list; struct list_head resource_list;
struct list_head param_list; struct list_head param_list;
struct list_head region_list;
u32 snapshot_id;
struct devlink_dpipe_headers *dpipe_headers; struct devlink_dpipe_headers *dpipe_headers;
const struct devlink_ops *ops; const struct devlink_ops *ops;
struct device *dev; struct device *dev;
...@@ -359,6 +361,7 @@ enum devlink_param_generic_id { ...@@ -359,6 +361,7 @@ enum devlink_param_generic_id {
DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET, DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
DEVLINK_PARAM_GENERIC_ID_MAX_MACS, DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
/* add new param generic ids above here*/ /* add new param generic ids above here*/
__DEVLINK_PARAM_GENERIC_ID_MAX, __DEVLINK_PARAM_GENERIC_ID_MAX,
...@@ -374,6 +377,9 @@ enum devlink_param_generic_id { ...@@ -374,6 +377,9 @@ enum devlink_param_generic_id {
#define DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME "enable_sriov" #define DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME "enable_sriov"
#define DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE DEVLINK_PARAM_TYPE_BOOL #define DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE DEVLINK_PARAM_TYPE_BOOL
#define DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME "region_snapshot_enable"
#define DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE DEVLINK_PARAM_TYPE_BOOL
#define DEVLINK_PARAM_GENERIC(_id, _cmodes, _get, _set, _validate) \ #define DEVLINK_PARAM_GENERIC(_id, _cmodes, _get, _set, _validate) \
{ \ { \
.id = DEVLINK_PARAM_GENERIC_ID_##_id, \ .id = DEVLINK_PARAM_GENERIC_ID_##_id, \
...@@ -397,6 +403,10 @@ enum devlink_param_generic_id { ...@@ -397,6 +403,10 @@ enum devlink_param_generic_id {
.validate = _validate, \ .validate = _validate, \
} }
struct devlink_region;
typedef void devlink_snapshot_data_dest_t(const void *data);
struct devlink_ops { struct devlink_ops {
int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack); int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack);
int (*port_type_set)(struct devlink_port *devlink_port, int (*port_type_set)(struct devlink_port *devlink_port,
...@@ -543,6 +553,15 @@ int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, ...@@ -543,6 +553,15 @@ int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
union devlink_param_value init_val); union devlink_param_value init_val);
void devlink_param_value_changed(struct devlink *devlink, u32 param_id); void devlink_param_value_changed(struct devlink *devlink, u32 param_id);
struct devlink_region *devlink_region_create(struct devlink *devlink,
const char *region_name,
u32 region_max_snapshots,
u64 region_size);
void devlink_region_destroy(struct devlink_region *region);
u32 devlink_region_shapshot_id_get(struct devlink *devlink);
int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
u8 *data, u32 snapshot_id,
devlink_snapshot_data_dest_t *data_destructor);
#else #else
...@@ -770,6 +789,34 @@ devlink_param_value_changed(struct devlink *devlink, u32 param_id) ...@@ -770,6 +789,34 @@ devlink_param_value_changed(struct devlink *devlink, u32 param_id)
{ {
} }
static inline struct devlink_region *
devlink_region_create(struct devlink *devlink,
const char *region_name,
u32 region_max_snapshots,
u64 region_size)
{
return NULL;
}
static inline void
devlink_region_destroy(struct devlink_region *region)
{
}
static inline u32
devlink_region_shapshot_id_get(struct devlink *devlink)
{
return 0;
}
static inline int
devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
u8 *data, u32 snapshot_id,
devlink_snapshot_data_dest_t *data_destructor)
{
return 0;
}
#endif #endif
#endif /* _NET_DEVLINK_H_ */ #endif /* _NET_DEVLINK_H_ */
...@@ -83,6 +83,12 @@ enum devlink_command { ...@@ -83,6 +83,12 @@ enum devlink_command {
DEVLINK_CMD_PARAM_NEW, DEVLINK_CMD_PARAM_NEW,
DEVLINK_CMD_PARAM_DEL, DEVLINK_CMD_PARAM_DEL,
DEVLINK_CMD_REGION_GET,
DEVLINK_CMD_REGION_SET,
DEVLINK_CMD_REGION_NEW,
DEVLINK_CMD_REGION_DEL,
DEVLINK_CMD_REGION_READ,
/* add new commands above here */ /* add new commands above here */
__DEVLINK_CMD_MAX, __DEVLINK_CMD_MAX,
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
...@@ -262,6 +268,18 @@ enum devlink_attr { ...@@ -262,6 +268,18 @@ enum devlink_attr {
DEVLINK_ATTR_PARAM_VALUE_DATA, /* dynamic */ DEVLINK_ATTR_PARAM_VALUE_DATA, /* dynamic */
DEVLINK_ATTR_PARAM_VALUE_CMODE, /* u8 */ DEVLINK_ATTR_PARAM_VALUE_CMODE, /* u8 */
DEVLINK_ATTR_REGION_NAME, /* string */
DEVLINK_ATTR_REGION_SIZE, /* u64 */
DEVLINK_ATTR_REGION_SNAPSHOTS, /* nested */
DEVLINK_ATTR_REGION_SNAPSHOT, /* nested */
DEVLINK_ATTR_REGION_SNAPSHOT_ID, /* u32 */
DEVLINK_ATTR_REGION_CHUNKS, /* nested */
DEVLINK_ATTR_REGION_CHUNK, /* nested */
DEVLINK_ATTR_REGION_CHUNK_DATA, /* binary */
DEVLINK_ATTR_REGION_CHUNK_ADDR, /* u64 */
DEVLINK_ATTR_REGION_CHUNK_LEN, /* u64 */
/* add new attributes above here, update the policy in devlink.c */ /* add new attributes above here, update the policy in devlink.c */
__DEVLINK_ATTR_MAX, __DEVLINK_ATTR_MAX,
......
This diff is collapsed.
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