Esempio n. 1
0
static void
isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
{
	struct cam_sim *sim;
	struct ispsoftc *isp;

	sim = (struct cam_sim *)cbarg;
	isp = (struct ispsoftc *) cam_sim_softc(sim);
	switch (code) {
	case AC_LOST_DEVICE:
		if (isp->isp_type & ISP_HA_SCSI) {
			u_int16_t oflags, nflags;
			sdparam *sdp = isp->isp_param;
			int s, tgt = xpt_path_target_id(path);

			s = splcam();
			sdp += cam_sim_bus(sim);
			isp->isp_update |= (1 << cam_sim_bus(sim));

			nflags = DPARM_SAFE_DFLT;
			if (ISP_FW_REVX(isp->isp_fwrev) >=
			    ISP_FW_REV(7, 55, 0)) {
				nflags |= DPARM_NARROW | DPARM_ASYNC;
			}
			oflags = sdp->isp_devparam[tgt].dev_flags;
			sdp->isp_devparam[tgt].dev_flags = nflags;
			sdp->isp_devparam[tgt].dev_update = 1;
			(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
			sdp->isp_devparam[tgt].dev_flags = oflags;
			(void) splx(s);
		}
		break;
	default:
		break;
	}
}
Esempio n. 2
0
/**
 * 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;
	char path_str[64];
	struct timeval cur_time, start_time;

	/*
	 * For 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;
		}

		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 device is
		 * a SATA direct-access end device.
		 */
		if (target->stop_at_shutdown) {
			if (xpt_create_path(&ccb->ccb_h.path,
			    xpt_periph, pathid, targetid,
			    CAM_LUN_WILDCARD) != 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 target.
			 * 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.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;
		}
	}
}