ntb_hw(4): Add sysctls for administrative/test link config, state

dev.ntb_hw.0.admin_up=0/1: Like ifconfig UP/DOWN.
dev.ntb_hw.0.active=0/1:   Like ifconfig 'status'

Reviewed by:	ngie
Sponsored by:	EMC / Isilon Storage Division
Differential Revision:	https://reviews.freebsd.org/D6429
This commit is contained in:
cem 2016-05-18 02:10:05 +00:00
parent 18735d1ff5
commit 27b91c5342
2 changed files with 88 additions and 10 deletions

View File

@ -364,6 +364,8 @@ static bool ntb_poll_link(struct ntb_softc *ntb);
static void save_bar_parameters(struct ntb_pci_bar_info *bar);
static void ntb_sysctl_init(struct ntb_softc *);
static int sysctl_handle_features(SYSCTL_HANDLER_ARGS);
static int sysctl_handle_link_admin(SYSCTL_HANDLER_ARGS);
static int sysctl_handle_link_status_human(SYSCTL_HANDLER_ARGS);
static int sysctl_handle_link_status(SYSCTL_HANDLER_ARGS);
static int sysctl_handle_register(SYSCTL_HANDLER_ARGS);
@ -2132,6 +2134,8 @@ ntb_link_enable(struct ntb_softc *ntb, enum ntb_speed s __unused,
{
uint32_t cntl;
ntb_printf(2, "%s\n", __func__);
if (ntb->type == NTB_ATOM) {
pci_write_config(ntb->device, NTB_PPD_OFFSET,
ntb->ppd | ATOM_PPD_INIT_LINK, 4);
@ -2170,6 +2174,8 @@ ntb_link_disable(struct ntb_softc *ntb)
{
uint32_t cntl;
ntb_printf(2, "%s\n", __func__);
if (ntb->conn_type == NTB_CONN_TRANSPARENT) {
ntb_link_event(ntb);
return (0);
@ -2185,6 +2191,23 @@ ntb_link_disable(struct ntb_softc *ntb)
return (0);
}
bool
ntb_link_enabled(struct ntb_softc *ntb)
{
uint32_t cntl;
if (ntb->type == NTB_ATOM) {
cntl = pci_read_config(ntb->device, NTB_PPD_OFFSET, 4);
return ((cntl & ATOM_PPD_INIT_LINK) != 0);
}
if (ntb->conn_type == NTB_CONN_TRANSPARENT)
return (true);
cntl = ntb_reg_read(4, ntb->reg->ntb_ctl);
return ((cntl & NTB_CNTL_LINK_DISABLE) == 0);
}
static void
recover_atom_link(void *arg)
{
@ -2304,16 +2327,26 @@ SYSCTL_NODE(_hw_ntb, OID_AUTO, debug_info, CTLFLAG_RW, 0,
static void
ntb_sysctl_init(struct ntb_softc *ntb)
{
struct sysctl_oid_list *tree_par, *regpar, *statpar, *errpar;
struct sysctl_oid_list *globals, *tree_par, *regpar, *statpar, *errpar;
struct sysctl_ctx_list *ctx;
struct sysctl_oid *tree, *tmptree;
ctx = device_get_sysctl_ctx(ntb->device);
globals = SYSCTL_CHILDREN(device_get_sysctl_tree(ntb->device));
tree = SYSCTL_ADD_NODE(ctx,
SYSCTL_CHILDREN(device_get_sysctl_tree(ntb->device)), OID_AUTO,
"debug_info", CTLFLAG_RD, NULL,
"Driver state, statistics, and HW registers");
SYSCTL_ADD_PROC(ctx, globals, OID_AUTO, "link_status",
CTLFLAG_RD | CTLTYPE_STRING, ntb, 0,
sysctl_handle_link_status_human, "A",
"Link status (human readable)");
SYSCTL_ADD_PROC(ctx, globals, OID_AUTO, "active",
CTLFLAG_RD | CTLTYPE_UINT, ntb, 0, sysctl_handle_link_status,
"IU", "Link status (1=active, 0=inactive)");
SYSCTL_ADD_PROC(ctx, globals, OID_AUTO, "admin_up",
CTLFLAG_RW | CTLTYPE_UINT, ntb, 0, sysctl_handle_link_admin,
"IU", "Set/get interface status (1=UP, 0=DOWN)");
tree = SYSCTL_ADD_NODE(ctx, globals, OID_AUTO, "debug_info",
CTLFLAG_RD, NULL, "Driver state, statistics, and HW registers");
tree_par = SYSCTL_CHILDREN(tree);
SYSCTL_ADD_UINT(ctx, tree_par, OID_AUTO, "conn_type", CTLFLAG_RD,
@ -2343,10 +2376,6 @@ ntb_sysctl_init(struct ntb_softc *ntb)
__DEVOLATILE(uint32_t *, &ntb->lnk_sta), 0,
"LNK STA register (cached)");
SYSCTL_ADD_PROC(ctx, tree_par, OID_AUTO, "link_status",
CTLFLAG_RD | CTLTYPE_STRING, ntb, 0, sysctl_handle_link_status,
"A", "Link status");
SYSCTL_ADD_U8(ctx, tree_par, OID_AUTO, "mw_count", CTLFLAG_RD,
&ntb->mw_count, 0, "MW count");
SYSCTL_ADD_U8(ctx, tree_par, OID_AUTO, "spad_count", CTLFLAG_RD,
@ -2592,7 +2621,37 @@ sysctl_handle_features(SYSCTL_HANDLER_ARGS)
}
static int
sysctl_handle_link_status(SYSCTL_HANDLER_ARGS)
sysctl_handle_link_admin(SYSCTL_HANDLER_ARGS)
{
struct ntb_softc *ntb;
unsigned old, new;
int error;
error = 0;
ntb = arg1;
old = ntb_link_enabled(ntb);
error = SYSCTL_OUT(req, &old, sizeof(old));
if (error != 0 || req->newptr == NULL)
return (error);
error = SYSCTL_IN(req, &new, sizeof(new));
if (error != 0)
return (error);
ntb_printf(0, "Admin set interface state to '%sabled'\n",
(new != 0)? "en" : "dis");
if (new != 0)
error = ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
else
error = ntb_link_disable(ntb);
return (error);
}
static int
sysctl_handle_link_status_human(SYSCTL_HANDLER_ARGS)
{
struct ntb_softc *ntb;
struct sbuf sb;
@ -2619,6 +2678,24 @@ sysctl_handle_link_status(SYSCTL_HANDLER_ARGS)
return (EINVAL);
}
static int
sysctl_handle_link_status(SYSCTL_HANDLER_ARGS)
{
struct ntb_softc *ntb;
unsigned res;
int error;
error = 0;
ntb = arg1;
res = ntb_link_is_up(ntb, NULL, NULL);
error = SYSCTL_OUT(req, &res, sizeof(res));
if (error || !req->newptr)
return (error);
return (EINVAL);
}
static int
sysctl_handle_register(SYSCTL_HANDLER_ARGS)
{

View File

@ -70,6 +70,7 @@ bool ntb_link_is_up(struct ntb_softc *, enum ntb_speed *, enum ntb_width *);
void ntb_link_event(struct ntb_softc *);
int ntb_link_enable(struct ntb_softc *, enum ntb_speed, enum ntb_width);
int ntb_link_disable(struct ntb_softc *);
bool ntb_link_enabled(struct ntb_softc *);
int ntb_set_ctx(struct ntb_softc *, void *, const struct ntb_ctx_ops *);
void *ntb_get_ctx(struct ntb_softc *, const struct ntb_ctx_ops **);