Add the ability to report and set debug flags as text strings instead of

just integer flags.  Report both for convenience.

Submitted by:	Eygene Ryabinkin (manpage)
Sponsored by:	Netflix
This commit is contained in:
scottl 2017-09-24 13:14:50 +00:00
parent 15e40f27cc
commit 95d837129a
4 changed files with 292 additions and 60 deletions

View File

@ -337,31 +337,41 @@ dev.mpr.X.use_phy_num
The same set of values are valid as when setting this tunable for all adapters.
.Pp
.Sh DEBUGGING
To enable debugging prints from the
.Nm
driver, set the
.Bd -literal -offset indent
hw.mpr.X.debug_level
.Ed
.Pp
tunable, either in
Driver diagnostic printing is controlled in
.Xr loader.conf 5
or by using
.Xr sysctl 8 .
These bits have the described effects:
.Bd -literal -offset indent
0x0001 Enable informational prints (set by default).
0x0002 Enable prints for driver faults (set by default).
0x0004 Enable prints for controller events.
0x0008 Enable prints for controller logging.
0x0010 Enable prints for tracing recovery operations.
0x0020 Enable prints for parameter errors and programming bugs.
0x0040 Enable prints for system initialization operations.
0x0080 Enable prints for more detailed information.
0x0100 Enable prints for user-generated commands (IOCTL).
0x0200 Enable prints for device mapping.
0x0400 Enable prints for tracing through driver functions.
.Ed
by using the global
.Va hw.mpr.debug_level
and per-device
.Va dev.mpr.X.debug_level
tunables.
One can alter the debug level for any adapter at run-time using the
.Xr sysctl 8
variable
.Va dev.mpr.X.debug_level .
.Pp
All
.Va debug_level
variables can be named by either an integer value or a text string.
Multiple values can be specified together by either ORing the
integer values or by providing a comma-separated list of names.
The current
.Va debug_level
status is reported in both formats for convenience.
The following levels are available:
.Bl -column "FlagXX" "NameXXXX" "Description" -offset indent
.It Em Flag Ta Em Name Ta Em Description
.It 0x0001 Ta info Ta Basic information (enabled by default)
.It 0x0002 Ta fault Ta Driver faults (enabled by default)
.It 0x0004 Ta event Ta Controller events
.It 0x0008 Ta log Ta Logging data from controller
.It 0x0010 Ta recovery Ta Tracing of recovery operations
.It 0x0020 Ta error Ta Parameter errors and programming bugs
.It 0x0040 Ta init Ta System initialization operations
.It 0x0080 Ta xinfo Ta More detailed information
.It 0x0100 Ta user Ta Tracing of user-generated commands (IOCTL)
.It 0x0200 Ta mapping Ta Tracing of device mapping
.It 0x0400 Ta trace Ta Tracing through driver functions
.El
.Sh SEE ALSO
.Xr cam 4 ,
.Xr cd 4 ,

View File

