Author: slm
Date: Wed Aug 20 23:09:27 2014
New Revision: 270250
URL: http://svnweb.freebsd.org/changeset/base/270250

Log:
  MFC r269314 and r269316
  
  r269314:
  Bring in LSI's phase16 - phase18 changes
  * Implements Start Stop Unit for SATA direct-attach devices in IR mode to 
avoid
    data corruption.
  * Use CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT and CAM_TID_INVALID
  
  r269316:
  Bring in LSI's phase19 changes
  * Removed unused mpssas_discovery_timeout function.
  * Don't alter mapping boundaries if not raid firmware.
  * Check free_busaddr instead of post_busaddr (diff minimisation really)
  
  Approved by:  ken (co-mentor) and smh

Modified:
  stable/10/sys/dev/mps/mps.c
  stable/10/sys/dev/mps/mps_mapping.c
  stable/10/sys/dev/mps/mps_sas.c
  stable/10/sys/dev/mps/mps_sas.h
  stable/10/sys/dev/mps/mps_sas_lsi.c
  stable/10/sys/dev/mps/mpsvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/mps/mps.c
==============================================================================
--- stable/10/sys/dev/mps/mps.c Wed Aug 20 22:58:12 2014        (r270249)
+++ stable/10/sys/dev/mps/mps.c Wed Aug 20 23:09:27 2014        (r270250)
@@ -140,6 +140,7 @@ mps_diag_reset(struct mps_softc *sc,int 
 {
        uint32_t reg;
        int i, error, tries = 0;
+       uint8_t first_wait_done = FALSE;
 
        mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
 
@@ -182,15 +183,32 @@ mps_diag_reset(struct mps_softc *sc,int 
 
        /* Wait up to 300 seconds in 50ms intervals */
        error = ETIMEDOUT;
-       for (i = 0; i < 60000; i++) {
-               /* wait 50 msec */
-               if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
-                       msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
-                           "mpsdiag", hz/20);
-               else if (sleep_flag == CAN_SLEEP)
-                       pause("mpsdiag", hz/20);
-               else
-                       DELAY(50 * 1000);
+       for (i = 0; i < 6000; i++) {
+               /*
+                * Wait 50 msec. If this is the first time through, wait 256
+                * msec to satisfy Diag Reset timing requirements.
+                */
+               if (first_wait_done) {
+                       if (mtx_owned(&sc->mps_mtx) && sleep_flag == CAN_SLEEP)
+                               msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
+                                   "mpsdiag", hz/20);
+                       else if (sleep_flag == CAN_SLEEP)
+                               pause("mpsdiag", hz/20);
+                       else
+                               DELAY(50 * 1000);
+               } else {
+                       DELAY(256 * 1000);
+                       first_wait_done = TRUE;
+               }
+               /*
+                * Check for the RESET_ADAPTER bit to be cleared first, then
+                * wait for the RESET state to be cleared, which takes a little
+                * longer.
+                */
+               reg = mps_regread(sc, MPI2_HOST_DIAGNOSTIC_OFFSET);
+               if (reg & MPI2_DIAG_RESET_ADAPTER) {
+                       continue;
+               }
                reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
                if ((reg & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_RESET) {
                        error = 0;
@@ -236,7 +254,7 @@ mps_transition_ready(struct mps_softc *s
        sleep_flags = (sc->mps_flags & MPS_FLAGS_ATTACH_DONE)
                                        ? CAN_SLEEP:NO_SLEEP;
        error = 0;
-       while (tries++ < 5) {
+       while (tries++ < 1200) {
                reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
                mps_dprint(sc, MPS_INIT, "Doorbell= 0x%x\n", reg);
 
@@ -592,7 +610,7 @@ mps_iocfacts_free(struct mps_softc *sc)
 
        mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
 
-       if (sc->post_busaddr != 0)
+       if (sc->free_busaddr != 0)
                bus_dmamap_unload(sc->queues_dmat, sc->queues_map);
        if (sc->free_queue != NULL)
                bus_dmamem_free(sc->queues_dmat, sc->free_queue,
@@ -656,6 +674,9 @@ int
 mps_reinit(struct mps_softc *sc)
 {
        int error;
+       struct mpssas_softc *sassc;
+
+       sassc = sc->sassc;
 
        MPS_FUNCTRACE(sc);
 
@@ -736,6 +757,8 @@ mps_reinit(struct mps_softc *sc)
        mps_dprint(sc, MPS_INFO, "%s finished sc %p post %u free %u\n", 
            __func__, sc, sc->replypostindex, sc->replyfreeindex);
 
+       mpssas_release_simq_reinit(sassc);
+
        return 0;
 }
 
@@ -2510,6 +2533,7 @@ int
 mps_request_polled(struct mps_softc *sc, struct mps_command *cm)
 {
        int error, timeout = 0, rc;
+       struct timeval cur_time, start_time;
 
        error = 0;
 
@@ -2517,22 +2541,33 @@ mps_request_polled(struct mps_softc *sc,
        cm->cm_complete = NULL;
        mps_map_command(sc, cm);
 
+       getmicrotime(&start_time);
        while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) {
                mps_intr_locked(sc);
 
-               DELAY(50 * 1000);
-               if (timeout++ > 1000) {
+               if (mtx_owned(&sc->mps_mtx))
+                       msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
+                           "mpspoll", hz/20);
+               else
+                       pause("mpsdiag", hz/20);
+
+               /*
+                * Check for real-time timeout and fail if more than 60 seconds.
+                */
+               getmicrotime(&cur_time);
+               timeout = cur_time.tv_sec - start_time.tv_sec;
+               if (timeout > 60) {
                        mps_dprint(sc, MPS_FAULT, "polling failed\n");
                        error = ETIMEDOUT;
                        break;
                }
        }
-       
+
        if (error) {
                mps_dprint(sc, MPS_FAULT, "Calling Reinit from %s\n", __func__);
                rc = mps_reinit(sc);
-               mps_dprint(sc, MPS_FAULT, "Reinit %s\n", 
-                               (rc == 0) ? "success" : "failed");
+               mps_dprint(sc, MPS_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
+                   "failed");
        }
 
        return (error);

Modified: stable/10/sys/dev/mps/mps_mapping.c
==============================================================================
--- stable/10/sys/dev/mps/mps_mapping.c Wed Aug 20 22:58:12 2014        
(r270249)
+++ stable/10/sys/dev/mps/mps_mapping.c Wed Aug 20 23:09:27 2014        
(r270250)
@@ -336,12 +336,13 @@ _mapping_get_high_missing_mt_idx(struct 
        end_idx = sc->max_devices;
        if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
                start_idx = 1;
-       if (sc->ir_firmware)
+       if (sc->ir_firmware) {
                _mapping_get_ir_maprange(sc, &start_idx_ir, &end_idx_ir);
-       if (start_idx == start_idx_ir)
-               start_idx = end_idx_ir + 1;
-       else
-               end_idx = start_idx_ir;
+               if (start_idx == start_idx_ir)
+                       start_idx = end_idx_ir + 1;
+               else
+                       end_idx = start_idx_ir;
+       }
        mt_entry = &sc->mapping_table[start_idx];
        for (map_idx = start_idx; map_idx < end_idx; map_idx++, mt_entry++) {
                if (mt_entry->missing_count > high_missing_count) {

Modified: stable/10/sys/dev/mps/mps_sas.c
==============================================================================
--- stable/10/sys/dev/mps/mps_sas.c     Wed Aug 20 22:58:12 2014        
(r270249)
+++ stable/10/sys/dev/mps/mps_sas.c     Wed Aug 20 23:09:27 2014        
(r270250)
@@ -115,7 +115,6 @@ static uint8_t op_code_prot[256] = {
 
 MALLOC_DEFINE(M_MPSSAS, "MPSSAS", "MPS SAS memory");
 
-static void mpssas_discovery_timeout(void *data);
 static void mpssas_remove_device(struct mps_softc *, struct mps_command *);
 static void mpssas_remove_complete(struct mps_softc *, struct mps_command *);
 static void mpssas_action(struct cam_sim *sim, union ccb *ccb);
@@ -191,6 +190,16 @@ mpssas_startup_increment(struct mpssas_s
 }
 
 void
+mpssas_release_simq_reinit(struct mpssas_softc *sassc)
+{
+       if (sassc->flags & MPSSAS_QUEUE_FROZEN) {
+               sassc->flags &= ~MPSSAS_QUEUE_FROZEN;
+               xpt_release_simq(sassc->sim, 1);
+               mps_dprint(sassc->sc, MPS_INFO, "Unfreezing SIM queue\n");
+       }
+}
+
+void
 mpssas_startup_decrement(struct mpssas_softc *sassc)
 {
        MPS_FUNCTRACE(sassc->sc);
@@ -902,46 +911,6 @@ mpssas_discovery_end(struct mpssas_softc
 }
 
 static void
-mpssas_discovery_timeout(void *data)
-{
-       struct mpssas_softc *sassc = data;
-       struct mps_softc *sc;
-
-       sc = sassc->sc;
-       MPS_FUNCTRACE(sc);
-
-       mps_lock(sc);
-       mps_dprint(sc, MPS_INFO,
-           "Timeout waiting for discovery, interrupts may not be working!\n");
-       sassc->flags &= ~MPSSAS_DISCOVERY_TIMEOUT_PENDING;
-
-       /* Poll the hardware for events in case interrupts aren't working */
-       mps_intr_locked(sc);
-
-       mps_dprint(sassc->sc, MPS_INFO,
-           "Finished polling after discovery timeout at %d\n", ticks);
-
-       if ((sassc->flags & MPSSAS_IN_DISCOVERY) == 0) {
-               mpssas_discovery_end(sassc);
-       } else {
-               if (sassc->discovery_timeouts < MPSSAS_MAX_DISCOVERY_TIMEOUTS) {
-                       sassc->flags |= MPSSAS_DISCOVERY_TIMEOUT_PENDING;
-                       callout_reset(&sassc->discovery_callout,
-                           MPSSAS_DISCOVERY_TIMEOUT * hz,
-                           mpssas_discovery_timeout, sassc);
-                       sassc->discovery_timeouts++;
-               } else {
-                       mps_dprint(sassc->sc, MPS_FAULT,
-                           "Discovery timed out, continuing.\n");
-                       sassc->flags &= ~MPSSAS_IN_DISCOVERY;
-                       mpssas_discovery_end(sassc);
-               }
-       }
-
-       mps_unlock(sc);
-}
-
-static void
 mpssas_action(struct cam_sim *sim, union ccb *ccb)
 {
        struct mpssas_softc *sassc;
@@ -1005,7 +974,7 @@ mpssas_action(struct cam_sim *sim, union
                    cts->ccb_h.target_id));
                targ = &sassc->targets[cts->ccb_h.target_id];
                if (targ->handle == 0x0) {
-                       mpssas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT);
+                       mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                        break;
                }
 
@@ -1122,6 +1091,14 @@ mpssas_complete_all_commands(struct mps_
                        wakeup(cm);
                        completed = 1;
                }
+
+               if (cm->cm_sc->io_cmds_active != 0) {
+                       cm->cm_sc->io_cmds_active--;
+               } else {
+                       mps_dprint(cm->cm_sc, MPS_INFO, "Warning: "
+                           "io_cmds_active is out of sync - resynching to "
+                           "0\n");
+               }
                
                if ((completed == 0) && (cm->cm_state != MPS_CM_STATE_FREE)) {
                        /* this should never happen, but if it does, log */
@@ -1649,14 +1626,14 @@ mpssas_action_scsiio(struct mpssas_softc
        if (targ->handle == 0x0) {
                mps_dprint(sc, MPS_ERROR, "%s NULL handle for target %u\n", 
                    __func__, csio->ccb_h.target_id);
-               mpssas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT);
+               mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                xpt_done(ccb);
                return;
        }
        if (targ->flags & MPS_TARGET_FLAGS_RAID_COMPONENT) {
                mps_dprint(sc, MPS_ERROR, "%s Raid component no SCSI IO "
                    "supported %u\n", __func__, csio->ccb_h.target_id);
-               mpssas_set_ccbstatus(ccb, CAM_TID_INVALID);
+               mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                xpt_done(ccb);
                return;
        }
@@ -1687,13 +1664,16 @@ mpssas_action_scsiio(struct mpssas_softc
 
        if ((sc->mps_flags & MPS_FLAGS_SHUTDOWN) != 0) {
                mps_dprint(sc, MPS_INFO, "%s shutting down\n", __func__);
-               mpssas_set_ccbstatus(ccb, CAM_TID_INVALID);
+               mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                xpt_done(ccb);
                return;
        }
 
        cm = mps_alloc_command(sc);
-       if (cm == NULL) {
+       if (cm == NULL || (sc->mps_flags & MPS_FLAGS_DIAGRESET)) {
+               if (cm != NULL) {
+                       mps_free_command(sc, cm);
+               }
                if ((sassc->flags & MPSSAS_QUEUE_FROZEN) == 0) {
                        xpt_freeze_simq(sassc->sim, 1);
                        sassc->flags |= MPSSAS_QUEUE_FROZEN;
@@ -2172,6 +2152,18 @@ mpssas_scsiio_complete(struct mps_softc 
                }
        }
 
+       /*
+        * If this is a Start Stop Unit command and it was issued by the driver
+        * during shutdown, decrement the refcount to account for all of the
+        * commands that were sent.  All SSU commands should be completed before
+        * shutdown completes, meaning SSU_refcount will be 0 after SSU_started
+        * is TRUE.
+        */
+       if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) {
+               mps_dprint(sc, MPS_INFO, "Decrementing SSU count.\n");
+               sc->SSU_refcount--;
+       }
+
        /* Take the fast path to completion */
        if (cm->cm_reply == NULL) {
                if (mpssas_get_ccbstatus(ccb) == CAM_REQ_INPROG) {
@@ -3001,7 +2993,7 @@ mpssas_action_smpio(struct mpssas_softc 
                        mps_dprint(sc, MPS_ERROR,
                                   "%s: handle %d does not have a valid "
                                   "parent handle!\n", __func__, targ->handle);
-                       mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
+                       mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                        goto bailout;
                }
 #ifdef OLD_MPS_PROBE
@@ -3012,7 +3004,7 @@ mpssas_action_smpio(struct mpssas_softc 
                        mps_dprint(sc, MPS_ERROR,
                                   "%s: handle %d does not have a valid "
                                   "parent target!\n", __func__, targ->handle);
-                       mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
+                       mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                        goto bailout;
                }
 
@@ -3022,7 +3014,7 @@ mpssas_action_smpio(struct mpssas_softc 
                                   "%s: handle %d parent %d does not "
                                   "have an SMP target!\n", __func__,
                                   targ->handle, parent_target->handle);
-                       mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
+                       mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                        goto bailout;
 
                }
@@ -3035,7 +3027,7 @@ mpssas_action_smpio(struct mpssas_softc 
                                   "%s: handle %d parent %d does not "
                                   "have an SMP target!\n", __func__,
                                   targ->handle, targ->parent_handle);
-                       mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
+                       mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                        goto bailout;
 
                }
@@ -3044,7 +3036,7 @@ mpssas_action_smpio(struct mpssas_softc 
                                   "%s: handle %d parent handle %d does "
                                   "not have a valid SAS address!\n",
                                   __func__, targ->handle, targ->parent_handle);
-                       mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
+                       mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                        goto bailout;
                }
 
@@ -3057,7 +3049,7 @@ mpssas_action_smpio(struct mpssas_softc 
                mps_dprint(sc, MPS_INFO,
                           "%s: unable to find SAS address for handle %d\n",
                           __func__, targ->handle);
-               mpssas_set_ccbstatus(ccb, CAM_REQ_INVALID);
+               mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
                goto bailout;
        }
        mpssas_send_smpcmd(sassc, ccb, sasaddr);
@@ -3368,6 +3360,20 @@ mpssas_check_eedp(struct mps_softc *sc, 
        }
 
        xpt_path_string(local_path, path_str, sizeof(path_str));
+
+       /*
+        * If this is a SATA direct-access end device,
+        * mark it so that a SCSI StartStopUnit command
+        * will be sent to it when the driver is being
+        * shutdown.
+        */
+       if ((cgd.inq_data.device == T_DIRECT) && 
+               (target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) &&
+               ((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
+               MPI2_SAS_DEVICE_INFO_END_DEVICE)) {
+               lun->stop_at_shutdown = TRUE;
+       }
+
        mps_dprint(sc, MPS_INFO, "Sending read cap: path %s handle %d\n",
            path_str, target->handle);
 

Modified: stable/10/sys/dev/mps/mps_sas.h
==============================================================================
--- stable/10/sys/dev/mps/mps_sas.h     Wed Aug 20 22:58:12 2014        
(r270249)
+++ stable/10/sys/dev/mps/mps_sas.h     Wed Aug 20 23:09:27 2014        
(r270250)
@@ -35,6 +35,7 @@ struct mpssas_lun {
        lun_id_t        lun_id;
        uint8_t         eedp_formatted;
        uint32_t        eedp_block_size;
+       uint8_t         stop_at_shutdown;
 };
 
 struct mpssas_target {

Modified: stable/10/sys/dev/mps/mps_sas_lsi.c
==============================================================================
--- stable/10/sys/dev/mps/mps_sas_lsi.c Wed Aug 20 22:58:12 2014        
(r270249)
+++ stable/10/sys/dev/mps/mps_sas_lsi.c Wed Aug 20 23:09:27 2014        
(r270250)
@@ -120,6 +120,9 @@ int mpssas_get_sas_address_for_sata_disk
     u64 *sas_address, u16 handle, u32 device_info);
 static int mpssas_volume_add(struct mps_softc *sc,
     u16 handle);
+static void mpssas_SSU_to_SATA_devices(struct mps_softc *sc);
+static void mpssas_stop_unit_done(struct cam_periph *periph,
+    union ccb *done_ccb);
 
 void
 mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
@@ -910,6 +913,138 @@ out:
 }
 
 /**
+ * mpssas_SSU_to_SATA_devices 
+ * @sc: per adapter object
+ *
+ * Looks through the target list and issues a StartStopUnit SCSI command to 
each
+ * SATA direct-access device.  This helps to ensure that data corruption is
+ * avoided when the system is being shut down.  This must be called after the 
IR
+ * System Shutdown RAID Action is sent if in IR mode.
+ *
+ * Return nothing.
+ */
+static void
+mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
+{
+       struct mpssas_softc *sassc = sc->sassc;
+       union ccb *ccb;
+       path_id_t pathid = cam_sim_path(sassc->sim);
+       target_id_t targetid;
+       struct mpssas_target *target;
+       struct mpssas_lun *lun;
+       char path_str[64];
+       struct timeval cur_time, start_time;
+
+       /*
+        * For each LUN of each target, issue a StartStopUnit command to stop
+        * the device.
+        */
+       sc->SSU_started = TRUE;
+       sc->SSU_refcount = 0;
+       for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
+               target = &sassc->targets[targetid];
+               if (target->handle == 0x0) {
+                       continue;
+               }
+
+               SLIST_FOREACH(lun, &target->luns, lun_link) {
+                       ccb = xpt_alloc_ccb_nowait();
+                       if (ccb == NULL) {
+                               mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB "
+                                   "to stop unit.\n");
+                               return;
+                       }
+
+                       /*
+                        * The stop_at_shutdown flag will be set if this LUN is
+                        * a SATA direct-access end device.
+                        */
+                       if (lun->stop_at_shutdown) {
+                               if (xpt_create_path(&ccb->ccb_h.path,
+                                   xpt_periph, pathid, targetid,
+                                   lun->lun_id) != CAM_REQ_CMP) {
+                                       mps_dprint(sc, MPS_FAULT, "Unable to "
+                                           "create LUN path to stop unit.\n");
+                                       xpt_free_ccb(ccb);
+                                       return;
+                               }
+                               xpt_path_string(ccb->ccb_h.path, path_str,
+                                   sizeof(path_str));
+
+                               mps_dprint(sc, MPS_INFO, "Sending StopUnit: "
+                                   "path %s handle %d\n", path_str,
+                                   target->handle);
+                       
+                               /*
+                                * Issue a START STOP UNIT command for the LUN.
+                                * Increment the SSU counter to be used to
+                                * count the number of required replies.
+                                */
+                               mps_dprint(sc, MPS_INFO, "Incrementing SSU "
+                                   "count\n");
+                               sc->SSU_refcount++;
+                               ccb->ccb_h.target_id =
+                                   xpt_path_target_id(ccb->ccb_h.path);
+                               ccb->ccb_h.target_lun = lun->lun_id;
+                               ccb->ccb_h.ppriv_ptr1 = sassc;
+                               scsi_start_stop(&ccb->csio,
+                                   /*retries*/0,
+                                   mpssas_stop_unit_done,
+                                   MSG_SIMPLE_Q_TAG,
+                                   /*start*/FALSE,
+                                   /*load/eject*/0,
+                                   /*immediate*/FALSE,
+                                   MPS_SENSE_LEN,
+                                   /*timeout*/10000);
+                               xpt_action(ccb);
+                       }
+               }
+       }
+
+       /*
+        * Wait until all of the SSU commands have completed or time has
+        * expired (60 seconds).  pause for 100ms each time through.  If any
+        * command times out, the target will be reset in the SCSI command
+        * timeout routine.
+        */
+       getmicrotime(&start_time);
+       while (sc->SSU_refcount) {
+               pause("mpswait", hz/10);
+               
+               getmicrotime(&cur_time);
+               if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
+                       mps_dprint(sc, MPS_FAULT, "Time has expired waiting "
+                           "for SSU commands to complete.\n");
+                       break;
+               }
+       }
+}
+
+static void
+mpssas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb)
+{
+       struct mpssas_softc *sassc;
+       char path_str[64];
+
+       sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
+
+       xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
+       mps_dprint(sassc->sc, MPS_INFO, "Completing stop unit for %s\n",
+           path_str);
+
+       if (done_ccb == NULL)
+               return;
+
+       /*
+        * Nothing more to do except free the CCB and path.  If the command
+        * timed out, an abort reset, then target reset will be issued during
+        * the SCSI Command process.
+        */
+       xpt_free_path(done_ccb->ccb_h.path);
+       xpt_free_ccb(done_ccb);
+}
+
+/**
  * mpssas_ir_shutdown - IR shutdown notification
  * @sc: per adapter object
  *
@@ -933,7 +1068,7 @@ mpssas_ir_shutdown(struct mps_softc *sc)
 
        /* is IR firmware build loaded? */
        if (!sc->ir_firmware)
-               return;
+               goto out;
 
        /* are there any volumes?  Look at IR target IDs. */
        // TODO-later, this should be looked up in the RAID config structure
@@ -958,11 +1093,11 @@ mpssas_ir_shutdown(struct mps_softc *sc)
        }
 
        if (!found_volume)
-               return;
+               goto out;
 
        if ((cm = mps_alloc_command(sc)) == NULL) {
                printf("%s: command alloc failed\n", __func__);
-               return;
+               goto out;
        }
 
        action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
@@ -978,4 +1113,7 @@ mpssas_ir_shutdown(struct mps_softc *sc)
         */
        if (cm)
                mps_free_command(sc, cm);
+
+out:
+       mpssas_SSU_to_SATA_devices(sc);
 }

Modified: stable/10/sys/dev/mps/mpsvar.h
==============================================================================
--- stable/10/sys/dev/mps/mpsvar.h      Wed Aug 20 22:58:12 2014        
(r270249)
+++ stable/10/sys/dev/mps/mpsvar.h      Wed Aug 20 23:09:27 2014        
(r270250)
@@ -32,7 +32,7 @@
 #ifndef _MPSVAR_H
 #define _MPSVAR_H
 
-#define MPS_DRIVER_VERSION     "16.00.00.00-fbsd"
+#define MPS_DRIVER_VERSION     "19.00.00.00-fbsd"
 
 #define MPS_DB_MAX_WAIT                2500
 
@@ -417,6 +417,10 @@ struct mps_softc {
 
        char                            exclude_ids[80];
        struct timeval                  lastfail;
+
+       /* StartStopUnit command handling at shutdown */
+       uint32_t                        SSU_refcount;
+       uint8_t                         SSU_started;
 };
 
 struct mps_config_params {
@@ -759,6 +763,7 @@ struct mpssas_target * mpssas_find_targe
 void mpssas_realloc_targets(struct mps_softc *sc, int maxtargets);
 struct mps_command * mpssas_alloc_tm(struct mps_softc *sc);
 void mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm);
+void mpssas_release_simq_reinit(struct mpssas_softc *sassc);
 
 SYSCTL_DECL(_hw_mps);
 
_______________________________________________
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