sfxge: support for MCDI logging implemented

Submitted by:   Artem V. Andreev <Artem.Andreev at oktetlabs.ru>
Sponsored by:   Solarflare Communications, Inc.
MFC after:      2 days
Differential Revision: https://reviews.freebsd.org/D4355
This commit is contained in:
arybchik 2015-12-05 07:04:11 +00:00
parent d5903f4e62
commit 0b3051dae1
4 changed files with 97 additions and 0 deletions

View File

@ -148,6 +148,14 @@ Number of packets with payload that must arrive in-order following loss
before a connection is eligible for LRO.
The idea is we should avoid coalescing segments when the sender is recovering
from loss, because reducing the ACK rate can damage performance.
.It Va hw.sfxge.mcdi_logging
Enable logging of MCDI protocol messages (only available if enabled at compile-time).
.It Va hw.sfxge.N.mcdi_logging
Enable or disable logging of MCDI protocol messages on a per-port basis. The default for each
port will be the value of
.Va hw.sfxge.mcdi_logging.
The logging may also be enabled or disabled after the driver is loaded using the sysctl
.Va dev.sfxge.%d.mcdi_logging.
.El
.Sh SUPPORT
For general information and support,

View File

@ -95,6 +95,12 @@ SYSCTL_INT(_hw_sfxge, OID_AUTO, tx_ring, CTLFLAG_RDTUN,
&sfxge_tx_ring_entries, 0,
"Maximum number of descriptors in a transmit ring");
#if EFSYS_OPT_MCDI_LOGGING
#define SFXGE_PARAM_MCDI_LOGGING SFXGE_PARAM(mcdi_logging)
static int sfxge_mcdi_logging = 0;
TUNABLE_INT(SFXGE_PARAM_MCDI_LOGGING, &sfxge_mcdi_logging);
#endif
static void
sfxge_reset(void *arg, int npending);
@ -620,6 +626,9 @@ sfxge_create(struct sfxge_softc *sc)
efx_nic_t *enp;
int error;
char rss_param_name[sizeof(SFXGE_PARAM(%d.max_rss_channels))];
#if EFSYS_OPT_MCDI_LOGGING
char mcdi_log_param_name[sizeof(SFXGE_PARAM(%d.mcdi_logging))];
#endif
dev = sc->dev;
@ -630,6 +639,13 @@ sfxge_create(struct sfxge_softc *sc)
SFXGE_PARAM(%d.max_rss_channels),
(int)device_get_unit(dev));
TUNABLE_INT_FETCH(rss_param_name, &sc->max_rss_channels);
#if EFSYS_OPT_MCDI_LOGGING
sc->mcdi_logging = sfxge_mcdi_logging;
snprintf(mcdi_log_param_name, sizeof(mcdi_log_param_name),
SFXGE_PARAM(%d.mcdi_logging),
(int)device_get_unit(dev));
TUNABLE_INT_FETCH(mcdi_log_param_name, &sc->mcdi_logging);
#endif
sc->stats_node = SYSCTL_ADD_NODE(
device_get_sysctl_ctx(dev),

View File

@ -281,6 +281,9 @@ struct sfxge_softc {
unsigned int txq_count;
int tso_fw_assisted;
#if EFSYS_OPT_MCDI_LOGGING
int mcdi_logging;
#endif
};
#define SFXGE_LINK_UP(sc) ((sc)->port.link_mode != EFX_LINK_DOWN)

View File

@ -49,6 +49,10 @@ __FBSDID("$FreeBSD$");
#include "sfxge.h"
#if EFSYS_OPT_MCDI_LOGGING
#include <dev/pci/pcivar.h>
#endif
#define SFXGE_MCDI_POLL_INTERVAL_MIN 10 /* 10us in 1us units */
#define SFXGE_MCDI_POLL_INTERVAL_MAX 100000 /* 100ms in 1us units */
#define SFXGE_MCDI_WATCHDOG_INTERVAL 10000000 /* 10s in 1us units */
@ -163,6 +167,64 @@ sfxge_mcdi_exception(void *arg, efx_mcdi_exception_t eme)
sfxge_schedule_reset(sc);
}
#if EFSYS_OPT_MCDI_LOGGING
#define SFXGE_MCDI_LOG_BUF_SIZE 128
static size_t
sfxge_mcdi_do_log(char *buffer, void *data, size_t data_size,
size_t pfxsize, size_t position)
{
uint32_t *words = data;
size_t i;
for (i = 0; i < data_size; i += sizeof(*words)) {
if (position + 2 * sizeof(*words) + 1 >= SFXGE_MCDI_LOG_BUF_SIZE) {
buffer[position] = '\0';
printf("%s \\\n", buffer);
position = pfxsize;
}
snprintf(buffer + position, SFXGE_MCDI_LOG_BUF_SIZE - position,
" %08x", *words);
words++;
position += 2 * sizeof(uint32_t) + 1;
}
return (position);
}
static void
sfxge_mcdi_logger(void *arg, efx_log_msg_t type,
void *header, size_t header_size,
void *data, size_t data_size)
{
struct sfxge_softc *sc = (struct sfxge_softc *)arg;
char buffer[SFXGE_MCDI_LOG_BUF_SIZE];
size_t pfxsize;
size_t start;
if (!sc->mcdi_logging)
return;
pfxsize = snprintf(buffer, sizeof(buffer),
"sfc %04x:%02x:%02x.%02x %s MCDI RPC %s:",
pci_get_domain(sc->dev),
pci_get_bus(sc->dev),
pci_get_slot(sc->dev),
pci_get_function(sc->dev),
device_get_nameunit(sc->dev),
type == EFX_LOG_MCDI_REQUEST ? "REQ" :
type == EFX_LOG_MCDI_RESPONSE ? "RESP" : "???");
start = sfxge_mcdi_do_log(buffer, header, header_size,
pfxsize, pfxsize);
start = sfxge_mcdi_do_log(buffer, data, data_size, pfxsize, start);
if (start != pfxsize) {
buffer[start] = '\0';
printf("%s\n", buffer);
}
}
#endif
int
sfxge_mcdi_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ip)
{
@ -269,6 +331,14 @@ sfxge_mcdi_init(struct sfxge_softc *sc)
emtp->emt_execute = sfxge_mcdi_execute;
emtp->emt_ev_cpl = sfxge_mcdi_ev_cpl;
emtp->emt_exception = sfxge_mcdi_exception;
#if EFSYS_OPT_MCDI_LOGGING
emtp->emt_logger = sfxge_mcdi_logger;
SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)),
OID_AUTO, "mcdi_logging", CTLFLAG_RW,
&sc->mcdi_logging, 0,
"MCDI logging");
#endif
if ((rc = efx_mcdi_init(enp, emtp)) != 0)
goto fail;