Author: scottl
Date: Wed Nov  2 15:13:25 2016
New Revision: 308217
URL: https://svnweb.freebsd.org/changeset/base/308217

Log:
  Add a fallback to the device mapper logic.  We've seen systems in the field
  that are apparently misconfigured by the manufacturer and cause the mapping
  logic to fail.  The fallback allows drive numbers to be assigned based on the
  PHY number that they're attached to.  Add sysctls and tunables to overrid
  this new behavior, but they should be considered only necessary for debugging.
  
  Reviewed by:   imp, smh
  Obtained from:        Netflix
  MFC after:    3 days
  Sponsored by: D8403

Modified:
  head/sys/dev/mpr/mpr.c
  head/sys/dev/mpr/mpr_sas_lsi.c
  head/sys/dev/mpr/mprvar.h
  head/sys/dev/mps/mps.c
  head/sys/dev/mps/mps_sas_lsi.c
  head/sys/dev/mps/mpsvar.h

Modified: head/sys/dev/mpr/mpr.c
==============================================================================
--- head/sys/dev/mpr/mpr.c      Wed Nov  2 15:11:23 2016        (r308216)
+++ head/sys/dev/mpr/mpr.c      Wed Nov  2 15:13:25 2016        (r308217)
@@ -1376,6 +1376,7 @@ mpr_get_tunables(struct mpr_softc *sc)
        sc->max_io_pages = MPR_MAXIO_PAGES;
        sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD;
        sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
+       sc->use_phynum = 1;
 
        /*
         * Grab the global variables.
@@ -1387,6 +1388,7 @@ mpr_get_tunables(struct mpr_softc *sc)
        TUNABLE_INT_FETCH("hw.mpr.max_io_pages", &sc->max_io_pages);
        TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu);
        TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time);
+       TUNABLE_INT_FETCH("hw.mpr.use_phy_num", &sc->use_phynum);
 
        /* Grab the unit-instance variables */
        snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level",
@@ -1421,6 +1423,10 @@ mpr_get_tunables(struct mpr_softc *sc)
        snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time",
            device_get_unit(sc->mpr_dev));
        TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time);
+
+       snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.use_phy_num",
+           device_get_unit(sc->mpr_dev));
+       TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum);
 }
 
 static void
@@ -1510,6 +1516,10 @@ mpr_setup_sysctl(struct mpr_softc *sc)
            OID_AUTO, "spinup_wait_time", CTLFLAG_RD,
            &sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for "
            "spinup after SATA ID error");
+
+       SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+           OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0,
+           "Use the phy number for enumeration");
 }
 
 int

Modified: head/sys/dev/mpr/mpr_sas_lsi.c
==============================================================================
--- head/sys/dev/mpr/mpr_sas_lsi.c      Wed Nov  2 15:11:23 2016        
(r308216)
+++ head/sys/dev/mpr/mpr_sas_lsi.c      Wed Nov  2 15:13:25 2016        
(r308217)
@@ -757,13 +757,24 @@ mprsas_add_device(struct mpr_softc *sc, 
                }
        }
 
-       id = mpr_mapping_get_sas_id(sc, sas_address, handle);
+       /*
+        * use_phynum:
+        *  1 - use the PhyNum field as a fallback to the mapping logic
+        *  0 - never use the PhyNum field
+        * -1 - only use the PhyNum field
+        */
+       id = MPR_MAP_BAD_ID;
+       if (sc->use_phynum != -1) 
+               id = mpr_mapping_get_sas_id(sc, sas_address, handle);
        if (id == MPR_MAP_BAD_ID) {
-               printf("failure at %s:%d/%s()! Could not get ID for device "
-                   "with handle 0x%04x\n", __FILE__, __LINE__, __func__,
-                   handle);
-               error = ENXIO;
-               goto out;
+               if ((sc->use_phynum == 0)
+                || ((id = config_page.PhyNum) > sassc->maxtargets)) {
+                       mpr_dprint(sc, MPR_INFO, "failure at %s:%d/%s()! "
+                           "Could not get ID for device with handle 0x%04x\n",
+                           __FILE__, __LINE__, __func__, handle);
+                       error = ENXIO;
+                       goto out;
+               }
        }
 
        if (mprsas_check_id(sassc, id) != 0) {
@@ -772,9 +783,16 @@ mprsas_add_device(struct mpr_softc *sc, 
                goto out;
        }
 
+       targ = &sassc->targets[id];
+       if (targ->handle != 0x0) {
+               mpr_dprint(sc, MPR_MAPPING, "Attempting to reuse target id "
+                   "%d handle 0x%04x\n", id, targ->handle);
+               error = ENXIO;
+               goto out;
+       }
+
        mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n",
            sas_address);
-       targ = &sassc->targets[id];
        targ->devinfo = device_info;
        targ->devname = le32toh(config_page.DeviceName.High);
        targ->devname = (targ->devname << 32) | 

