Commit 045203e9 authored by David S. Miller's avatar David S. Miller

Merge branch 'nfp-enhanced-debug-dump-via-ethtool'

Simon Horman says:

====================
nfp: enhanced debug dump via ethtool

Add debug dump implementation to the NFP driver. This makes use of
existing ethtool infrastructure.  ethtool -W is used to select the dump
level and ethtool -w is used to dump NFP state.

The existing behaviour of dump level 0, dumping the arm.diag resource, is
preserved. Dump levels greater than 0 are implemented by this patchset and
optionally supported by firmware providing a _abi_dump_spec rtsym. This
rtsym provides a specification, in TLV format, of the information to be
dumped from the NFP at each supported dump level.

Dumps are also structured using a TLVs. They consist a prolog and the data
described int he corresponding dump.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents efbf7897 60b84a9b
...@@ -22,6 +22,7 @@ nfp-objs := \ ...@@ -22,6 +22,7 @@ nfp-objs := \
nfp_hwmon.o \ nfp_hwmon.o \
nfp_main.o \ nfp_main.o \
nfp_net_common.o \ nfp_net_common.o \
nfp_net_debugdump.o \
nfp_net_ethtool.o \ nfp_net_ethtool.o \
nfp_net_main.o \ nfp_net_main.o \
nfp_net_repr.o \ nfp_net_repr.o \
......
...@@ -262,6 +262,7 @@ enum lcsr_wr_src { ...@@ -262,6 +262,7 @@ enum lcsr_wr_src {
#define OP_CARB_BASE 0x0e000000000ULL #define OP_CARB_BASE 0x0e000000000ULL
#define OP_CARB_OR 0x00000010000ULL #define OP_CARB_OR 0x00000010000ULL
#define NFP_CSR_CTX_PTR 0x20
#define NFP_CSR_ACT_LM_ADDR0 0x64 #define NFP_CSR_ACT_LM_ADDR0 0x64
#define NFP_CSR_ACT_LM_ADDR1 0x6c #define NFP_CSR_ACT_LM_ADDR1 0x6c
#define NFP_CSR_ACT_LM_ADDR2 0x94 #define NFP_CSR_ACT_LM_ADDR2 0x94
...@@ -382,4 +383,13 @@ int swreg_to_restricted(swreg dst, swreg lreg, swreg rreg, ...@@ -382,4 +383,13 @@ int swreg_to_restricted(swreg dst, swreg lreg, swreg rreg,
int nfp_ustore_check_valid_no_ecc(u64 insn); int nfp_ustore_check_valid_no_ecc(u64 insn);
u64 nfp_ustore_calc_ecc_insn(u64 insn); u64 nfp_ustore_calc_ecc_insn(u64 insn);
#define NFP_IND_ME_REFL_WR_SIG_INIT 3
#define NFP_IND_ME_CTX_PTR_BASE_MASK GENMASK(9, 0)
#define NFP_IND_NUM_CONTEXTS 8
static inline u32 nfp_get_ind_csr_ctx_ptr_offs(u32 read_offset)
{
return (read_offset & ~NFP_IND_ME_CTX_PTR_BASE_MASK) | NFP_CSR_CTX_PTR;
}
#endif #endif
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/vermagic.h> #include <linux/vermagic.h>
#include <linux/vmalloc.h>
#include <net/devlink.h> #include <net/devlink.h>
#include "nfpcore/nfp.h" #include "nfpcore/nfp.h"
...@@ -509,6 +510,9 @@ static int nfp_pci_probe(struct pci_dev *pdev, ...@@ -509,6 +510,9 @@ static int nfp_pci_probe(struct pci_dev *pdev,
pf->mip = nfp_mip_open(pf->cpp); pf->mip = nfp_mip_open(pf->cpp);
pf->rtbl = __nfp_rtsym_table_read(pf->cpp, pf->mip); pf->rtbl = __nfp_rtsym_table_read(pf->cpp, pf->mip);
pf->dump_flag = NFP_DUMP_NSP_DIAG;
pf->dumpspec = nfp_net_dump_load_dumpspec(pf->cpp, pf->rtbl);
err = nfp_pcie_sriov_read_nfd_limit(pf); err = nfp_pcie_sriov_read_nfd_limit(pf);
if (err) if (err)
goto err_fw_unload; goto err_fw_unload;
...@@ -544,6 +548,7 @@ static int nfp_pci_probe(struct pci_dev *pdev, ...@@ -544,6 +548,7 @@ static int nfp_pci_probe(struct pci_dev *pdev,
nfp_fw_unload(pf); nfp_fw_unload(pf);
kfree(pf->eth_tbl); kfree(pf->eth_tbl);
kfree(pf->nspi); kfree(pf->nspi);
vfree(pf->dumpspec);
err_devlink_unreg: err_devlink_unreg:
devlink_unregister(devlink); devlink_unregister(devlink);
err_hwinfo_free: err_hwinfo_free:
...@@ -579,6 +584,7 @@ static void nfp_pci_remove(struct pci_dev *pdev) ...@@ -579,6 +584,7 @@ static void nfp_pci_remove(struct pci_dev *pdev)
devlink_unregister(devlink); devlink_unregister(devlink);
vfree(pf->dumpspec);
kfree(pf->rtbl); kfree(pf->rtbl);
nfp_mip_close(pf->mip); nfp_mip_close(pf->mip);
if (pf->fw_loaded) if (pf->fw_loaded)
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#ifndef NFP_MAIN_H #ifndef NFP_MAIN_H
#define NFP_MAIN_H #define NFP_MAIN_H
#include <linux/ethtool.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/msi.h> #include <linux/msi.h>
...@@ -61,6 +62,17 @@ struct nfp_nsp_identify; ...@@ -61,6 +62,17 @@ struct nfp_nsp_identify;
struct nfp_port; struct nfp_port;
struct nfp_rtsym_table; struct nfp_rtsym_table;
/**
* struct nfp_dumpspec - NFP FW dump specification structure
* @size: Size of the data
* @data: Sequence of TLVs, each being an instruction to dump some data
* from FW
*/
struct nfp_dumpspec {
u32 size;
u8 data[0];
};
/** /**
* struct nfp_pf - NFP PF-specific device structure * struct nfp_pf - NFP PF-specific device structure
* @pdev: Backpointer to PCI device * @pdev: Backpointer to PCI device
...@@ -83,6 +95,9 @@ struct nfp_rtsym_table; ...@@ -83,6 +95,9 @@ struct nfp_rtsym_table;
* @mip: MIP handle * @mip: MIP handle
* @rtbl: RTsym table * @rtbl: RTsym table
* @hwinfo: HWInfo table * @hwinfo: HWInfo table
* @dumpspec: Debug dump specification
* @dump_flag: Store dump flag between set_dump and get_dump_flag
* @dump_len: Store dump length between set_dump and get_dump_flag
* @eth_tbl: NSP ETH table * @eth_tbl: NSP ETH table
* @nspi: NSP identification info * @nspi: NSP identification info
* @hwmon_dev: pointer to hwmon device * @hwmon_dev: pointer to hwmon device
...@@ -124,6 +139,9 @@ struct nfp_pf { ...@@ -124,6 +139,9 @@ struct nfp_pf {
const struct nfp_mip *mip; const struct nfp_mip *mip;
struct nfp_rtsym_table *rtbl; struct nfp_rtsym_table *rtbl;
struct nfp_hwinfo *hwinfo; struct nfp_hwinfo *hwinfo;
struct nfp_dumpspec *dumpspec;
u32 dump_flag;
u32 dump_len;
struct nfp_eth_table *eth_tbl; struct nfp_eth_table *eth_tbl;
struct nfp_nsp_identify *nspi; struct nfp_nsp_identify *nspi;
...@@ -157,4 +175,15 @@ void nfp_net_get_mac_addr(struct nfp_pf *pf, struct nfp_port *port); ...@@ -157,4 +175,15 @@ void nfp_net_get_mac_addr(struct nfp_pf *pf, struct nfp_port *port);
bool nfp_ctrl_tx(struct nfp_net *nn, struct sk_buff *skb); bool nfp_ctrl_tx(struct nfp_net *nn, struct sk_buff *skb);
enum nfp_dump_diag {
NFP_DUMP_NSP_DIAG = 0,
};
struct nfp_dumpspec *
nfp_net_dump_load_dumpspec(struct nfp_cpp *cpp, struct nfp_rtsym_table *rtbl);
s64 nfp_net_dump_calculate_size(struct nfp_pf *pf, struct nfp_dumpspec *spec,
u32 flag);
int nfp_net_dump_populate_buffer(struct nfp_pf *pf, struct nfp_dumpspec *spec,
struct ethtool_dump *dump_param, void *dest);
#endif /* NFP_MAIN_H */ #endif /* NFP_MAIN_H */
This diff is collapsed.
...@@ -51,14 +51,11 @@ ...@@ -51,14 +51,11 @@
#include "nfpcore/nfp.h" #include "nfpcore/nfp.h"
#include "nfpcore/nfp_nsp.h" #include "nfpcore/nfp_nsp.h"
#include "nfp_app.h" #include "nfp_app.h"
#include "nfp_main.h"
#include "nfp_net_ctrl.h" #include "nfp_net_ctrl.h"
#include "nfp_net.h" #include "nfp_net.h"
#include "nfp_port.h" #include "nfp_port.h"
enum nfp_dump_diag {
NFP_DUMP_NSP_DIAG = 0,
};
struct nfp_et_stat { struct nfp_et_stat {
char name[ETH_GSTRING_LEN]; char name[ETH_GSTRING_LEN];
int off; int off;
...@@ -1066,15 +1063,34 @@ nfp_dump_nsp_diag(struct nfp_app *app, struct ethtool_dump *dump, void *buffer) ...@@ -1066,15 +1063,34 @@ nfp_dump_nsp_diag(struct nfp_app *app, struct ethtool_dump *dump, void *buffer)
return ret; return ret;
} }
/* Set the dump flag/level. Calculate the dump length for flag > 0 only (new TLV
* based dumps), since flag 0 (default) calculates the length in
* nfp_app_get_dump_flag(), and we need to support triggering a level 0 dump
* without setting the flag first, for backward compatibility.
*/
static int nfp_app_set_dump(struct net_device *netdev, struct ethtool_dump *val) static int nfp_app_set_dump(struct net_device *netdev, struct ethtool_dump *val)
{ {
struct nfp_app *app = nfp_app_from_netdev(netdev); struct nfp_app *app = nfp_app_from_netdev(netdev);
s64 len;
if (!app) if (!app)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (val->flag != NFP_DUMP_NSP_DIAG) if (val->flag == NFP_DUMP_NSP_DIAG) {
return -EINVAL; app->pf->dump_flag = val->flag;
return 0;
}
if (!app->pf->dumpspec)
return -EOPNOTSUPP;
len = nfp_net_dump_calculate_size(app->pf, app->pf->dumpspec,
val->flag);
if (len < 0)
return len;
app->pf->dump_flag = val->flag;
app->pf->dump_len = len;
return 0; return 0;
} }
...@@ -1082,14 +1098,37 @@ static int nfp_app_set_dump(struct net_device *netdev, struct ethtool_dump *val) ...@@ -1082,14 +1098,37 @@ static int nfp_app_set_dump(struct net_device *netdev, struct ethtool_dump *val)
static int static int
nfp_app_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) nfp_app_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
{ {
return nfp_dump_nsp_diag(nfp_app_from_netdev(netdev), dump, NULL); struct nfp_app *app = nfp_app_from_netdev(netdev);
if (!app)
return -EOPNOTSUPP;
if (app->pf->dump_flag == NFP_DUMP_NSP_DIAG)
return nfp_dump_nsp_diag(app, dump, NULL);
dump->flag = app->pf->dump_flag;
dump->len = app->pf->dump_len;
return 0;
} }
static int static int
nfp_app_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, nfp_app_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
void *buffer) void *buffer)
{ {
return nfp_dump_nsp_diag(nfp_app_from_netdev(netdev), dump, buffer); struct nfp_app *app = nfp_app_from_netdev(netdev);
if (!app)
return -EOPNOTSUPP;
if (app->pf->dump_flag == NFP_DUMP_NSP_DIAG)
return nfp_dump_nsp_diag(app, dump, buffer);
dump->flag = app->pf->dump_flag;
dump->len = app->pf->dump_len;
return nfp_net_dump_populate_buffer(app->pf, app->pf->dumpspec, dump,
buffer);
} }
static int nfp_net_set_coalesce(struct net_device *netdev, static int nfp_net_set_coalesce(struct net_device *netdev,
......
...@@ -49,6 +49,8 @@ ...@@ -49,6 +49,8 @@
struct nfp_hwinfo; struct nfp_hwinfo;
struct nfp_hwinfo *nfp_hwinfo_read(struct nfp_cpp *cpp); struct nfp_hwinfo *nfp_hwinfo_read(struct nfp_cpp *cpp);
const char *nfp_hwinfo_lookup(struct nfp_hwinfo *hwinfo, const char *lookup); const char *nfp_hwinfo_lookup(struct nfp_hwinfo *hwinfo, const char *lookup);
char *nfp_hwinfo_get_packed_strings(struct nfp_hwinfo *hwinfo);
u32 nfp_hwinfo_get_packed_str_size(struct nfp_hwinfo *hwinfo);
/* Implemented in nfp_nsp.c, low level functions */ /* Implemented in nfp_nsp.c, low level functions */
......
...@@ -302,3 +302,13 @@ const char *nfp_hwinfo_lookup(struct nfp_hwinfo *hwinfo, const char *lookup) ...@@ -302,3 +302,13 @@ const char *nfp_hwinfo_lookup(struct nfp_hwinfo *hwinfo, const char *lookup)
return NULL; return NULL;
} }
char *nfp_hwinfo_get_packed_strings(struct nfp_hwinfo *hwinfo)
{
return hwinfo->data;
}
u32 nfp_hwinfo_get_packed_str_size(struct nfp_hwinfo *hwinfo)
{
return le32_to_cpu(hwinfo->size) - sizeof(u32);
}
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