Author: mav
Date: Tue Jun 23 16:13:20 2015
New Revision: 284727
URL: https://svnweb.freebsd.org/changeset/base/284727

Log:
  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.

Modified:
  head/sys/dev/isp/isp_freebsd.c
  head/sys/dev/isp/isp_pci.c

Modified: head/sys/dev/isp/isp_freebsd.c
==============================================================================
--- head/sys/dev/isp/isp_freebsd.c      Tue Jun 23 15:49:12 2015        
(r284726)
+++ head/sys/dev/isp/isp_freebsd.c      Tue Jun 23 16:13:20 2015        
(r284727)
@@ -84,6 +84,43 @@ static struct cdevsw isp_cdevsw = {
 };
 
 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)
 {
        struct ccb_setasync csa;
@@ -138,6 +175,9 @@ isp_attach_chan(ispsoftc_t *isp, struct 
        } 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 
                }
                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 (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, 
0)->inject_lost_data_frame, 0, "Cause a Lost Frame on a Read");
+               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);
 }

Modified: head/sys/dev/isp/isp_pci.c
==============================================================================
--- head/sys/dev/isp/isp_pci.c  Tue Jun 23 15:49:12 2015        (r284726)
+++ head/sys/dev/isp/isp_pci.c  Tue Jun 23 16:13:20 2015        (r284727)
@@ -527,8 +527,15 @@ isp_get_specific_options(device_t dev, i
 {
        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, i
        }
 
        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, i
        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, i
        }
 
        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, i
         * '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, i
        }
 
        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, i
        }
 
        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, i
        }
 
        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, i
        }
 
        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 {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to