Add dev.isp.X.role sysctl in addition to tunable.
It (mostly) allows to enable/disable initiator mode in run time. Target mode control is blocked here to force coordination with CTL. While there, add separate tunables/sysctls for virtual channels.
This commit is contained in:
parent
be30841cf6
commit
ebd76cdbc6
@ -83,6 +83,43 @@ static struct cdevsw isp_cdevsw = {
|
||||
.d_name = "isp",
|
||||
};
|
||||
|
||||
static int
|
||||
isp_role_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
ispsoftc_t *isp = (ispsoftc_t *)arg1;
|
||||
int chan = arg2;
|
||||
int error, old, value;
|
||||
|
||||
value = FCPARAM(isp, chan)->role;
|
||||
|
||||
error = sysctl_handle_int(oidp, &value, 0, req);
|
||||
if ((error != 0) || (req->newptr == NULL))
|
||||
return (error);
|
||||
|
||||
if (value < ISP_ROLE_NONE || value > ISP_ROLE_BOTH)
|
||||
return (EINVAL);
|
||||
|
||||
ISP_LOCK(isp);
|
||||
old = FCPARAM(isp, chan)->role;
|
||||
|
||||
/* If nothing has changed -- we are done. */
|
||||
if (value == old) {
|
||||
ISP_UNLOCK(isp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* We don't allow target mode switch from here. */
|
||||
if ((value ^ old) & ISP_ROLE_TARGET) {
|
||||
ISP_UNLOCK(isp);
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
/* Actually change the role. */
|
||||
error = isp_fc_change_role(isp, chan, value);
|
||||
ISP_UNLOCK(isp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
|
||||
{
|
||||
@ -138,6 +175,9 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
|
||||
} else {
|
||||
fcparam *fcp = FCPARAM(isp, chan);
|
||||
struct isp_fc *fc = ISP_FC_PC(isp, chan);
|
||||
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(isp->isp_osinfo.dev);
|
||||
struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
|
||||
char name[16];
|
||||
|
||||
ISP_LOCK(isp);
|
||||
fc->sim = sim;
|
||||
@ -178,17 +218,21 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
|
||||
}
|
||||
ISP_FC_PC(isp, chan)->num_threads += 1;
|
||||
#endif
|
||||
if (chan == 0) {
|
||||
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(isp->isp_osinfo.dev);
|
||||
struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
|
||||
SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "wwnn", CTLFLAG_RD, &FCPARAM(isp, 0)->isp_wwnn, "World Wide Node Name");
|
||||
SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "wwpn", CTLFLAG_RD, &FCPARAM(isp, 0)->isp_wwpn, "World Wide Port Name");
|
||||
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "loop_down_limit", CTLFLAG_RW, &ISP_FC_PC(isp, 0)->loop_down_limit, 0, "Loop Down Limit");
|
||||
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "gone_device_time", CTLFLAG_RW, &ISP_FC_PC(isp, 0)->gone_device_time, 0, "Gone Device Time");
|
||||
#if defined(ISP_TARGET_MODE) && defined(DEBUG)
|
||||
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "inject_lost_data_frame", CTLFLAG_RW, &ISP_FC_PC(isp, 0)->inject_lost_data_frame, 0, "Cause a Lost Frame on a Read");
|
||||
#endif
|
||||
if (chan > 0) {
|
||||
snprintf(name, sizeof(name), "chan%d", chan);
|
||||
tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(tree),
|
||||
OID_AUTO, name, CTLFLAG_RW, 0, "Virtual channel");
|
||||
}
|
||||
SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "wwnn", CTLFLAG_RD, &FCPARAM(isp, chan)->isp_wwnn, "World Wide Node Name");
|
||||
SYSCTL_ADD_QUAD(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "wwpn", CTLFLAG_RD, &FCPARAM(isp, chan)->isp_wwpn, "World Wide Port Name");
|
||||
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "loop_down_limit", CTLFLAG_RW, &ISP_FC_PC(isp, chan)->loop_down_limit, 0, "Loop Down Limit");
|
||||
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "gone_device_time", CTLFLAG_RW, &ISP_FC_PC(isp, chan)->gone_device_time, 0, "Gone Device Time");
|
||||
#if defined(ISP_TARGET_MODE) && defined(DEBUG)
|
||||
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "inject_lost_data_frame", CTLFLAG_RW, &ISP_FC_PC(isp, chan)->inject_lost_data_frame, 0, "Cause a Lost Frame on a Read");
|
||||
#endif
|
||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
||||
"role", CTLTYPE_INT | CTLFLAG_RW, isp, chan,
|
||||
isp_role_sysctl, "I", "Current role");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
@ -527,8 +527,15 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
{
|
||||
const char *sptr;
|
||||
int tval = 0;
|
||||
char prefix[12], name[16];
|
||||
|
||||
if (resource_int_value(device_get_name(dev), device_get_unit(dev), "iid", &tval)) {
|
||||
if (chan == 0)
|
||||
prefix[0] = 0;
|
||||
else
|
||||
snprintf(prefix, sizeof(prefix), "chan%d.", chan);
|
||||
snprintf(name, sizeof(name), "%siid", prefix);
|
||||
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, &tval)) {
|
||||
if (IS_FC(isp)) {
|
||||
ISP_FC_PC(isp, chan)->default_id = 109 - chan;
|
||||
} else {
|
||||
@ -548,13 +555,15 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
}
|
||||
|
||||
tval = -1;
|
||||
if (resource_int_value(device_get_name(dev), device_get_unit(dev), "role", &tval) == 0) {
|
||||
snprintf(name, sizeof(name), "%srole", prefix);
|
||||
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, &tval) == 0) {
|
||||
switch (tval) {
|
||||
case ISP_ROLE_NONE:
|
||||
case ISP_ROLE_INITIATOR:
|
||||
case ISP_ROLE_TARGET:
|
||||
case ISP_ROLE_INITIATOR|ISP_ROLE_TARGET:
|
||||
device_printf(dev, "setting role to 0x%x\n", tval);
|
||||
case ISP_ROLE_BOTH:
|
||||
device_printf(dev, "Chan %d setting role to 0x%x\n", chan, tval);
|
||||
break;
|
||||
default:
|
||||
tval = -1;
|
||||
@ -572,11 +581,15 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
ISP_FC_PC(isp, chan)->def_role = tval;
|
||||
|
||||
tval = 0;
|
||||
if (resource_int_value(device_get_name(dev), device_get_unit(dev), "fullduplex", &tval) == 0 && tval != 0) {
|
||||
snprintf(name, sizeof(name), "%sfullduplex", prefix);
|
||||
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, &tval) == 0 && tval != 0) {
|
||||
isp->isp_confopts |= ISP_CFG_FULL_DUPLEX;
|
||||
}
|
||||
sptr = 0;
|
||||
if (resource_string_value(device_get_name(dev), device_get_unit(dev), "topology", (const char **) &sptr) == 0 && sptr != 0) {
|
||||
snprintf(name, sizeof(name), "%stopology", prefix);
|
||||
if (resource_string_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, (const char **) &sptr) == 0 && sptr != 0) {
|
||||
if (strcmp(sptr, "lport") == 0) {
|
||||
isp->isp_confopts |= ISP_CFG_LPORT;
|
||||
} else if (strcmp(sptr, "nport") == 0) {
|
||||
@ -589,13 +602,17 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
}
|
||||
|
||||
tval = 0;
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev), "nofctape", &tval);
|
||||
snprintf(name, sizeof(name), "%snofctape", prefix);
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, &tval);
|
||||
if (tval) {
|
||||
isp->isp_confopts |= ISP_CFG_NOFCTAPE;
|
||||
}
|
||||
|
||||
tval = 0;
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev), "fctape", &tval);
|
||||
snprintf(name, sizeof(name), "%sfctape", prefix);
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, &tval);
|
||||
if (tval) {
|
||||
isp->isp_confopts &= ~ISP_CFG_NOFCTAPE;
|
||||
isp->isp_confopts |= ISP_CFG_FCTAPE;
|
||||
@ -611,7 +628,9 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
* 'w' (e..g w50000000aaaa0001). Sigh.
|
||||
*/
|
||||
sptr = 0;
|
||||
tval = resource_string_value(device_get_name(dev), device_get_unit(dev), "portwwn", (const char **) &sptr);
|
||||
snprintf(name, sizeof(name), "%sportwwn", prefix);
|
||||
tval = resource_string_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, (const char **) &sptr);
|
||||
if (tval == 0 && sptr != 0 && *sptr++ == 'w') {
|
||||
char *eptr = 0;
|
||||
ISP_FC_PC(isp, chan)->def_wwpn = strtouq(sptr, &eptr, 16);
|
||||
@ -622,7 +641,9 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
}
|
||||
|
||||
sptr = 0;
|
||||
tval = resource_string_value(device_get_name(dev), device_get_unit(dev), "nodewwn", (const char **) &sptr);
|
||||
snprintf(name, sizeof(name), "%snodewwn", prefix);
|
||||
tval = resource_string_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, (const char **) &sptr);
|
||||
if (tval == 0 && sptr != 0 && *sptr++ == 'w') {
|
||||
char *eptr = 0;
|
||||
ISP_FC_PC(isp, chan)->def_wwnn = strtouq(sptr, &eptr, 16);
|
||||
@ -633,7 +654,9 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
}
|
||||
|
||||
tval = 0;
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev), "hysteresis", &tval);
|
||||
snprintf(name, sizeof(name), "%shysteresis", prefix);
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
"name", &tval);
|
||||
if (tval >= 0 && tval < 256) {
|
||||
ISP_FC_PC(isp, chan)->hysteresis = tval;
|
||||
} else {
|
||||
@ -641,7 +664,9 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
}
|
||||
|
||||
tval = -1;
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev), "loop_down_limit", &tval);
|
||||
snprintf(name, sizeof(name), "%sloop_down_limit", prefix);
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, &tval);
|
||||
if (tval >= 0 && tval < 0xffff) {
|
||||
ISP_FC_PC(isp, chan)->loop_down_limit = tval;
|
||||
} else {
|
||||
@ -649,7 +674,9 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
||||
}
|
||||
|
||||
tval = -1;
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev), "gone_device_time", &tval);
|
||||
snprintf(name, sizeof(name), "%sgone_device_time", prefix);
|
||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||
name, &tval);
|
||||
if (tval >= 0 && tval < 0xffff) {
|
||||
ISP_FC_PC(isp, chan)->gone_device_time = tval;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user