@ -313,31 +313,41 @@ dev.mps.X.use_phy_num
The same set of values are valid as when setting this tunable for all adapters.
.Pp
.Sh DEBUGGING
To enable debugging prints from the
.Nm
driver, set the
.Bd -literal -offset indent
hw.mps.X.debug_level
.Ed
.Pp
tunable, either in
Driver diagnostic printing is controlled in
.Xr loader.conf 5
or by using
.Xr sysctl 8 .
These bits have the described effects:
.Bd -literal -offset indent
0x0001 Enable informational prints (set by default).
0x0002 Enable prints for driver faults (set by default).
0x0004 Enable prints for controller events.
0x0008 Enable prints for controller logging.
0x0010 Enable prints for tracing recovery operations.
0x0020 Enable prints for parameter errors and programming bugs.
0x0040 Enable prints for system initialization operations.
0x0080 Enable prints for more detailed information.
0x0100 Enable prints for user-generated commands (IOCTL).
0x0200 Enable prints for device mapping.
0x0400 Enable prints for tracing through driver functions.
.Ed
by using the global
.Va hw.mps.debug_level
and per-device
.Va dev.mps.X.debug_level
tunables.
One can alter the debug level for any adapter at run-time using the
.Xr sysctl 8
variable
.Va dev.mps.X.debug_level .
.Pp
All
.Va debug_level
variables can be named by either an integer value or a text string.
Multiple values can be specified together by either ORing the
integer values or by providing a comma-separated list of names.
The current
.Va debug_level
status is reported in both formats for convenience.
The following levels are available:
.Bl -column "FlagXX" "NameXXXX" "Description" -offset indent
.It Em Flag Ta Em Name Ta Em Description
.It 0x0001 Ta info Ta Basic information (enabled by default)
.It 0x0002 Ta fault Ta Driver faults (enabled by default)
.It 0x0004 Ta event Ta Controller events
.It 0x0008 Ta log Ta Logging data from controller
.It 0x0010 Ta recovery Ta Tracing of recovery operations
.It 0x0020 Ta error Ta Parameter errors and programming bugs
.It 0x0040 Ta init Ta System initialization operations
.It 0x0080 Ta xinfo Ta More detailed information
.It 0x0100 Ta user Ta Tracing of user-generated commands (IOCTL)
.It 0x0200 Ta mapping Ta Tracing of device mapping
.It 0x0400 Ta trace Ta Tracing through driver functions
.El
.Sh SEE ALSO
.Xr cam 4 ,
.Xr cd 4 ,

View File