Modified: head/sys/dev/mpr/mprvar.h
==============================================================================
--- head/sys/dev/mpr/mprvar.h   Wed Nov  2 15:11:23 2016        (r308216)
+++ head/sys/dev/mpr/mprvar.h   Wed Nov  2 15:13:25 2016        (r308217)
@@ -271,6 +271,7 @@ struct mpr_softc {
        uint16_t                        chain_seg_size;
        u_int                           enable_ssu;
        int                             spinup_wait_time;
+       int                             use_phynum;
        uint64_t                        chain_alloc_fail;
        struct sysctl_ctx_list          sysctl_ctx;
        struct sysctl_oid               *sysctl_tree;

Modified: head/sys/dev/mps/mps.c
==============================================================================
--- head/sys/dev/mps/mps.c      Wed Nov  2 15:11:23 2016        (r308216)
+++ head/sys/dev/mps/mps.c      Wed Nov  2 15:13:25 2016        (r308217)
@@ -1353,6 +1353,7 @@ mps_get_tunables(struct mps_softc *sc)
        sc->max_io_pages = MPS_MAXIO_PAGES;
        sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD;
        sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
+       sc->use_phynum = 1;
 
        /*
         * Grab the global variables.
@@ -1364,6 +1365,7 @@ mps_get_tunables(struct mps_softc *sc)
        TUNABLE_INT_FETCH("hw.mps.max_io_pages", &sc->max_io_pages);
        TUNABLE_INT_FETCH("hw.mps.enable_ssu", &sc->enable_ssu);
        TUNABLE_INT_FETCH("hw.mps.spinup_wait_time", &sc->spinup_wait_time);
+       TUNABLE_INT_FETCH("hw.mps.use_phy_num", &sc->use_phynum);
 
        /* Grab the unit-instance variables */
        snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level",
@@ -1398,6 +1400,10 @@ mps_get_tunables(struct mps_softc *sc)
        snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.spinup_wait_time",
            device_get_unit(sc->mps_dev));
        TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time);
+
+       snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.use_phy_num",
+           device_get_unit(sc->mps_dev));
+       TUNABLE_INT_FETCH(tmpstr, &sc->use_phynum);
 }
 
 static void
@@ -1495,6 +1501,10 @@ mps_setup_sysctl(struct mps_softc *sc)
        SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
            OID_AUTO, "encl_table_dump", CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
            mps_mapping_encl_dump, "A", "Enclosure Table Dump");
+
+       SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
+           OID_AUTO, "use_phy_num", CTLFLAG_RD, &sc->use_phynum, 0,
+           "Use the phy number for enumeration");
 }
 
 int

Modified: head/sys/dev/mps/mps_sas_lsi.c
==============================================================================
--- head/sys/dev/mps/mps_sas_lsi.c      Wed Nov  2 15:11:23 2016        
(r308216)
+++ head/sys/dev/mps/mps_sas_lsi.c      Wed Nov  2 15:13:25 2016        
(r308217)
@@ -669,13 +669,24 @@ mpssas_add_device(struct mps_softc *sc, 
                }
        }
 
-       id = mps_mapping_get_sas_id(sc, sas_address, handle);
+       /*
+        * use_phynum:
+        *  1 - use the PhyNum field as a fallback to the mapping logic
+        *  0 - never use the PhyNum field
+        * -1 - only use the PhyNum field
+        */
+       id = MPS_MAP_BAD_ID;
+       if (sc->use_phynum != -1) 
+               id = mps_mapping_get_sas_id(sc, sas_address, handle);
        if (id == MPS_MAP_BAD_ID) {
-               printf("failure at %s:%d/%s()! Could not get ID for device "
-                   "with handle 0x%04x\n", __FILE__, __LINE__, __func__,
-                   handle);
-               error = ENXIO;
-               goto out;
+               if ((sc->use_phynum == 0)
+                || ((id = config_page.PhyNum) > sassc->maxtargets)) {
+                       mps_dprint(sc, MPS_INFO, "failure at %s:%d/%s()! "
+                           "Could not get ID for device with handle 0x%04x\n",
+                           __FILE__, __LINE__, __func__, handle);
+                       error = ENXIO;
+                       goto out;
+               }
        }
 
        if (mpssas_check_id(sassc, id) != 0) {
@@ -684,9 +695,16 @@ mpssas_add_device(struct mps_softc *sc, 
                goto out;
        }
 
+       targ = &sassc->targets[id];
+       if (targ->handle != 0x0) {
+               mps_dprint(sc, MPS_MAPPING, "Attempting to reuse target id "
+                   "%d handle 0x%04x\n", id, targ->handle);
+               error = ENXIO;
+               goto out;
+       }
+
        mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n",
            sas_address);
-       targ = &sassc->targets[id];
        targ->devinfo = device_info;
        targ->devname = le32toh(config_page.DeviceName.High);
        targ->devname = (targ->devname << 32) | 

Modified: head/sys/dev/mps/mpsvar.h
==============================================================================
--- head/sys/dev/mps/mpsvar.h   Wed Nov  2 15:11:23 2016        (r308216)
+++ head/sys/dev/mps/mpsvar.h   Wed Nov  2 15:13:25 2016        (r308217)
@@ -285,6 +285,7 @@ struct mps_softc {
        int                             chain_free_lowwater;
        u_int                           enable_ssu;
        int                             spinup_wait_time;
+       int                             use_phynum;
        uint64_t                        chain_alloc_fail;
        struct sysctl_ctx_list          sysctl_ctx;
        struct sysctl_oid               *sysctl_tree;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to