@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/taskqueue.h>
#include <sys/endian.h>
#include <sys/eventhandler.h>
#include <sys/sbuf.h>
#include <machine/bus.h>
#include <machine/resource.h>
@ -105,6 +106,9 @@ static int mpr_reregister_events(struct mpr_softc *sc);
static void mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm);
static int mpr_get_iocfacts(struct mpr_softc *sc, MPI2_IOC_FACTS_REPLY *facts);
static int mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag);
static int mpr_debug_sysctl(SYSCTL_HANDLER_ARGS);
static void mpr_parse_debug(struct mpr_softc *sc, char *list);
SYSCTL_NODE(_hw, OID_AUTO, mpr, CTLFLAG_RD, 0, "MPR Driver Parameters");
MALLOC_DEFINE(M_MPR, "mpr", "mpr driver memory");
@ -1591,7 +1595,7 @@ mpr_init_queues(struct mpr_softc *sc)
void
mpr_get_tunables(struct mpr_softc *sc)
{
char tmpstr[80];
char tmpstr[80], mpr_debug[80];
/* XXX default to some debugging for now */
sc->mpr_debug = MPR_INFO | MPR_FAULT;
@ -1611,7 +1615,9 @@ mpr_get_tunables(struct mpr_softc *sc)
/*
* Grab the global variables.
*/
TUNABLE_INT_FETCH("hw.mpr.debug_level", &sc->mpr_debug);
bzero(mpr_debug, 80);
if (TUNABLE_STR_FETCH("hw.mpr.debug_level", mpr_debug, 80) != 0)
mpr_parse_debug(sc, mpr_debug);
TUNABLE_INT_FETCH("hw.mpr.disable_msix", &sc->disable_msix);
TUNABLE_INT_FETCH("hw.mpr.disable_msi", &sc->disable_msi);
TUNABLE_INT_FETCH("hw.mpr.max_msix", &sc->max_msix);
@ -1628,7 +1634,9 @@ mpr_get_tunables(struct mpr_softc *sc)
/* Grab the unit-instance variables */
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level",
device_get_unit(sc->mpr_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->mpr_debug);
bzero(mpr_debug, 80);
if (TUNABLE_STR_FETCH(tmpstr, mpr_debug, 80) != 0)
mpr_parse_debug(sc, mpr_debug);
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.disable_msix",
device_get_unit(sc->mpr_dev));
@ -1714,9 +1722,9 @@ mpr_setup_sysctl(struct mpr_softc *sc)
sysctl_tree = sc->sysctl_tree;
}
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "debug_level", CTLFLAG_RW, &sc->mpr_debug, 0,
"mpr debug level");
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "debug_level", CTLTYPE_STRING | CTLFLAG_RW, sc, 0,
mpr_debug_sysctl, "A", "mpr debug level");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "disable_msix", CTLFLAG_RD, &sc->disable_msix, 0,
@ -1809,6 +1817,104 @@ mpr_setup_sysctl(struct mpr_softc *sc)
&sc->prp_page_alloc_fail, "PRP page allocation failures");
}
static struct mpr_debug_string {
char *name;
int flag;
} mpr_debug_strings[] = {
{"info", MPR_INFO},
{"fault", MPR_FAULT},
{"event", MPR_EVENT},
{"log", MPR_LOG},
{"recovery", MPR_RECOVERY},
{"error", MPR_ERROR},
{"init", MPR_INIT},
{"xinfo", MPR_XINFO},
{"user", MPR_USER},
{"mapping", MPR_MAPPING},
{"trace", MPR_TRACE}
};
static int
mpr_debug_sysctl(SYSCTL_HANDLER_ARGS)
{
struct mpr_softc *sc;
struct mpr_debug_string *string;
struct sbuf sbuf;
char *buffer;
size_t sz;
int i, len, debug, error;
sc = (struct mpr_softc *)arg1;
error = sysctl_wire_old_buffer(req, 0);
if (error != 0)
return (error);
sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
debug = sc->mpr_debug;
sbuf_printf(&sbuf, "%#x", debug);
sz = sizeof(mpr_debug_strings) / sizeof(mpr_debug_strings[0]);
for (i = 0; i < sz; i++) {
string = &mpr_debug_strings[i];
if (debug & string->flag)
sbuf_printf(&sbuf, ",%s", string->name);
}
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
if (error || req->newptr == NULL)
return (error);
len = req->newlen - req->newidx;
if (len == 0)
return (0);
buffer = malloc(len, M_MPR, M_ZERO|M_WAITOK);
error = SYSCTL_IN(req, buffer, len);
mpr_parse_debug(sc, buffer);
free(buffer, M_MPR);
return (error);
}
static void
mpr_parse_debug(struct mpr_softc *sc, char *list)
{
struct mpr_debug_string *string;
char *token, *endtoken;
size_t sz;
int flags, i;
if (list == NULL || *list == '\0')
return;
flags = 0;
sz = sizeof(mpr_debug_strings) / sizeof(mpr_debug_strings[0]);
while ((token = strsep(&list, ":,")) != NULL) {
/* Handle integer flags */
flags |= strtol(token, &endtoken, 0);
if (token != endtoken)
continue;
/* Handle text flags */
for (i = 0; i < sz; i++) {
string = &mpr_debug_strings[i];
if (strcasecmp(token, string->name) == 0) {
flags |= string->flag;
break;
}
}
}
sc->mpr_debug = flags;
return;
}
int
mpr_attach(struct mpr_softc *sc)
{

View File

@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/taskqueue.h>
#include <sys/endian.h>
#include <sys/eventhandler.h>
#include <sys/sbuf.h>
#include <machine/bus.h>
#include <machine/resource.h>
@ -102,6 +103,9 @@ static int mps_reregister_events(struct mps_softc *sc);
static void mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm);
static int mps_get_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts);
static int mps_wait_db_ack(struct mps_softc *sc, int timeout, int sleep_flag);
static int mps_debug_sysctl(SYSCTL_HANDLER_ARGS);
static void mps_parse_debug(struct mps_softc *sc, char *list);
SYSCTL_NODE(_hw, OID_AUTO, mps, CTLFLAG_RD, 0, "MPS Driver Parameters");
MALLOC_DEFINE(M_MPT2, "mps", "mpt2 driver memory");
@ -1452,7 +1456,7 @@ mps_init_queues(struct mps_softc *sc)
void
mps_get_tunables(struct mps_softc *sc)
{
char tmpstr[80];
char tmpstr[80], mps_debug[80];
/* XXX default to some debugging for now */
sc->mps_debug = MPS_INFO|MPS_FAULT;
@ -1472,7 +1476,9 @@ mps_get_tunables(struct mps_softc *sc)
/*
* Grab the global variables.
*/
TUNABLE_INT_FETCH("hw.mps.debug_level", &sc->mps_debug);
bzero(mps_debug, 80);
if (TUNABLE_STR_FETCH("hw.mps.debug_level", mps_debug, 80) != 0)
mps_parse_debug(sc, mps_debug);
TUNABLE_INT_FETCH("hw.mps.disable_msix", &sc->disable_msix);
TUNABLE_INT_FETCH("hw.mps.disable_msi", &sc->disable_msi);
TUNABLE_INT_FETCH("hw.mps.max_msix", &sc->max_msix);
@ -1489,7 +1495,9 @@ mps_get_tunables(struct mps_softc *sc)
/* Grab the unit-instance variables */
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level",
device_get_unit(sc->mps_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->mps_debug);
bzero(mps_debug, 80);
if (TUNABLE_STR_FETCH(tmpstr, mps_debug, 80) != 0)
mps_parse_debug(sc, mps_debug);
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.disable_msix",
device_get_unit(sc->mps_dev));
@ -1576,9 +1584,9 @@ mps_setup_sysctl(struct mps_softc *sc)
sysctl_tree = sc->sysctl_tree;
}
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "debug_level", CTLFLAG_RW, &sc->mps_debug, 0,
"mps debug level");
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "debug_level", CTLTYPE_STRING | CTLFLAG_RW, sc, 0,
mps_debug_sysctl, "A", "mps debug level");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "disable_msix", CTLFLAG_RD, &sc->disable_msix, 0,
@ -1671,6 +1679,104 @@ mps_setup_sysctl(struct mps_softc *sc)
"Use the phy number for enumeration");
}
struct mps_debug_string {
char *name;
int flag;
} mps_debug_strings[] = {
{"info", MPS_INFO},
{"fault", MPS_FAULT},
{"event", MPS_EVENT},
{"log", MPS_LOG},
{"recovery", MPS_RECOVERY},
{"error", MPS_ERROR},
{"init", MPS_INIT},
{"xinfo", MPS_XINFO},
{"user", MPS_USER},
{"mapping", MPS_MAPPING},
{"trace", MPS_TRACE}
};
static int
mps_debug_sysctl(SYSCTL_HANDLER_ARGS)
{
struct mps_softc *sc;
struct mps_debug_string *string;
struct sbuf sbuf;
char *buffer;
size_t sz;
int i, len, debug, error;
sc = (struct mps_softc *)arg1;
error = sysctl_wire_old_buffer(req, 0);
if (error != 0)
return (error);
sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
debug = sc->mps_debug;
sbuf_printf(&sbuf, "%#x", debug);
sz = sizeof(mps_debug_strings) / sizeof(mps_debug_strings[0]);
for (i = 0; i < sz; i++) {
string = &mps_debug_strings[i];
if (debug & string->flag)
sbuf_printf(&sbuf, ",%s", string->name);
}
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
if (error || req->newptr == NULL)
return (error);
len = req->newlen - req->newidx;
if (len == 0)
return (0);
buffer = malloc(len, M_MPT2, M_ZERO|M_WAITOK);
error = SYSCTL_IN(req, buffer, len);
mps_parse_debug(sc, buffer);
free(buffer, M_MPT2);
return (error);
}
static void
mps_parse_debug(struct mps_softc *sc, char *list)
{
struct mps_debug_string *string;
char *token, *endtoken;
size_t sz;
int flags, i;
if (list == NULL || *list == '\0')
return;
flags = 0;
sz = sizeof(mps_debug_strings) / sizeof(mps_debug_strings[0]);
while ((token = strsep(&list, ":,")) != NULL) {
/* Handle integer flags */
flags |= strtol(token, &endtoken, 0);
if (token != endtoken)
continue;
/* Handle text flags */
for (i = 0; i < sz; i++) {
string = &mps_debug_strings[i];
if (strcasecmp(token, string->name) == 0) {
flags |= string->flag;
break;
}
}
}
sc->mps_debug = flags;
return;
}
int
mps_attach(struct mps_softc *sc)
{