1265236Sken/*-
2265236Sken * Copyright (c) 2009 Yahoo! Inc.
3283990Sslm * Copyright (c) 2011-2015 LSI Corp.
4299962Sslm * Copyright (c) 2013-2016 Avago Technologies
5265236Sken * All rights reserved.
6265236Sken *
7265236Sken * Redistribution and use in source and binary forms, with or without
8265236Sken * modification, are permitted provided that the following conditions
9265236Sken * are met:
10265236Sken * 1. Redistributions of source code must retain the above copyright
11265236Sken *    notice, this list of conditions and the following disclaimer.
12265236Sken * 2. Redistributions in binary form must reproduce the above copyright
13265236Sken *    notice, this list of conditions and the following disclaimer in the
14265236Sken *    documentation and/or other materials provided with the distribution.
15265236Sken *
16265236Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17265236Sken * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18265236Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19265236Sken * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20265236Sken * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21265236Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22265236Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23265236Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24265236Sken * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25265236Sken * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26265236Sken * SUCH DAMAGE.
27283990Sslm *
28283990Sslm * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
29283990Sslm *
30265236Sken */
31265236Sken
32265236Sken#include <sys/cdefs.h>
33265236Sken__FBSDID("$FreeBSD: stable/10/sys/dev/mpr/mpr_sas.c 322661 2017-08-18 15:38:08Z ken $");
34265236Sken
35283990Sslm/* Communications core for Avago Technologies (LSI) MPT3 */
36265236Sken
37265236Sken/* TODO Move headers to mprvar */
38265236Sken#include <sys/types.h>
39265236Sken#include <sys/param.h>
40265236Sken#include <sys/systm.h>
41265236Sken#include <sys/kernel.h>
42265236Sken#include <sys/selinfo.h>
43265236Sken#include <sys/module.h>
44265236Sken#include <sys/bus.h>
45265236Sken#include <sys/conf.h>
46265236Sken#include <sys/bio.h>
47265236Sken#include <sys/malloc.h>
48265236Sken#include <sys/uio.h>
49265236Sken#include <sys/sysctl.h>
50265236Sken#include <sys/endian.h>
51265236Sken#include <sys/queue.h>
52265236Sken#include <sys/kthread.h>
53265236Sken#include <sys/taskqueue.h>
54265236Sken#include <sys/sbuf.h>
55265236Sken
56265236Sken#include <machine/bus.h>
57265236Sken#include <machine/resource.h>
58265236Sken#include <sys/rman.h>
59265236Sken
60265236Sken#include <machine/stdarg.h>
61265236Sken
62265236Sken#include <cam/cam.h>
63265236Sken#include <cam/cam_ccb.h>
64265236Sken#include <cam/cam_debug.h>
65265236Sken#include <cam/cam_sim.h>
66265236Sken#include <cam/cam_xpt_sim.h>
67265236Sken#include <cam/cam_xpt_periph.h>
68265236Sken#include <cam/cam_periph.h>
69265236Sken#include <cam/scsi/scsi_all.h>
70265236Sken#include <cam/scsi/scsi_message.h>
71265236Sken#if __FreeBSD_version >= 900026
72265236Sken#include <cam/scsi/smp_all.h>
73265236Sken#endif
74265236Sken
75319436Sslm#include <dev/nvme/nvme.h>
76319436Sslm
77265236Sken#include <dev/mpr/mpi/mpi2_type.h>
78265236Sken#include <dev/mpr/mpi/mpi2.h>
79265236Sken#include <dev/mpr/mpi/mpi2_ioc.h>
80265236Sken#include <dev/mpr/mpi/mpi2_sas.h>
81319436Sslm#include <dev/mpr/mpi/mpi2_pci.h>
82265236Sken#include <dev/mpr/mpi/mpi2_cnfg.h>
83265236Sken#include <dev/mpr/mpi/mpi2_init.h>
84265236Sken#include <dev/mpr/mpi/mpi2_tool.h>
85265236Sken#include <dev/mpr/mpr_ioctl.h>
86265236Sken#include <dev/mpr/mprvar.h>
87265236Sken#include <dev/mpr/mpr_table.h>
88265236Sken#include <dev/mpr/mpr_sas.h>
89265236Sken
90265236Sken#define MPRSAS_DISCOVERY_TIMEOUT	20
91265236Sken#define MPRSAS_MAX_DISCOVERY_TIMEOUTS	10 /* 200 seconds */
92265236Sken
93265236Sken/*
94265236Sken * static array to check SCSI OpCode for EEDP protection bits
95265236Sken */
96265236Sken#define	PRO_R MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP
97265236Sken#define	PRO_W MPI2_SCSIIO_EEDPFLAGS_INSERT_OP
98265236Sken#define	PRO_V MPI2_SCSIIO_EEDPFLAGS_INSERT_OP
99265236Skenstatic uint8_t op_code_prot[256] = {
100265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102265236Sken	0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
103265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104265236Sken	0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108265236Sken	0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
109265236Sken	0, 0, 0, PRO_W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110265236Sken	0, 0, 0, 0, 0, 0, 0, 0, PRO_R, 0, PRO_W, 0, 0, 0, PRO_W, PRO_V,
111265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115265236Sken	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
116265236Sken};
117265236Sken
118265236SkenMALLOC_DEFINE(M_MPRSAS, "MPRSAS", "MPR SAS memory");
119265236Sken
120265236Skenstatic void mprsas_remove_device(struct mpr_softc *, struct mpr_command *);
121265236Skenstatic void mprsas_remove_complete(struct mpr_softc *, struct mpr_command *);
122265236Skenstatic void mprsas_action(struct cam_sim *sim, union ccb *ccb);
123265236Skenstatic void mprsas_poll(struct cam_sim *sim);
124265236Skenstatic void mprsas_scsiio_timeout(void *data);
125299962Sslmstatic void mprsas_abort_complete(struct mpr_softc *sc, struct mpr_command *cm);
126265236Skenstatic void mprsas_action_scsiio(struct mprsas_softc *, union ccb *);
127265236Skenstatic void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *);
128265236Skenstatic void mprsas_action_resetdev(struct mprsas_softc *, union ccb *);
129299962Sslmstatic void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *);
130283990Sslmstatic int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm,
131265236Sken    struct mpr_command *cm);
132265236Skenstatic void mprsas_async(void *callback_arg, uint32_t code,
133265236Sken    struct cam_path *path, void *arg);
134265236Sken#if (__FreeBSD_version < 901503) || \
135265236Sken    ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006))
136265236Skenstatic void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path,
137265236Sken    struct ccb_getdev *cgd);
138265236Skenstatic void mprsas_read_cap_done(struct cam_periph *periph,
139265236Sken    union ccb *done_ccb);
140265236Sken#endif
141265236Skenstatic int mprsas_send_portenable(struct mpr_softc *sc);
142265236Skenstatic void mprsas_portenable_complete(struct mpr_softc *sc,
143265236Sken    struct mpr_command *cm);
144265236Sken
145265236Sken#if __FreeBSD_version >= 900026
146299962Sslmstatic void mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm);
147299962Sslmstatic void mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb,
148299962Sslm    uint64_t sasaddr);
149283990Sslmstatic void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb);
150283990Sslm#endif //FreeBSD_version >= 900026
151265236Sken
152265236Skenstruct mprsas_target *
153265236Skenmprsas_find_target_by_handle(struct mprsas_softc *sassc, int start,
154265236Sken    uint16_t handle)
155265236Sken{
156265236Sken	struct mprsas_target *target;
157265236Sken	int i;
158265236Sken
159265236Sken	for (i = start; i < sassc->maxtargets; i++) {
160265236Sken		target = &sassc->targets[i];
161265236Sken		if (target->handle == handle)
162265236Sken			return (target);
163265236Sken	}
164265236Sken
165265236Sken	return (NULL);
166265236Sken}
167265236Sken
168265236Sken/* we need to freeze the simq during attach and diag reset, to avoid failing
169265236Sken * commands before device handles have been found by discovery.  Since
170265236Sken * discovery involves reading config pages and possibly sending commands,
171265236Sken * discovery actions may continue even after we receive the end of discovery
172265236Sken * event, so refcount discovery actions instead of assuming we can unfreeze
173265236Sken * the simq when we get the event.
174265236Sken */
175265236Skenvoid
176265236Skenmprsas_startup_increment(struct mprsas_softc *sassc)
177265236Sken{
178265236Sken	MPR_FUNCTRACE(sassc->sc);
179265236Sken
180265236Sken	if ((sassc->flags & MPRSAS_IN_STARTUP) != 0) {
181265236Sken		if (sassc->startup_refcount++ == 0) {
182265236Sken			/* just starting, freeze the simq */
183265236Sken			mpr_dprint(sassc->sc, MPR_INIT,
184265236Sken			    "%s freezing simq\n", __func__);
185266548Sken#if (__FreeBSD_version >= 1000039) || \
186266548Sken    ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502))
187265236Sken			xpt_hold_boot();
188265236Sken#endif
189265236Sken			xpt_freeze_simq(sassc->sim, 1);
190265236Sken		}
191265236Sken		mpr_dprint(sassc->sc, MPR_INIT, "%s refcount %u\n", __func__,
192265236Sken		    sassc->startup_refcount);
193265236Sken	}
194265236Sken}
195265236Sken
196265236Skenvoid
197265236Skenmprsas_release_simq_reinit(struct mprsas_softc *sassc)
198265236Sken{
199265236Sken	if (sassc->flags & MPRSAS_QUEUE_FROZEN) {
200265236Sken		sassc->flags &= ~MPRSAS_QUEUE_FROZEN;
201265236Sken		xpt_release_simq(sassc->sim, 1);
202265236Sken		mpr_dprint(sassc->sc, MPR_INFO, "Unfreezing SIM queue\n");
203265236Sken	}
204265236Sken}
205265236Sken
206265236Skenvoid
207265236Skenmprsas_startup_decrement(struct mprsas_softc *sassc)
208265236Sken{
209265236Sken	MPR_FUNCTRACE(sassc->sc);
210265236Sken
211265236Sken	if ((sassc->flags & MPRSAS_IN_STARTUP) != 0) {
212265236Sken		if (--sassc->startup_refcount == 0) {
213265236Sken			/* finished all discovery-related actions, release
214265236Sken			 * the simq and rescan for the latest topology.
215265236Sken			 */
216265236Sken			mpr_dprint(sassc->sc, MPR_INIT,
217265236Sken			    "%s releasing simq\n", __func__);
218265236Sken			sassc->flags &= ~MPRSAS_IN_STARTUP;
219265236Sken			xpt_release_simq(sassc->sim, 1);
220266548Sken#if (__FreeBSD_version >= 1000039) || \
221266548Sken    ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502))
222265236Sken			xpt_release_boot();
223265236Sken#else
224265236Sken			mprsas_rescan_target(sassc->sc, NULL);
225265236Sken#endif
226265236Sken		}
227265236Sken		mpr_dprint(sassc->sc, MPR_INIT, "%s refcount %u\n", __func__,
228265236Sken		    sassc->startup_refcount);
229265236Sken	}
230265236Sken}
231265236Sken
232283990Sslm/* The firmware requires us to stop sending commands when we're doing task
233265236Sken * management, so refcount the TMs and keep the simq frozen when any are in
234265236Sken * use.
235265236Sken */
236265236Skenstruct mpr_command *
237265236Skenmprsas_alloc_tm(struct mpr_softc *sc)
238265236Sken{
239265236Sken	struct mpr_command *tm;
240265236Sken
241265236Sken	MPR_FUNCTRACE(sc);
242265236Sken	tm = mpr_alloc_high_priority_command(sc);
243265236Sken	return tm;
244265236Sken}
245265236Sken
246265236Skenvoid
247265236Skenmprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm)
248265236Sken{
249299962Sslm	int target_id = 0xFFFFFFFF;
250299962Sslm
251283990Sslm	MPR_FUNCTRACE(sc);
252265236Sken	if (tm == NULL)
253265236Sken		return;
254265236Sken
255283990Sslm	/*
256283990Sslm	 * For TM's the devq is frozen for the device.  Unfreeze it here and
257283990Sslm	 * free the resources used for freezing the devq.  Must clear the
258283990Sslm	 * INRESET flag as well or scsi I/O will not work.
259265236Sken	 */
260283990Sslm	if (tm->cm_targ != NULL) {
261283990Sslm		tm->cm_targ->flags &= ~MPRSAS_TARGET_INRESET;
262299962Sslm		target_id = tm->cm_targ->tid;
263265236Sken	}
264283990Sslm	if (tm->cm_ccb) {
265283990Sslm		mpr_dprint(sc, MPR_INFO, "Unfreezing devq for target ID %d\n",
266299962Sslm		    target_id);
267283990Sslm		xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE);
268283990Sslm		xpt_free_path(tm->cm_ccb->ccb_h.path);
269283990Sslm		xpt_free_ccb(tm->cm_ccb);
270283990Sslm	}
271265236Sken
272265236Sken	mpr_free_high_priority_command(sc, tm);
273265236Sken}
274265236Sken
275265236Skenvoid
276265236Skenmprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ)
277265236Sken{
278265236Sken	struct mprsas_softc *sassc = sc->sassc;
279265236Sken	path_id_t pathid;
280265236Sken	target_id_t targetid;
281265236Sken	union ccb *ccb;
282265236Sken
283265236Sken	MPR_FUNCTRACE(sc);
284265236Sken	pathid = cam_sim_path(sassc->sim);
285265236Sken	if (targ == NULL)
286265236Sken		targetid = CAM_TARGET_WILDCARD;
287265236Sken	else
288265236Sken		targetid = targ - sassc->targets;
289265236Sken
290265236Sken	/*
291265236Sken	 * Allocate a CCB and schedule a rescan.
292265236Sken	 */
293265236Sken	ccb = xpt_alloc_ccb_nowait();
294265236Sken	if (ccb == NULL) {
295265236Sken		mpr_dprint(sc, MPR_ERROR, "unable to alloc CCB for rescan\n");
296265236Sken		return;
297265236Sken	}
298265236Sken
299283990Sslm	if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid,
300283990Sslm	    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
301265236Sken		mpr_dprint(sc, MPR_ERROR, "unable to create path for rescan\n");
302265236Sken		xpt_free_ccb(ccb);
303265236Sken		return;
304265236Sken	}
305265236Sken
306265236Sken	if (targetid == CAM_TARGET_WILDCARD)
307265236Sken		ccb->ccb_h.func_code = XPT_SCAN_BUS;
308265236Sken	else
309265236Sken		ccb->ccb_h.func_code = XPT_SCAN_TGT;
310265236Sken
311265236Sken	mpr_dprint(sc, MPR_TRACE, "%s targetid %u\n", __func__, targetid);
312265236Sken	xpt_rescan(ccb);
313265236Sken}
314265236Sken
315265236Skenstatic void
316265236Skenmprsas_log_command(struct mpr_command *cm, u_int level, const char *fmt, ...)
317265236Sken{
318265236Sken	struct sbuf sb;
319265236Sken	va_list ap;
320265236Sken	char str[192];
321265236Sken	char path_str[64];
322265236Sken
323265236Sken	if (cm == NULL)
324265236Sken		return;
325265236Sken
326265236Sken	/* No need to be in here if debugging isn't enabled */
327265236Sken	if ((cm->cm_sc->mpr_debug & level) == 0)
328265236Sken		return;
329265236Sken
330265236Sken	sbuf_new(&sb, str, sizeof(str), 0);
331265236Sken
332265236Sken	va_start(ap, fmt);
333265236Sken
334265236Sken	if (cm->cm_ccb != NULL) {
335265236Sken		xpt_path_string(cm->cm_ccb->csio.ccb_h.path, path_str,
336265236Sken		    sizeof(path_str));
337265236Sken		sbuf_cat(&sb, path_str);
338265236Sken		if (cm->cm_ccb->ccb_h.func_code == XPT_SCSI_IO) {
339265236Sken			scsi_command_string(&cm->cm_ccb->csio, &sb);
340265236Sken			sbuf_printf(&sb, "length %d ",
341265236Sken			    cm->cm_ccb->csio.dxfer_len);
342265236Sken		}
343265236Sken	} else {
344265236Sken		sbuf_printf(&sb, "(noperiph:%s%d:%u:%u:%u): ",
345265236Sken		    cam_sim_name(cm->cm_sc->sassc->sim),
346265236Sken		    cam_sim_unit(cm->cm_sc->sassc->sim),
347265236Sken		    cam_sim_bus(cm->cm_sc->sassc->sim),
348265236Sken		    cm->cm_targ ? cm->cm_targ->tid : 0xFFFFFFFF,
349265236Sken		    cm->cm_lun);
350265236Sken	}
351265236Sken
352265236Sken	sbuf_printf(&sb, "SMID %u ", cm->cm_desc.Default.SMID);
353265236Sken	sbuf_vprintf(&sb, fmt, ap);
354265236Sken	sbuf_finish(&sb);
355319436Sslm	mpr_print_field(cm->cm_sc, "%s", sbuf_data(&sb));
356265236Sken
357265236Sken	va_end(ap);
358265236Sken}
359265236Sken
360265236Skenstatic void
361265236Skenmprsas_remove_volume(struct mpr_softc *sc, struct mpr_command *tm)
362265236Sken{
363265236Sken	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
364265236Sken	struct mprsas_target *targ;
365265236Sken	uint16_t handle;
366265236Sken
367265236Sken	MPR_FUNCTRACE(sc);
368265236Sken
369265236Sken	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
370265236Sken	handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
371265236Sken	targ = tm->cm_targ;
372265236Sken
373265236Sken	if (reply == NULL) {
374265236Sken		/* XXX retry the remove after the diag reset completes? */
375265236Sken		mpr_dprint(sc, MPR_FAULT, "%s NULL reply resetting device "
376265236Sken		    "0x%04x\n", __func__, handle);
377265236Sken		mprsas_free_tm(sc, tm);
378265236Sken		return;
379265236Sken	}
380265236Sken
381299962Sslm	if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
382299962Sslm	    MPI2_IOCSTATUS_SUCCESS) {
383299962Sslm		mpr_dprint(sc, MPR_ERROR, "IOCStatus = 0x%x while resetting "
384299962Sslm		    "device 0x%x\n", le16toh(reply->IOCStatus), handle);
385265236Sken	}
386265236Sken
387265236Sken	mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n",
388299962Sslm	    le32toh(reply->TerminationCount));
389265236Sken	mpr_free_reply(sc, tm->cm_reply_data);
390265236Sken	tm->cm_reply = NULL;	/* Ensures the reply won't get re-freed */
391265236Sken
392265236Sken	mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n",
393265236Sken	    targ->tid, handle);
394265236Sken
395265236Sken	/*
396265236Sken	 * Don't clear target if remove fails because things will get confusing.
397265236Sken	 * Leave the devname and sasaddr intact so that we know to avoid reusing
398265236Sken	 * this target id if possible, and so we can assign the same target id
399265236Sken	 * to this device if it comes back in the future.
400265236Sken	 */
401299962Sslm	if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) ==
402299962Sslm	    MPI2_IOCSTATUS_SUCCESS) {
403265236Sken		targ = tm->cm_targ;
404265236Sken		targ->handle = 0x0;
405265236Sken		targ->encl_handle = 0x0;
406265236Sken		targ->encl_level_valid = 0x0;
407265236Sken		targ->encl_level = 0x0;
408265236Sken		targ->connector_name[0] = ' ';
409265236Sken		targ->connector_name[1] = ' ';
410265236Sken		targ->connector_name[2] = ' ';
411265236Sken		targ->connector_name[3] = ' ';
412265236Sken		targ->encl_slot = 0x0;
413265236Sken		targ->exp_dev_handle = 0x0;
414265236Sken		targ->phy_num = 0x0;
415265236Sken		targ->linkrate = 0x0;
416265236Sken		targ->devinfo = 0x0;
417265236Sken		targ->flags = 0x0;
418265236Sken		targ->scsi_req_desc_type = 0;
419265236Sken	}
420265236Sken
421265236Sken	mprsas_free_tm(sc, tm);
422265236Sken}
423265236Sken
424265236Sken
425265236Sken/*
426265236Sken * No Need to call "MPI2_SAS_OP_REMOVE_DEVICE" For Volume removal.
427265236Sken * Otherwise Volume Delete is same as Bare Drive Removal.
428265236Sken */
429265236Skenvoid
430265236Skenmprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle)
431265236Sken{
432265236Sken	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
433265236Sken	struct mpr_softc *sc;
434265236Sken	struct mpr_command *cm;
435265236Sken	struct mprsas_target *targ = NULL;
436265236Sken
437265236Sken	MPR_FUNCTRACE(sassc->sc);
438265236Sken	sc = sassc->sc;
439265236Sken
440265236Sken	targ = mprsas_find_target_by_handle(sassc, 0, handle);
441265236Sken	if (targ == NULL) {
442265236Sken		/* FIXME: what is the action? */
443265236Sken		/* We don't know about this device? */
444265236Sken		mpr_dprint(sc, MPR_ERROR,
445265236Sken		   "%s %d : invalid handle 0x%x \n", __func__,__LINE__, handle);
446265236Sken		return;
447265236Sken	}
448265236Sken
449265236Sken	targ->flags |= MPRSAS_TARGET_INREMOVAL;
450265236Sken
451265236Sken	cm = mprsas_alloc_tm(sc);
452265236Sken	if (cm == NULL) {
453265236Sken		mpr_dprint(sc, MPR_ERROR,
454265236Sken		    "%s: command alloc failure\n", __func__);
455265236Sken		return;
456265236Sken	}
457265236Sken
458265236Sken	mprsas_rescan_target(sc, targ);
459265236Sken
460265236Sken	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
461265236Sken	req->DevHandle = targ->handle;
462265236Sken	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
463265236Sken	req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
464265236Sken
465265236Sken	/* SAS Hard Link Reset / SATA Link Reset */
466265236Sken	req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
467265236Sken
468265236Sken	cm->cm_targ = targ;
469265236Sken	cm->cm_data = NULL;
470265236Sken	cm->cm_desc.HighPriority.RequestFlags =
471265236Sken	    MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
472265236Sken	cm->cm_complete = mprsas_remove_volume;
473265236Sken	cm->cm_complete_data = (void *)(uintptr_t)handle;
474283990Sslm
475283990Sslm	mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n",
476283990Sslm	    __func__, targ->tid);
477283990Sslm	mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
478283990Sslm
479265236Sken	mpr_map_command(sc, cm);
480265236Sken}
481265236Sken
482265236Sken/*
483319436Sslm * The firmware performs debounce on the link to avoid transient link errors
484319436Sslm * and false removals.  When it does decide that link has been lost and a
485319436Sslm * device needs to go away, it expects that the host will perform a target reset
486319436Sslm * and then an op remove.  The reset has the side-effect of aborting any
487319436Sslm * outstanding requests for the device, which is required for the op-remove to
488319436Sslm * succeed.  It's not clear if the host should check for the device coming back
489319436Sslm * alive after the reset.
490265236Sken */
491265236Skenvoid
492265236Skenmprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle)
493265236Sken{
494265236Sken	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
495265236Sken	struct mpr_softc *sc;
496265236Sken	struct mpr_command *cm;
497265236Sken	struct mprsas_target *targ = NULL;
498265236Sken
499265236Sken	MPR_FUNCTRACE(sassc->sc);
500265236Sken
501265236Sken	sc = sassc->sc;
502265236Sken
503265236Sken	targ = mprsas_find_target_by_handle(sassc, 0, handle);
504265236Sken	if (targ == NULL) {
505265236Sken		/* FIXME: what is the action? */
506265236Sken		/* We don't know about this device? */
507265236Sken		mpr_dprint(sc, MPR_ERROR, "%s : invalid handle 0x%x \n",
508265236Sken		    __func__, handle);
509265236Sken		return;
510265236Sken	}
511265236Sken
512265236Sken	targ->flags |= MPRSAS_TARGET_INREMOVAL;
513265236Sken
514265236Sken	cm = mprsas_alloc_tm(sc);
515265236Sken	if (cm == NULL) {
516265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: command alloc failure\n",
517265236Sken		    __func__);
518265236Sken		return;
519265236Sken	}
520265236Sken
521265236Sken	mprsas_rescan_target(sc, targ);
522265236Sken
523265236Sken	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
524265236Sken	memset(req, 0, sizeof(*req));
525265236Sken	req->DevHandle = htole16(targ->handle);
526265236Sken	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
527265236Sken	req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
528265236Sken
529265236Sken	/* SAS Hard Link Reset / SATA Link Reset */
530265236Sken	req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
531265236Sken
532265236Sken	cm->cm_targ = targ;
533265236Sken	cm->cm_data = NULL;
534265236Sken	cm->cm_desc.HighPriority.RequestFlags =
535265236Sken	    MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
536265236Sken	cm->cm_complete = mprsas_remove_device;
537265236Sken	cm->cm_complete_data = (void *)(uintptr_t)handle;
538283990Sslm
539283990Sslm	mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n",
540283990Sslm	    __func__, targ->tid);
541283990Sslm	mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
542283990Sslm
543265236Sken	mpr_map_command(sc, cm);
544265236Sken}
545265236Sken
546265236Skenstatic void
547265236Skenmprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm)
548265236Sken{
549265236Sken	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
550265236Sken	MPI2_SAS_IOUNIT_CONTROL_REQUEST *req;
551265236Sken	struct mprsas_target *targ;
552265236Sken	struct mpr_command *next_cm;
553265236Sken	uint16_t handle;
554265236Sken
555265236Sken	MPR_FUNCTRACE(sc);
556265236Sken
557265236Sken	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
558265236Sken	handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
559265236Sken	targ = tm->cm_targ;
560265236Sken
561265236Sken	/*
562265236Sken	 * Currently there should be no way we can hit this case.  It only
563265236Sken	 * happens when we have a failure to allocate chain frames, and
564265236Sken	 * task management commands don't have S/G lists.
565265236Sken	 */
566265236Sken	if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
567265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for remove of "
568265236Sken		    "handle %#04x! This should not happen!\n", __func__,
569265236Sken		    tm->cm_flags, handle);
570265236Sken	}
571265236Sken
572265236Sken	if (reply == NULL) {
573265236Sken		/* XXX retry the remove after the diag reset completes? */
574265236Sken		mpr_dprint(sc, MPR_FAULT, "%s NULL reply resetting device "
575265236Sken		    "0x%04x\n", __func__, handle);
576265236Sken		mprsas_free_tm(sc, tm);
577265236Sken		return;
578265236Sken	}
579265236Sken
580299962Sslm	if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
581299962Sslm	    MPI2_IOCSTATUS_SUCCESS) {
582299962Sslm		mpr_dprint(sc, MPR_ERROR, "IOCStatus = 0x%x while resetting "
583265236Sken		    "device 0x%x\n", le16toh(reply->IOCStatus), handle);
584265236Sken	}
585265236Sken
586265236Sken	mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n",
587265236Sken	    le32toh(reply->TerminationCount));
588265236Sken	mpr_free_reply(sc, tm->cm_reply_data);
589265236Sken	tm->cm_reply = NULL;	/* Ensures the reply won't get re-freed */
590265236Sken
591265236Sken	/* Reuse the existing command */
592265236Sken	req = (MPI2_SAS_IOUNIT_CONTROL_REQUEST *)tm->cm_req;
593265236Sken	memset(req, 0, sizeof(*req));
594265236Sken	req->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
595265236Sken	req->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
596265236Sken	req->DevHandle = htole16(handle);
597265236Sken	tm->cm_data = NULL;
598265236Sken	tm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
599265236Sken	tm->cm_complete = mprsas_remove_complete;
600265236Sken	tm->cm_complete_data = (void *)(uintptr_t)handle;
601265236Sken
602265236Sken	mpr_map_command(sc, tm);
603265236Sken
604283990Sslm	mpr_dprint(sc, MPR_INFO, "clearing target %u handle 0x%04x\n",
605265236Sken	    targ->tid, handle);
606265236Sken	if (targ->encl_level_valid) {
607283990Sslm		mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, "
608265236Sken		    "connector name (%4s)\n", targ->encl_level, targ->encl_slot,
609265236Sken		    targ->connector_name);
610265236Sken	}
611265236Sken	TAILQ_FOREACH_SAFE(tm, &targ->commands, cm_link, next_cm) {
612265236Sken		union ccb *ccb;
613265236Sken
614265236Sken		mpr_dprint(sc, MPR_XINFO, "Completing missed command %p\n", tm);
615265236Sken		ccb = tm->cm_complete_data;
616283990Sslm		mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
617265236Sken		mprsas_scsiio_complete(sc, tm);
618265236Sken	}
619265236Sken}
620265236Sken
621265236Skenstatic void
622265236Skenmprsas_remove_complete(struct mpr_softc *sc, struct mpr_command *tm)
623265236Sken{
624265236Sken	MPI2_SAS_IOUNIT_CONTROL_REPLY *reply;
625265236Sken	uint16_t handle;
626265236Sken	struct mprsas_target *targ;
627265236Sken	struct mprsas_lun *lun;
628265236Sken
629265236Sken	MPR_FUNCTRACE(sc);
630265236Sken
631265236Sken	reply = (MPI2_SAS_IOUNIT_CONTROL_REPLY *)tm->cm_reply;
632265236Sken	handle = (uint16_t)(uintptr_t)tm->cm_complete_data;
633265236Sken
634265236Sken	/*
635265236Sken	 * Currently there should be no way we can hit this case.  It only
636265236Sken	 * happens when we have a failure to allocate chain frames, and
637265236Sken	 * task management commands don't have S/G lists.
638265236Sken	 */
639265236Sken	if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
640265236Sken		mpr_dprint(sc, MPR_XINFO, "%s: cm_flags = %#x for remove of "
641265236Sken		    "handle %#04x! This should not happen!\n", __func__,
642265236Sken		    tm->cm_flags, handle);
643265236Sken		mprsas_free_tm(sc, tm);
644265236Sken		return;
645265236Sken	}
646265236Sken
647265236Sken	if (reply == NULL) {
648265236Sken		/* most likely a chip reset */
649265236Sken		mpr_dprint(sc, MPR_FAULT, "%s NULL reply removing device "
650265236Sken		    "0x%04x\n", __func__, handle);
651265236Sken		mprsas_free_tm(sc, tm);
652265236Sken		return;
653265236Sken	}
654265236Sken
655265236Sken	mpr_dprint(sc, MPR_XINFO, "%s on handle 0x%04x, IOCStatus= 0x%x\n",
656265236Sken	    __func__, handle, le16toh(reply->IOCStatus));
657265236Sken
658265236Sken	/*
659265236Sken	 * Don't clear target if remove fails because things will get confusing.
660265236Sken	 * Leave the devname and sasaddr intact so that we know to avoid reusing
661265236Sken	 * this target id if possible, and so we can assign the same target id
662265236Sken	 * to this device if it comes back in the future.
663265236Sken	 */
664299962Sslm	if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) ==
665299962Sslm	    MPI2_IOCSTATUS_SUCCESS) {
666265236Sken		targ = tm->cm_targ;
667265236Sken		targ->handle = 0x0;
668265236Sken		targ->encl_handle = 0x0;
669265236Sken		targ->encl_level_valid = 0x0;
670265236Sken		targ->encl_level = 0x0;
671265236Sken		targ->connector_name[0] = ' ';
672265236Sken		targ->connector_name[1] = ' ';
673265236Sken		targ->connector_name[2] = ' ';
674265236Sken		targ->connector_name[3] = ' ';
675265236Sken		targ->encl_slot = 0x0;
676265236Sken		targ->exp_dev_handle = 0x0;
677265236Sken		targ->phy_num = 0x0;
678265236Sken		targ->linkrate = 0x0;
679265236Sken		targ->devinfo = 0x0;
680265236Sken		targ->flags = 0x0;
681265236Sken		targ->scsi_req_desc_type = 0;
682265236Sken
683265236Sken		while (!SLIST_EMPTY(&targ->luns)) {
684265236Sken			lun = SLIST_FIRST(&targ->luns);
685265236Sken			SLIST_REMOVE_HEAD(&targ->luns, lun_link);
686265236Sken			free(lun, M_MPR);
687265236Sken		}
688265236Sken	}
689265236Sken
690265236Sken	mprsas_free_tm(sc, tm);
691265236Sken}
692265236Sken
693265236Skenstatic int
694265236Skenmprsas_register_events(struct mpr_softc *sc)
695265236Sken{
696265236Sken	uint8_t events[16];
697265236Sken
698265236Sken	bzero(events, 16);
699265236Sken	setbit(events, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
700265236Sken	setbit(events, MPI2_EVENT_SAS_DISCOVERY);
701265236Sken	setbit(events, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
702265236Sken	setbit(events, MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE);
703265236Sken	setbit(events, MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW);
704265236Sken	setbit(events, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
705265236Sken	setbit(events, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
706265236Sken	setbit(events, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
707265236Sken	setbit(events, MPI2_EVENT_IR_VOLUME);
708265236Sken	setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK);
709265236Sken	setbit(events, MPI2_EVENT_IR_OPERATION_STATUS);
710265236Sken	setbit(events, MPI2_EVENT_TEMP_THRESHOLD);
711319436Sslm	if (sc->facts->MsgVersion >= MPI2_VERSION_02_06) {
712319436Sslm		setbit(events, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
713319436Sslm		if (sc->mpr_flags & MPR_FLAGS_GEN35_IOC) {
714319436Sslm			setbit(events, MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE);
715319436Sslm			setbit(events, MPI2_EVENT_PCIE_ENUMERATION);
716319436Sslm			setbit(events, MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST);
717319436Sslm		}
718319436Sslm	}
719265236Sken
720265236Sken	mpr_register_events(sc, events, mprsas_evt_handler, NULL,
721265236Sken	    &sc->sassc->mprsas_eh);
722265236Sken
723265236Sken	return (0);
724265236Sken}
725265236Sken
726265236Skenint
727265236Skenmpr_attach_sas(struct mpr_softc *sc)
728265236Sken{
729265236Sken	struct mprsas_softc *sassc;
730265236Sken	cam_status status;
731265236Sken	int unit, error = 0;
732265236Sken
733265236Sken	MPR_FUNCTRACE(sc);
734265236Sken
735265236Sken	sassc = malloc(sizeof(struct mprsas_softc), M_MPR, M_WAITOK|M_ZERO);
736265236Sken	if (!sassc) {
737265236Sken		device_printf(sc->mpr_dev, "Cannot allocate memory %s %d\n",
738265236Sken		    __func__, __LINE__);
739265236Sken		return (ENOMEM);
740265236Sken	}
741265236Sken
742265236Sken	/*
743283990Sslm	 * XXX MaxTargets could change during a reinit.  Since we don't
744265236Sken	 * resize the targets[] array during such an event, cache the value
745265236Sken	 * of MaxTargets here so that we don't get into trouble later.  This
746265236Sken	 * should move into the reinit logic.
747265236Sken	 */
748319445Sslm	sassc->maxtargets = sc->facts->MaxTargets + sc->facts->MaxVolumes;
749265236Sken	sassc->targets = malloc(sizeof(struct mprsas_target) *
750265236Sken	    sassc->maxtargets, M_MPR, M_WAITOK|M_ZERO);
751265236Sken	if (!sassc->targets) {
752265236Sken		device_printf(sc->mpr_dev, "Cannot allocate memory %s %d\n",
753265236Sken		    __func__, __LINE__);
754265236Sken		free(sassc, M_MPR);
755265236Sken		return (ENOMEM);
756265236Sken	}
757265236Sken	sc->sassc = sassc;
758265236Sken	sassc->sc = sc;
759265236Sken
760265236Sken	if ((sassc->devq = cam_simq_alloc(sc->num_reqs)) == NULL) {
761265236Sken		mpr_dprint(sc, MPR_ERROR, "Cannot allocate SIMQ\n");
762265236Sken		error = ENOMEM;
763265236Sken		goto out;
764265236Sken	}
765265236Sken
766265236Sken	unit = device_get_unit(sc->mpr_dev);
767265236Sken	sassc->sim = cam_sim_alloc(mprsas_action, mprsas_poll, "mpr", sassc,
768265236Sken	    unit, &sc->mpr_mtx, sc->num_reqs, sc->num_reqs, sassc->devq);
769265236Sken	if (sassc->sim == NULL) {
770265236Sken		mpr_dprint(sc, MPR_ERROR, "Cannot allocate SIM\n");
771265236Sken		error = EINVAL;
772265236Sken		goto out;
773265236Sken	}
774265236Sken
775265236Sken	TAILQ_INIT(&sassc->ev_queue);
776265236Sken
777265236Sken	/* Initialize taskqueue for Event Handling */
778265236Sken	TASK_INIT(&sassc->ev_task, 0, mprsas_firmware_event_work, sc);
779265236Sken	sassc->ev_tq = taskqueue_create("mpr_taskq", M_NOWAIT | M_ZERO,
780265236Sken	    taskqueue_thread_enqueue, &sassc->ev_tq);
781297700Smav	taskqueue_start_threads(&sassc->ev_tq, 1, PRIBIO, "%s taskq",
782265236Sken	    device_get_nameunit(sc->mpr_dev));
783265236Sken
784265236Sken	mpr_lock(sc);
785265236Sken
786265236Sken	/*
787265236Sken	 * XXX There should be a bus for every port on the adapter, but since
788265236Sken	 * we're just going to fake the topology for now, we'll pretend that
789265236Sken	 * everything is just a target on a single bus.
790265236Sken	 */
791265236Sken	if ((error = xpt_bus_register(sassc->sim, sc->mpr_dev, 0)) != 0) {
792265236Sken		mpr_dprint(sc, MPR_ERROR, "Error %d registering SCSI bus\n",
793265236Sken		    error);
794265236Sken		mpr_unlock(sc);
795265236Sken		goto out;
796265236Sken	}
797265236Sken
798265236Sken	/*
799283990Sslm	 * Assume that discovery events will start right away.
800265236Sken	 *
801265236Sken	 * Hold off boot until discovery is complete.
802265236Sken	 */
803265236Sken	sassc->flags |= MPRSAS_IN_STARTUP | MPRSAS_IN_DISCOVERY;
804265236Sken	sc->sassc->startup_refcount = 0;
805265236Sken	mprsas_startup_increment(sassc);
806265236Sken
807283990Sslm	callout_init(&sassc->discovery_callout, 1 /*mpsafe*/);
808265236Sken
809265236Sken	/*
810265236Sken	 * Register for async events so we can determine the EEDP
811265236Sken	 * capabilities of devices.
812265236Sken	 */
813265236Sken	status = xpt_create_path(&sassc->path, /*periph*/NULL,
814265236Sken	    cam_sim_path(sc->sassc->sim), CAM_TARGET_WILDCARD,
815265236Sken	    CAM_LUN_WILDCARD);
816265236Sken	if (status != CAM_REQ_CMP) {
817265236Sken		mpr_printf(sc, "Error %#x creating sim path\n", status);
818265236Sken		sassc->path = NULL;
819265236Sken	} else {
820265236Sken		int event;
821265236Sken
822265236Sken#if (__FreeBSD_version >= 1000006) || \
823265236Sken    ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000))
824265236Sken		event = AC_ADVINFO_CHANGED | AC_FOUND_DEVICE;
825265236Sken#else
826265236Sken		event = AC_FOUND_DEVICE;
827265236Sken#endif
828265730Sken
829265730Sken		/*
830265730Sken		 * Prior to the CAM locking improvements, we can't call
831265730Sken		 * xpt_register_async() with a particular path specified.
832265730Sken		 *
833265730Sken		 * If a path isn't specified, xpt_register_async() will
834265730Sken		 * generate a wildcard path and acquire the XPT lock while
835265730Sken		 * it calls xpt_action() to execute the XPT_SASYNC_CB CCB.
836265730Sken		 * It will then drop the XPT lock once that is done.
837265730Sken		 *
838265730Sken		 * If a path is specified for xpt_register_async(), it will
839265730Sken		 * not acquire and drop the XPT lock around the call to
840265730Sken		 * xpt_action().  xpt_action() asserts that the caller
841265730Sken		 * holds the SIM lock, so the SIM lock has to be held when
842265730Sken		 * calling xpt_register_async() when the path is specified.
843265730Sken		 *
844265730Sken		 * But xpt_register_async calls xpt_for_all_devices(),
845265730Sken		 * which calls xptbustraverse(), which will acquire each
846265730Sken		 * SIM lock.  When it traverses our particular bus, it will
847265730Sken		 * necessarily acquire the SIM lock, which will lead to a
848265730Sken		 * recursive lock acquisition.
849265730Sken		 *
850265730Sken		 * The CAM locking changes fix this problem by acquiring
851265730Sken		 * the XPT topology lock around bus traversal in
852265730Sken		 * xptbustraverse(), so the caller can hold the SIM lock
853265730Sken		 * and it does not cause a recursive lock acquisition.
854265730Sken		 *
855265730Sken		 * These __FreeBSD_version values are approximate, especially
856265730Sken		 * for stable/10, which is two months later than the actual
857265730Sken		 * change.
858265730Sken		 */
859265730Sken
860265730Sken#if (__FreeBSD_version < 1000703) || \
861265730Sken    ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002))
862265730Sken		mpr_unlock(sc);
863265236Sken		status = xpt_register_async(event, mprsas_async, sc,
864265730Sken					    NULL);
865265730Sken		mpr_lock(sc);
866265730Sken#else
867265730Sken		status = xpt_register_async(event, mprsas_async, sc,
868265236Sken					    sassc->path);
869265730Sken#endif
870265730Sken
871265236Sken		if (status != CAM_REQ_CMP) {
872265236Sken			mpr_dprint(sc, MPR_ERROR,
873265236Sken			    "Error %#x registering async handler for "
874265236Sken			    "AC_ADVINFO_CHANGED events\n", status);
875265236Sken			xpt_free_path(sassc->path);
876265236Sken			sassc->path = NULL;
877265236Sken		}
878265236Sken	}
879265236Sken	if (status != CAM_REQ_CMP) {
880265236Sken		/*
881265236Sken		 * EEDP use is the exception, not the rule.
882265236Sken		 * Warn the user, but do not fail to attach.
883265236Sken		 */
884265236Sken		mpr_printf(sc, "EEDP capabilities disabled.\n");
885265236Sken	}
886265236Sken
887265236Sken	mpr_unlock(sc);
888265236Sken
889265236Sken	mprsas_register_events(sc);
890265236Skenout:
891265236Sken	if (error)
892265236Sken		mpr_detach_sas(sc);
893265236Sken	return (error);
894265236Sken}
895265236Sken
896265236Skenint
897265236Skenmpr_detach_sas(struct mpr_softc *sc)
898265236Sken{
899265236Sken	struct mprsas_softc *sassc;
900265236Sken	struct mprsas_lun *lun, *lun_tmp;
901265236Sken	struct mprsas_target *targ;
902265236Sken	int i;
903265236Sken
904265236Sken	MPR_FUNCTRACE(sc);
905265236Sken
906265236Sken	if (sc->sassc == NULL)
907265236Sken		return (0);
908265236Sken
909265236Sken	sassc = sc->sassc;
910265236Sken	mpr_deregister_events(sc, sassc->mprsas_eh);
911265236Sken
912265236Sken	/*
913265236Sken	 * Drain and free the event handling taskqueue with the lock
914265236Sken	 * unheld so that any parallel processing tasks drain properly
915265236Sken	 * without deadlocking.
916265236Sken	 */
917265236Sken	if (sassc->ev_tq != NULL)
918265236Sken		taskqueue_free(sassc->ev_tq);
919265236Sken
920265236Sken	/* Make sure CAM doesn't wedge if we had to bail out early. */
921265236Sken	mpr_lock(sc);
922265236Sken
923265236Sken	/* Deregister our async handler */
924265236Sken	if (sassc->path != NULL) {
925265236Sken		xpt_register_async(0, mprsas_async, sc, sassc->path);
926265236Sken		xpt_free_path(sassc->path);
927265236Sken		sassc->path = NULL;
928265236Sken	}
929265236Sken
930265236Sken	if (sassc->flags & MPRSAS_IN_STARTUP)
931265236Sken		xpt_release_simq(sassc->sim, 1);
932265236Sken
933265236Sken	if (sassc->sim != NULL) {
934265236Sken		xpt_bus_deregister(cam_sim_path(sassc->sim));
935265236Sken		cam_sim_free(sassc->sim, FALSE);
936265236Sken	}
937265236Sken
938265236Sken	mpr_unlock(sc);
939265236Sken
940265236Sken	if (sassc->devq != NULL)
941265236Sken		cam_simq_free(sassc->devq);
942265236Sken
943265236Sken	for (i = 0; i < sassc->maxtargets; i++) {
944265236Sken		targ = &sassc->targets[i];
945265236Sken		SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) {
946265236Sken			free(lun, M_MPR);
947265236Sken		}
948265236Sken	}
949265236Sken	free(sassc->targets, M_MPR);
950265236Sken	free(sassc, M_MPR);
951265236Sken	sc->sassc = NULL;
952265236Sken
953265236Sken	return (0);
954265236Sken}
955265236Sken
956265236Skenvoid
957265236Skenmprsas_discovery_end(struct mprsas_softc *sassc)
958265236Sken{
959265236Sken	struct mpr_softc *sc = sassc->sc;
960265236Sken
961265236Sken	MPR_FUNCTRACE(sc);
962265236Sken
963265236Sken	if (sassc->flags & MPRSAS_DISCOVERY_TIMEOUT_PENDING)
964265236Sken		callout_stop(&sassc->discovery_callout);
965265236Sken
966319445Sslm	/*
967319445Sslm	 * After discovery has completed, check the mapping table for any
968319445Sslm	 * missing devices and update their missing counts. Only do this once
969319445Sslm	 * whenever the driver is initialized so that missing counts aren't
970319445Sslm	 * updated unnecessarily. Note that just because discovery has
971319445Sslm	 * completed doesn't mean that events have been processed yet. The
972319445Sslm	 * check_devices function is a callout timer that checks if ALL devices
973319445Sslm	 * are missing. If so, it will wait a little longer for events to
974319445Sslm	 * complete and keep resetting itself until some device in the mapping
975319445Sslm	 * table is not missing, meaning that event processing has started.
976319445Sslm	 */
977319445Sslm	if (sc->track_mapping_events) {
978319445Sslm		mpr_dprint(sc, MPR_XINFO | MPR_MAPPING, "Discovery has "
979319445Sslm		    "completed. Check for missing devices in the mapping "
980319445Sslm		    "table.\n");
981319445Sslm		callout_reset(&sc->device_check_callout,
982319445Sslm		    MPR_MISSING_CHECK_DELAY * hz, mpr_mapping_check_devices,
983319445Sslm		    sc);
984319445Sslm	}
985265236Sken}
986265236Sken
987265236Skenstatic void
988265236Skenmprsas_action(struct cam_sim *sim, union ccb *ccb)
989265236Sken{
990265236Sken	struct mprsas_softc *sassc;
991265236Sken
992265236Sken	sassc = cam_sim_softc(sim);
993265236Sken
994265236Sken	MPR_FUNCTRACE(sassc->sc);
995283990Sslm	mpr_dprint(sassc->sc, MPR_TRACE, "ccb func_code 0x%x\n",
996265236Sken	    ccb->ccb_h.func_code);
997265236Sken	mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED);
998265236Sken
999265236Sken	switch (ccb->ccb_h.func_code) {
1000265236Sken	case XPT_PATH_INQ:
1001265236Sken	{
1002265236Sken		struct ccb_pathinq *cpi = &ccb->cpi;
1003303089Sslm		struct mpr_softc *sc = sassc->sc;
1004303089Sslm		uint8_t sges_per_frame;
1005265236Sken
1006265236Sken		cpi->version_num = 1;
1007265236Sken		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
1008265236Sken		cpi->target_sprt = 0;
1009266548Sken#if (__FreeBSD_version >= 1000039) || \
1010266548Sken    ((__FreeBSD_version < 1000000) && (__FreeBSD_version >= 902502))
1011265236Sken		cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN;
1012265236Sken#else
1013265236Sken		cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
1014265236Sken#endif
1015265236Sken		cpi->hba_eng_cnt = 0;
1016265236Sken		cpi->max_target = sassc->maxtargets - 1;
1017265236Sken		cpi->max_lun = 255;
1018319445Sslm
1019319445Sslm		/*
1020319445Sslm		 * initiator_id is set here to an ID outside the set of valid
1021319445Sslm		 * target IDs (including volumes).
1022319445Sslm		 */
1023319445Sslm		cpi->initiator_id = sassc->maxtargets;
1024315813Smav		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1025315813Smav		strlcpy(cpi->hba_vid, "Avago Tech", HBA_IDLEN);
1026315813Smav		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1027265236Sken		cpi->unit_number = cam_sim_unit(sim);
1028265236Sken		cpi->bus_id = cam_sim_bus(sim);
1029265236Sken		/*
1030265236Sken		 * XXXSLM-I think this needs to change based on config page or
1031265236Sken		 * something instead of hardcoded to 150000.
1032265236Sken		 */
1033265236Sken		cpi->base_transfer_speed = 150000;
1034265236Sken		cpi->transport = XPORT_SAS;
1035265236Sken		cpi->transport_version = 0;
1036265236Sken		cpi->protocol = PROTO_SCSI;
1037265236Sken		cpi->protocol_version = SCSI_REV_SPC;
1038303089Sslm
1039265236Sken		/*
1040303089Sslm		 * Max IO Size is Page Size * the following:
1041303089Sslm		 * ((SGEs per frame - 1 for chain element) *
1042303089Sslm		 * Max Chain Depth) + 1 for no chain needed in last frame
1043303089Sslm		 *
1044303089Sslm		 * If user suggests a Max IO size to use, use the smaller of the
1045303089Sslm		 * user's value and the calculated value as long as the user's
1046303089Sslm		 * value is larger than 0. The user's value is in pages.
1047265236Sken		 */
1048303089Sslm		sges_per_frame = (sc->chain_frame_size /
1049303089Sslm		    sizeof(MPI2_IEEE_SGE_SIMPLE64)) - 1;
1050303089Sslm		cpi->maxio = (sges_per_frame * sc->facts->MaxChainDepth) + 1;
1051303089Sslm		cpi->maxio *= PAGE_SIZE;
1052303089Sslm		if ((sc->max_io_pages > 0) && (sc->max_io_pages * PAGE_SIZE <
1053303089Sslm		    cpi->maxio))
1054303089Sslm			cpi->maxio = sc->max_io_pages * PAGE_SIZE;
1055319436Sslm		sc->maxio = cpi->maxio;
1056283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
1057265236Sken		break;
1058265236Sken	}
1059265236Sken	case XPT_GET_TRAN_SETTINGS:
1060265236Sken	{
1061265236Sken		struct ccb_trans_settings	*cts;
1062265236Sken		struct ccb_trans_settings_sas	*sas;
1063265236Sken		struct ccb_trans_settings_scsi	*scsi;
1064265236Sken		struct mprsas_target *targ;
1065265236Sken
1066265236Sken		cts = &ccb->cts;
1067265236Sken		sas = &cts->xport_specific.sas;
1068265236Sken		scsi = &cts->proto_specific.scsi;
1069265236Sken
1070265236Sken		KASSERT(cts->ccb_h.target_id < sassc->maxtargets,
1071265236Sken		    ("Target %d out of bounds in XPT_GET_TRAN_SETTINGS\n",
1072265236Sken		    cts->ccb_h.target_id));
1073265236Sken		targ = &sassc->targets[cts->ccb_h.target_id];
1074265236Sken		if (targ->handle == 0x0) {
1075283990Sslm			mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
1076265236Sken			break;
1077265236Sken		}
1078265236Sken
1079265236Sken		cts->protocol_version = SCSI_REV_SPC2;
1080265236Sken		cts->transport = XPORT_SAS;
1081265236Sken		cts->transport_version = 0;
1082265236Sken
1083265236Sken		sas->valid = CTS_SAS_VALID_SPEED;
1084265236Sken		switch (targ->linkrate) {
1085265236Sken		case 0x08:
1086265236Sken			sas->bitrate = 150000;
1087265236Sken			break;
1088265236Sken		case 0x09:
1089265236Sken			sas->bitrate = 300000;
1090265236Sken			break;
1091265236Sken		case 0x0a:
1092265236Sken			sas->bitrate = 600000;
1093265236Sken			break;
1094273125Smav		case 0x0b:
1095273125Smav			sas->bitrate = 1200000;
1096273125Smav			break;
1097265236Sken		default:
1098265236Sken			sas->valid = 0;
1099265236Sken		}
1100265236Sken
1101265236Sken		cts->protocol = PROTO_SCSI;
1102265236Sken		scsi->valid = CTS_SCSI_VALID_TQ;
1103265236Sken		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
1104265236Sken
1105283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
1106265236Sken		break;
1107265236Sken	}
1108265236Sken	case XPT_CALC_GEOMETRY:
1109265236Sken		cam_calc_geometry(&ccb->ccg, /*extended*/1);
1110283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
1111265236Sken		break;
1112265236Sken	case XPT_RESET_DEV:
1113299962Sslm		mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action "
1114299962Sslm		    "XPT_RESET_DEV\n");
1115265236Sken		mprsas_action_resetdev(sassc, ccb);
1116265236Sken		return;
1117265236Sken	case XPT_RESET_BUS:
1118265236Sken	case XPT_ABORT:
1119265236Sken	case XPT_TERM_IO:
1120299962Sslm		mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success "
1121299962Sslm		    "for abort or reset\n");
1122283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
1123265236Sken		break;
1124265236Sken	case XPT_SCSI_IO:
1125265236Sken		mprsas_action_scsiio(sassc, ccb);
1126265236Sken		return;
1127265236Sken#if __FreeBSD_version >= 900026
1128265236Sken	case XPT_SMP_IO:
1129265236Sken		mprsas_action_smpio(sassc, ccb);
1130265236Sken		return;
1131265236Sken#endif
1132265236Sken	default:
1133283990Sslm		mprsas_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL);
1134265236Sken		break;
1135265236Sken	}
1136265236Sken	xpt_done(ccb);
1137265236Sken
1138265236Sken}
1139265236Sken
1140265236Skenstatic void
1141265236Skenmprsas_announce_reset(struct mpr_softc *sc, uint32_t ac_code,
1142265236Sken    target_id_t target_id, lun_id_t lun_id)
1143265236Sken{
1144265236Sken	path_id_t path_id = cam_sim_path(sc->sassc->sim);
1145265236Sken	struct cam_path *path;
1146265236Sken
1147265236Sken	mpr_dprint(sc, MPR_XINFO, "%s code %x target %d lun %jx\n", __func__,
1148265236Sken	    ac_code, target_id, (uintmax_t)lun_id);
1149265236Sken
1150265236Sken	if (xpt_create_path(&path, NULL,
1151265236Sken		path_id, target_id, lun_id) != CAM_REQ_CMP) {
1152265236Sken		mpr_dprint(sc, MPR_ERROR, "unable to create path for reset "
1153283990Sslm		    "notification\n");
1154265236Sken		return;
1155265236Sken	}
1156265236Sken
1157265236Sken	xpt_async(ac_code, path, NULL);
1158265236Sken	xpt_free_path(path);
1159265236Sken}
1160265236Sken
1161265236Skenstatic void
1162265236Skenmprsas_complete_all_commands(struct mpr_softc *sc)
1163265236Sken{
1164265236Sken	struct mpr_command *cm;
1165265236Sken	int i;
1166265236Sken	int completed;
1167265236Sken
1168265236Sken	MPR_FUNCTRACE(sc);
1169265236Sken	mtx_assert(&sc->mpr_mtx, MA_OWNED);
1170265236Sken
1171265236Sken	/* complete all commands with a NULL reply */
1172265236Sken	for (i = 1; i < sc->num_reqs; i++) {
1173265236Sken		cm = &sc->commands[i];
1174265236Sken		cm->cm_reply = NULL;
1175265236Sken		completed = 0;
1176265236Sken
1177265236Sken		if (cm->cm_flags & MPR_CM_FLAGS_POLLED)
1178265236Sken			cm->cm_flags |= MPR_CM_FLAGS_COMPLETE;
1179265236Sken
1180265236Sken		if (cm->cm_complete != NULL) {
1181265236Sken			mprsas_log_command(cm, MPR_RECOVERY,
1182299962Sslm			    "completing cm %p state %x ccb %p for diag reset\n",
1183299962Sslm			    cm, cm->cm_state, cm->cm_ccb);
1184265236Sken			cm->cm_complete(sc, cm);
1185265236Sken			completed = 1;
1186265236Sken		}
1187265236Sken
1188265236Sken		if (cm->cm_flags & MPR_CM_FLAGS_WAKEUP) {
1189265236Sken			mprsas_log_command(cm, MPR_RECOVERY,
1190265236Sken			    "waking up cm %p state %x ccb %p for diag reset\n",
1191265236Sken			    cm, cm->cm_state, cm->cm_ccb);
1192265236Sken			wakeup(cm);
1193265236Sken			completed = 1;
1194265236Sken		}
1195265236Sken
1196322661Sken		if (cm->cm_sc->io_cmds_active != 0)
1197283990Sslm			cm->cm_sc->io_cmds_active--;
1198283990Sslm
1199265236Sken		if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) {
1200265236Sken			/* this should never happen, but if it does, log */
1201265236Sken			mprsas_log_command(cm, MPR_RECOVERY,
1202265236Sken			    "cm %p state %x flags 0x%x ccb %p during diag "
1203265236Sken			    "reset\n", cm, cm->cm_state, cm->cm_flags,
1204265236Sken			    cm->cm_ccb);
1205265236Sken		}
1206265236Sken	}
1207265236Sken}
1208265236Sken
1209265236Skenvoid
1210265236Skenmprsas_handle_reinit(struct mpr_softc *sc)
1211265236Sken{
1212265236Sken	int i;
1213265236Sken
1214265236Sken	/* Go back into startup mode and freeze the simq, so that CAM
1215265236Sken	 * doesn't send any commands until after we've rediscovered all
1216265236Sken	 * targets and found the proper device handles for them.
1217265236Sken	 *
1218265236Sken	 * After the reset, portenable will trigger discovery, and after all
1219265236Sken	 * discovery-related activities have finished, the simq will be
1220265236Sken	 * released.
1221265236Sken	 */
1222265236Sken	mpr_dprint(sc, MPR_INIT, "%s startup\n", __func__);
1223265236Sken	sc->sassc->flags |= MPRSAS_IN_STARTUP;
1224265236Sken	sc->sassc->flags |= MPRSAS_IN_DISCOVERY;
1225265236Sken	mprsas_startup_increment(sc->sassc);
1226265236Sken
1227265236Sken	/* notify CAM of a bus reset */
1228265236Sken	mprsas_announce_reset(sc, AC_BUS_RESET, CAM_TARGET_WILDCARD,
1229265236Sken	    CAM_LUN_WILDCARD);
1230265236Sken
1231265236Sken	/* complete and cleanup after all outstanding commands */
1232265236Sken	mprsas_complete_all_commands(sc);
1233265236Sken
1234283990Sslm	mpr_dprint(sc, MPR_INIT, "%s startup %u after command completion\n",
1235283990Sslm	    __func__, sc->sassc->startup_refcount);
1236265236Sken
1237265236Sken	/* zero all the target handles, since they may change after the
1238265236Sken	 * reset, and we have to rediscover all the targets and use the new
1239265236Sken	 * handles.
1240265236Sken	 */
1241265236Sken	for (i = 0; i < sc->sassc->maxtargets; i++) {
1242265236Sken		if (sc->sassc->targets[i].outstanding != 0)
1243265236Sken			mpr_dprint(sc, MPR_INIT, "target %u outstanding %u\n",
1244265236Sken			    i, sc->sassc->targets[i].outstanding);
1245265236Sken		sc->sassc->targets[i].handle = 0x0;
1246265236Sken		sc->sassc->targets[i].exp_dev_handle = 0x0;
1247265236Sken		sc->sassc->targets[i].outstanding = 0;
1248265236Sken		sc->sassc->targets[i].flags = MPRSAS_TARGET_INDIAGRESET;
1249265236Sken	}
1250265236Sken}
1251265236Skenstatic void
1252265236Skenmprsas_tm_timeout(void *data)
1253265236Sken{
1254265236Sken	struct mpr_command *tm = data;
1255265236Sken	struct mpr_softc *sc = tm->cm_sc;
1256265236Sken
1257265236Sken	mtx_assert(&sc->mpr_mtx, MA_OWNED);
1258265236Sken
1259299962Sslm	mprsas_log_command(tm, MPR_INFO|MPR_RECOVERY, "task mgmt %p timed "
1260299962Sslm	    "out\n", tm);
1261265236Sken	mpr_reinit(sc);
1262265236Sken}
1263265236Sken
1264265236Skenstatic void
1265299962Sslmmprsas_logical_unit_reset_complete(struct mpr_softc *sc, struct mpr_command *tm)
1266265236Sken{
1267265236Sken	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
1268265236Sken	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
1269265236Sken	unsigned int cm_count = 0;
1270265236Sken	struct mpr_command *cm;
1271265236Sken	struct mprsas_target *targ;
1272265236Sken
1273265236Sken	callout_stop(&tm->cm_callout);
1274265236Sken
1275265236Sken	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
1276265236Sken	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
1277265236Sken	targ = tm->cm_targ;
1278265236Sken
1279265236Sken	/*
1280265236Sken	 * Currently there should be no way we can hit this case.  It only
1281265236Sken	 * happens when we have a failure to allocate chain frames, and
1282265236Sken	 * task management commands don't have S/G lists.
1283265236Sken	 */
1284265236Sken	if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
1285265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for LUN reset! "
1286265236Sken		    "This should not happen!\n", __func__, tm->cm_flags);
1287265236Sken		mprsas_free_tm(sc, tm);
1288265236Sken		return;
1289265236Sken	}
1290265236Sken
1291265236Sken	if (reply == NULL) {
1292299962Sslm		mprsas_log_command(tm, MPR_RECOVERY, "NULL reset reply for tm "
1293299962Sslm		    "%p\n", tm);
1294265236Sken		if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) {
1295265236Sken			/* this completion was due to a reset, just cleanup */
1296265236Sken			targ->tm = NULL;
1297265236Sken			mprsas_free_tm(sc, tm);
1298265236Sken		}
1299265236Sken		else {
1300265236Sken			/* we should have gotten a reply. */
1301265236Sken			mpr_reinit(sc);
1302265236Sken		}
1303265236Sken		return;
1304265236Sken	}
1305265236Sken
1306265236Sken	mprsas_log_command(tm, MPR_RECOVERY,
1307265236Sken	    "logical unit reset status 0x%x code 0x%x count %u\n",
1308265236Sken	    le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
1309265236Sken	    le32toh(reply->TerminationCount));
1310265236Sken
1311265236Sken	/* See if there are any outstanding commands for this LUN.
1312265236Sken	 * This could be made more efficient by using a per-LU data
1313265236Sken	 * structure of some sort.
1314265236Sken	 */
1315265236Sken	TAILQ_FOREACH(cm, &targ->commands, cm_link) {
1316265236Sken		if (cm->cm_lun == tm->cm_lun)
1317265236Sken			cm_count++;
1318265236Sken	}
1319265236Sken
1320265236Sken	if (cm_count == 0) {
1321265236Sken		mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO,
1322265236Sken		    "logical unit %u finished recovery after reset\n",
1323265236Sken		    tm->cm_lun, tm);
1324265236Sken
1325265236Sken		mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
1326265236Sken		    tm->cm_lun);
1327265236Sken
1328265236Sken		/* we've finished recovery for this logical unit.  check and
1329265236Sken		 * see if some other logical unit has a timedout command
1330265236Sken		 * that needs to be processed.
1331265236Sken		 */
1332265236Sken		cm = TAILQ_FIRST(&targ->timedout_commands);
1333265236Sken		if (cm) {
1334265236Sken			mprsas_send_abort(sc, tm, cm);
1335265236Sken		}
1336265236Sken		else {
1337265236Sken			targ->tm = NULL;
1338265236Sken			mprsas_free_tm(sc, tm);
1339265236Sken		}
1340265236Sken	}
1341265236Sken	else {
1342265236Sken		/* if we still have commands for this LUN, the reset
1343265236Sken		 * effectively failed, regardless of the status reported.
1344265236Sken		 * Escalate to a target reset.
1345265236Sken		 */
1346265236Sken		mprsas_log_command(tm, MPR_RECOVERY,
1347265236Sken		    "logical unit reset complete for tm %p, but still have %u "
1348265236Sken		    "command(s)\n", tm, cm_count);
1349265236Sken		mprsas_send_reset(sc, tm,
1350265236Sken		    MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
1351265236Sken	}
1352265236Sken}
1353265236Sken
1354265236Skenstatic void
1355265236Skenmprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm)
1356265236Sken{
1357265236Sken	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
1358265236Sken	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
1359265236Sken	struct mprsas_target *targ;
1360265236Sken
1361265236Sken	callout_stop(&tm->cm_callout);
1362265236Sken
1363265236Sken	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
1364265236Sken	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
1365265236Sken	targ = tm->cm_targ;
1366265236Sken
1367265236Sken	/*
1368265236Sken	 * Currently there should be no way we can hit this case.  It only
1369265236Sken	 * happens when we have a failure to allocate chain frames, and
1370265236Sken	 * task management commands don't have S/G lists.
1371265236Sken	 */
1372265236Sken	if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
1373283990Sslm		mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target "
1374283990Sslm		    "reset! This should not happen!\n", __func__, tm->cm_flags);
1375265236Sken		mprsas_free_tm(sc, tm);
1376265236Sken		return;
1377265236Sken	}
1378265236Sken
1379265236Sken	if (reply == NULL) {
1380299962Sslm		mprsas_log_command(tm, MPR_RECOVERY, "NULL reset reply for tm "
1381299962Sslm		    "%p\n", tm);
1382265236Sken		if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) {
1383265236Sken			/* this completion was due to a reset, just cleanup */
1384265236Sken			targ->tm = NULL;
1385265236Sken			mprsas_free_tm(sc, tm);
1386265236Sken		}
1387265236Sken		else {
1388265236Sken			/* we should have gotten a reply. */
1389265236Sken			mpr_reinit(sc);
1390265236Sken		}
1391265236Sken		return;
1392265236Sken	}
1393265236Sken
1394265236Sken	mprsas_log_command(tm, MPR_RECOVERY,
1395265236Sken	    "target reset status 0x%x code 0x%x count %u\n",
1396265236Sken	    le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
1397265236Sken	    le32toh(reply->TerminationCount));
1398265236Sken
1399265236Sken	if (targ->outstanding == 0) {
1400265236Sken		/* we've finished recovery for this target and all
1401265236Sken		 * of its logical units.
1402265236Sken		 */
1403265236Sken		mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO,
1404265236Sken		    "recovery finished after target reset\n");
1405265236Sken
1406265236Sken		mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
1407265236Sken		    CAM_LUN_WILDCARD);
1408265236Sken
1409265236Sken		targ->tm = NULL;
1410265236Sken		mprsas_free_tm(sc, tm);
1411265236Sken	}
1412265236Sken	else {
1413265236Sken		/* after a target reset, if this target still has
1414265236Sken		 * outstanding commands, the reset effectively failed,
1415265236Sken		 * regardless of the status reported.  escalate.
1416265236Sken		 */
1417265236Sken		mprsas_log_command(tm, MPR_RECOVERY,
1418265236Sken		    "target reset complete for tm %p, but still have %u "
1419265236Sken		    "command(s)\n", tm, targ->outstanding);
1420265236Sken		mpr_reinit(sc);
1421265236Sken	}
1422265236Sken}
1423265236Sken
1424265236Sken#define MPR_RESET_TIMEOUT 30
1425265236Sken
1426283990Sslmint
1427265236Skenmprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type)
1428265236Sken{
1429265236Sken	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
1430265236Sken	struct mprsas_target *target;
1431265236Sken	int err;
1432265236Sken
1433265236Sken	target = tm->cm_targ;
1434265236Sken	if (target->handle == 0) {
1435283990Sslm		mpr_dprint(sc, MPR_ERROR, "%s null devhandle for target_id "
1436283990Sslm		    "%d\n", __func__, target->tid);
1437265236Sken		return -1;
1438265236Sken	}
1439265236Sken
1440265236Sken	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
1441265236Sken	req->DevHandle = htole16(target->handle);
1442265236Sken	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
1443265236Sken	req->TaskType = type;
1444265236Sken
1445265236Sken	if (type == MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET) {
1446265236Sken		/* XXX Need to handle invalid LUNs */
1447265236Sken		MPR_SET_LUN(req->LUN, tm->cm_lun);
1448265236Sken		tm->cm_targ->logical_unit_resets++;
1449265236Sken		mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO,
1450265236Sken		    "sending logical unit reset\n");
1451265236Sken		tm->cm_complete = mprsas_logical_unit_reset_complete;
1452283990Sslm		mprsas_prepare_for_tm(sc, tm, target, tm->cm_lun);
1453265236Sken	}
1454265236Sken	else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1455265236Sken		/*
1456265236Sken		 * Target reset method =
1457265236Sken		 *     SAS Hard Link Reset / SATA Link Reset
1458265236Sken		 */
1459265236Sken		req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
1460265236Sken		tm->cm_targ->target_resets++;
1461265236Sken		mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO,
1462265236Sken		    "sending target reset\n");
1463265236Sken		tm->cm_complete = mprsas_target_reset_complete;
1464283990Sslm		mprsas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD);
1465265236Sken	}
1466265236Sken	else {
1467265236Sken		mpr_dprint(sc, MPR_ERROR, "unexpected reset type 0x%x\n", type);
1468265236Sken		return -1;
1469265236Sken	}
1470265236Sken
1471283990Sslm	mpr_dprint(sc, MPR_INFO, "to target %u handle 0x%04x\n", target->tid,
1472265236Sken	    target->handle);
1473265236Sken	if (target->encl_level_valid) {
1474283990Sslm		mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, "
1475265236Sken		    "connector name (%4s)\n", target->encl_level,
1476265236Sken		    target->encl_slot, target->connector_name);
1477265236Sken	}
1478265236Sken
1479265236Sken	tm->cm_data = NULL;
1480265236Sken	tm->cm_desc.HighPriority.RequestFlags =
1481265236Sken	    MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
1482265236Sken	tm->cm_complete_data = (void *)tm;
1483265236Sken
1484265236Sken	callout_reset(&tm->cm_callout, MPR_RESET_TIMEOUT * hz,
1485265236Sken	    mprsas_tm_timeout, tm);
1486265236Sken
1487265236Sken	err = mpr_map_command(sc, tm);
1488265236Sken	if (err)
1489265236Sken		mprsas_log_command(tm, MPR_RECOVERY,
1490283990Sslm		    "error %d sending reset type %u\n", err, type);
1491265236Sken
1492265236Sken	return err;
1493265236Sken}
1494265236Sken
1495265236Sken
1496265236Skenstatic void
1497265236Skenmprsas_abort_complete(struct mpr_softc *sc, struct mpr_command *tm)
1498265236Sken{
1499265236Sken	struct mpr_command *cm;
1500265236Sken	MPI2_SCSI_TASK_MANAGE_REPLY *reply;
1501265236Sken	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
1502265236Sken	struct mprsas_target *targ;
1503265236Sken
1504265236Sken	callout_stop(&tm->cm_callout);
1505265236Sken
1506265236Sken	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
1507265236Sken	reply = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
1508265236Sken	targ = tm->cm_targ;
1509265236Sken
1510265236Sken	/*
1511265236Sken	 * Currently there should be no way we can hit this case.  It only
1512265236Sken	 * happens when we have a failure to allocate chain frames, and
1513265236Sken	 * task management commands don't have S/G lists.
1514265236Sken	 */
1515265236Sken	if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
1516265236Sken		mprsas_log_command(tm, MPR_RECOVERY,
1517265236Sken		    "cm_flags = %#x for abort %p TaskMID %u!\n",
1518265236Sken		    tm->cm_flags, tm, le16toh(req->TaskMID));
1519265236Sken		mprsas_free_tm(sc, tm);
1520265236Sken		return;
1521265236Sken	}
1522265236Sken
1523265236Sken	if (reply == NULL) {
1524265236Sken		mprsas_log_command(tm, MPR_RECOVERY,
1525265236Sken		    "NULL abort reply for tm %p TaskMID %u\n",
1526265236Sken		    tm, le16toh(req->TaskMID));
1527265236Sken		if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) {
1528265236Sken			/* this completion was due to a reset, just cleanup */
1529265236Sken			targ->tm = NULL;
1530265236Sken			mprsas_free_tm(sc, tm);
1531265236Sken		}
1532265236Sken		else {
1533265236Sken			/* we should have gotten a reply. */
1534265236Sken			mpr_reinit(sc);
1535265236Sken		}
1536265236Sken		return;
1537265236Sken	}
1538265236Sken
1539265236Sken	mprsas_log_command(tm, MPR_RECOVERY,
1540265236Sken	    "abort TaskMID %u status 0x%x code 0x%x count %u\n",
1541265236Sken	    le16toh(req->TaskMID),
1542265236Sken	    le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
1543265236Sken	    le32toh(reply->TerminationCount));
1544265236Sken
1545265236Sken	cm = TAILQ_FIRST(&tm->cm_targ->timedout_commands);
1546265236Sken	if (cm == NULL) {
1547265236Sken		/* if there are no more timedout commands, we're done with
1548265236Sken		 * error recovery for this target.
1549265236Sken		 */
1550265236Sken		mprsas_log_command(tm, MPR_RECOVERY,
1551265236Sken		    "finished recovery after aborting TaskMID %u\n",
1552265236Sken		    le16toh(req->TaskMID));
1553265236Sken
1554265236Sken		targ->tm = NULL;
1555265236Sken		mprsas_free_tm(sc, tm);
1556265236Sken	}
1557265236Sken	else if (le16toh(req->TaskMID) != cm->cm_desc.Default.SMID) {
1558265236Sken		/* abort success, but we have more timedout commands to abort */
1559265236Sken		mprsas_log_command(tm, MPR_RECOVERY,
1560265236Sken		    "continuing recovery after aborting TaskMID %u\n",
1561265236Sken		    le16toh(req->TaskMID));
1562265236Sken
1563265236Sken		mprsas_send_abort(sc, tm, cm);
1564265236Sken	}
1565265236Sken	else {
1566265236Sken		/* we didn't get a command completion, so the abort
1567265236Sken		 * failed as far as we're concerned.  escalate.
1568265236Sken		 */
1569265236Sken		mprsas_log_command(tm, MPR_RECOVERY,
1570265236Sken		    "abort failed for TaskMID %u tm %p\n",
1571265236Sken		    le16toh(req->TaskMID), tm);
1572265236Sken
1573265236Sken		mprsas_send_reset(sc, tm,
1574265236Sken		    MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET);
1575265236Sken	}
1576265236Sken}
1577265236Sken
1578265236Sken#define MPR_ABORT_TIMEOUT 5
1579265236Sken
1580265236Skenstatic int
1581265236Skenmprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm,
1582265236Sken    struct mpr_command *cm)
1583265236Sken{
1584265236Sken	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
1585265236Sken	struct mprsas_target *targ;
1586265236Sken	int err;
1587265236Sken
1588265236Sken	targ = cm->cm_targ;
1589265236Sken	if (targ->handle == 0) {
1590265236Sken		mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n",
1591265236Sken		    __func__, cm->cm_ccb->ccb_h.target_id);
1592265236Sken		return -1;
1593265236Sken	}
1594265236Sken
1595319436Sslm	mprsas_log_command(cm, MPR_RECOVERY|MPR_INFO,
1596265236Sken	    "Aborting command %p\n", cm);
1597265236Sken
1598265236Sken	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
1599265236Sken	req->DevHandle = htole16(targ->handle);
1600265236Sken	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
1601265236Sken	req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
1602265236Sken
1603265236Sken	/* XXX Need to handle invalid LUNs */
1604265236Sken	MPR_SET_LUN(req->LUN, cm->cm_ccb->ccb_h.target_lun);
1605265236Sken
1606265236Sken	req->TaskMID = htole16(cm->cm_desc.Default.SMID);
1607265236Sken
1608265236Sken	tm->cm_data = NULL;
1609265236Sken	tm->cm_desc.HighPriority.RequestFlags =
1610265236Sken	    MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
1611265236Sken	tm->cm_complete = mprsas_abort_complete;
1612265236Sken	tm->cm_complete_data = (void *)tm;
1613265236Sken	tm->cm_targ = cm->cm_targ;
1614265236Sken	tm->cm_lun = cm->cm_lun;
1615265236Sken
1616265236Sken	callout_reset(&tm->cm_callout, MPR_ABORT_TIMEOUT * hz,
1617265236Sken	    mprsas_tm_timeout, tm);
1618265236Sken
1619265236Sken	targ->aborts++;
1620265236Sken
1621283990Sslm	mpr_dprint(sc, MPR_INFO, "Sending reset from %s for target ID %d\n",
1622283990Sslm	    __func__, targ->tid);
1623283990Sslm	mprsas_prepare_for_tm(sc, tm, targ, tm->cm_lun);
1624283990Sslm
1625265236Sken	err = mpr_map_command(sc, tm);
1626265236Sken	if (err)
1627319436Sslm		mpr_dprint(sc, MPR_RECOVERY,
1628265236Sken		    "error %d sending abort for cm %p SMID %u\n",
1629265236Sken		    err, cm, req->TaskMID);
1630265236Sken	return err;
1631265236Sken}
1632265236Sken
1633265236Skenstatic void
1634265236Skenmprsas_scsiio_timeout(void *data)
1635265236Sken{
1636265236Sken	struct mpr_softc *sc;
1637265236Sken	struct mpr_command *cm;
1638265236Sken	struct mprsas_target *targ;
1639265236Sken
1640265236Sken	cm = (struct mpr_command *)data;
1641265236Sken	sc = cm->cm_sc;
1642265236Sken
1643265236Sken	MPR_FUNCTRACE(sc);
1644265236Sken	mtx_assert(&sc->mpr_mtx, MA_OWNED);
1645265236Sken
1646265236Sken	mpr_dprint(sc, MPR_XINFO, "Timeout checking cm %p\n", cm);
1647265236Sken
1648265236Sken	/*
1649265236Sken	 * Run the interrupt handler to make sure it's not pending.  This
1650265236Sken	 * isn't perfect because the command could have already completed
1651265236Sken	 * and been re-used, though this is unlikely.
1652265236Sken	 */
1653265236Sken	mpr_intr_locked(sc);
1654265236Sken	if (cm->cm_state == MPR_CM_STATE_FREE) {
1655265236Sken		mprsas_log_command(cm, MPR_XINFO,
1656265236Sken		    "SCSI command %p almost timed out\n", cm);
1657265236Sken		return;
1658265236Sken	}
1659265236Sken
1660265236Sken	if (cm->cm_ccb == NULL) {
1661265236Sken		mpr_dprint(sc, MPR_ERROR, "command timeout with NULL ccb\n");
1662265236Sken		return;
1663265236Sken	}
1664265236Sken
1665265236Sken	targ = cm->cm_targ;
1666265236Sken	targ->timeouts++;
1667265236Sken
1668319436Sslm	mprsas_log_command(cm, MPR_ERROR, "command timeout %d cm %p target "
1669319436Sslm	    "%u, handle(0x%04x)\n", cm->cm_ccb->ccb_h.timeout, cm, targ->tid,
1670319436Sslm	    targ->handle);
1671265236Sken	if (targ->encl_level_valid) {
1672283990Sslm		mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, "
1673265236Sken		    "connector name (%4s)\n", targ->encl_level, targ->encl_slot,
1674265236Sken		    targ->connector_name);
1675265236Sken	}
1676265236Sken
1677265236Sken	/* XXX first, check the firmware state, to see if it's still
1678265236Sken	 * operational.  if not, do a diag reset.
1679265236Sken	 */
1680283990Sslm	mprsas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT);
1681265236Sken	cm->cm_state = MPR_CM_STATE_TIMEDOUT;
1682265236Sken	TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery);
1683265236Sken
1684265236Sken	if (targ->tm != NULL) {
1685265236Sken		/* target already in recovery, just queue up another
1686265236Sken		 * timedout command to be processed later.
1687265236Sken		 */
1688265236Sken		mpr_dprint(sc, MPR_RECOVERY, "queued timedout cm %p for "
1689265236Sken		    "processing by tm %p\n", cm, targ->tm);
1690265236Sken	}
1691265236Sken	else if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) {
1692265236Sken		mpr_dprint(sc, MPR_RECOVERY, "timedout cm %p allocated tm %p\n",
1693265236Sken		    cm, targ->tm);
1694265236Sken
1695265236Sken		/* start recovery by aborting the first timedout command */
1696265236Sken		mprsas_send_abort(sc, targ->tm, cm);
1697265236Sken	}
1698265236Sken	else {
1699265236Sken		/* XXX queue this target up for recovery once a TM becomes
1700265236Sken		 * available.  The firmware only has a limited number of
1701265236Sken		 * HighPriority credits for the high priority requests used
1702265236Sken		 * for task management, and we ran out.
1703265236Sken		 *
1704265236Sken		 * Isilon: don't worry about this for now, since we have
1705265236Sken		 * more credits than disks in an enclosure, and limit
1706265236Sken		 * ourselves to one TM per target for recovery.
1707265236Sken		 */
1708299962Sslm		mpr_dprint(sc, MPR_RECOVERY, "timedout cm %p failed to "
1709299962Sslm		    "allocate a tm\n", cm);
1710265236Sken	}
1711265236Sken}
1712265236Sken
1713319436Sslm/**
1714319436Sslm * mprsas_build_nvme_unmap - Build Native NVMe DSM command equivalent
1715319436Sslm *			     to SCSI Unmap.
1716319436Sslm * Return 0 - for success,
1717319436Sslm *	  1 - to immediately return back the command with success status to CAM
1718319436Sslm *	  negative value - to fallback to firmware path i.e. issue scsi unmap
1719319436Sslm *			   to FW without any translation.
1720319436Sslm */
1721319436Sslmstatic int
1722319436Sslmmprsas_build_nvme_unmap(struct mpr_softc *sc, struct mpr_command *cm,
1723319436Sslm    union ccb *ccb, struct mprsas_target *targ)
1724319436Sslm{
1725319436Sslm	Mpi26NVMeEncapsulatedRequest_t *req = NULL;
1726319436Sslm	struct ccb_scsiio *csio;
1727319436Sslm	struct unmap_parm_list *plist;
1728319436Sslm	struct nvme_dsm_range *nvme_dsm_ranges = NULL;
1729319436Sslm	struct nvme_command *c;
1730319436Sslm	int i, res;
1731319436Sslm	uint16_t ndesc, list_len, data_length;
1732319436Sslm	struct mpr_prp_page *prp_page_info;
1733319436Sslm	uint64_t nvme_dsm_ranges_dma_handle;
1734319436Sslm
1735319436Sslm	csio = &ccb->csio;
1736319436Sslm#if __FreeBSD_version >= 1100103
1737319436Sslm	list_len = (scsiio_cdb_ptr(csio)[7] << 8 | scsiio_cdb_ptr(csio)[8]);
1738319436Sslm#else
1739319436Sslm	if (csio->ccb_h.flags & CAM_CDB_POINTER) {
1740319436Sslm		list_len = (ccb->csio.cdb_io.cdb_ptr[7] << 8 |
1741319436Sslm		    ccb->csio.cdb_io.cdb_ptr[8]);
1742319436Sslm	} else {
1743319436Sslm		list_len = (ccb->csio.cdb_io.cdb_bytes[7] << 8 |
1744319436Sslm		    ccb->csio.cdb_io.cdb_bytes[8]);
1745319436Sslm	}
1746319436Sslm#endif
1747319436Sslm	if (!list_len) {
1748319436Sslm		mpr_dprint(sc, MPR_ERROR, "Parameter list length is Zero\n");
1749319436Sslm		return -EINVAL;
1750319436Sslm	}
1751319436Sslm
1752319436Sslm	plist = malloc(csio->dxfer_len, M_MPR, M_ZERO|M_NOWAIT);
1753319436Sslm	if (!plist) {
1754319436Sslm		mpr_dprint(sc, MPR_ERROR, "Unable to allocate memory to "
1755319436Sslm		    "save UNMAP data\n");
1756319436Sslm		return -ENOMEM;
1757319436Sslm	}
1758319436Sslm
1759319436Sslm	/* Copy SCSI unmap data to a local buffer */
1760319436Sslm	bcopy(csio->data_ptr, plist, csio->dxfer_len);
1761319436Sslm
1762319436Sslm	/* return back the unmap command to CAM with success status,
1763319436Sslm	 * if number of descripts is zero.
1764319436Sslm	 */
1765319436Sslm	ndesc = be16toh(plist->unmap_blk_desc_data_len) >> 4;
1766319436Sslm	if (!ndesc) {
1767319436Sslm		mpr_dprint(sc, MPR_XINFO, "Number of descriptors in "
1768319436Sslm		    "UNMAP cmd is Zero\n");
1769319436Sslm		res = 1;
1770319436Sslm		goto out;
1771319436Sslm	}
1772319436Sslm
1773319436Sslm	data_length = ndesc * sizeof(struct nvme_dsm_range);
1774319436Sslm	if (data_length > targ->MDTS) {
1775319436Sslm		mpr_dprint(sc, MPR_ERROR, "data length: %d is greater than "
1776319436Sslm		    "Device's MDTS: %d\n", data_length, targ->MDTS);
1777319436Sslm		res = -EINVAL;
1778319436Sslm		goto out;
1779319436Sslm	}
1780319436Sslm
1781319436Sslm	prp_page_info = mpr_alloc_prp_page(sc);
1782319436Sslm	KASSERT(prp_page_info != NULL, ("%s: There is no PRP Page for "
1783319436Sslm	    "UNMAP command.\n", __func__));
1784319436Sslm
1785319436Sslm	/*
1786319436Sslm	 * Insert the allocated PRP page into the command's PRP page list. This
1787319436Sslm	 * will be freed when the command is freed.
1788319436Sslm	 */
1789319436Sslm	TAILQ_INSERT_TAIL(&cm->cm_prp_page_list, prp_page_info, prp_page_link);
1790319436Sslm
1791319436Sslm	nvme_dsm_ranges = (struct nvme_dsm_range *)prp_page_info->prp_page;
1792319436Sslm	nvme_dsm_ranges_dma_handle = prp_page_info->prp_page_busaddr;
1793319436Sslm
1794319436Sslm	bzero(nvme_dsm_ranges, data_length);
1795319436Sslm
1796319436Sslm	/* Convert SCSI unmap's descriptor data to NVMe DSM specific Range data
1797319436Sslm	 * for each descriptors contained in SCSI UNMAP data.
1798319436Sslm	 */
1799319436Sslm	for (i = 0; i < ndesc; i++) {
1800319436Sslm		nvme_dsm_ranges[i].length =
1801319436Sslm		    htole32(be32toh(plist->desc[i].nlb));
1802319436Sslm		nvme_dsm_ranges[i].starting_lba =
1803319436Sslm		    htole64(be64toh(plist->desc[i].slba));
1804319436Sslm		nvme_dsm_ranges[i].attributes = 0;
1805319436Sslm	}
1806319436Sslm
1807319436Sslm	/* Build MPI2.6's NVMe Encapsulated Request Message */
1808319436Sslm	req = (Mpi26NVMeEncapsulatedRequest_t *)cm->cm_req;
1809319436Sslm	bzero(req, sizeof(*req));
1810319436Sslm	req->DevHandle = htole16(targ->handle);
1811319436Sslm	req->Function = MPI2_FUNCTION_NVME_ENCAPSULATED;
1812319436Sslm	req->Flags = MPI26_NVME_FLAGS_WRITE;
1813319436Sslm	req->ErrorResponseBaseAddress.High =
1814319436Sslm	    htole32((uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32));
1815319436Sslm	req->ErrorResponseBaseAddress.Low =
1816319436Sslm	    htole32(cm->cm_sense_busaddr);
1817319436Sslm	req->ErrorResponseAllocationLength =
1818319436Sslm	    htole16(sizeof(struct nvme_completion));
1819319436Sslm	req->EncapsulatedCommandLength =
1820319436Sslm	    htole16(sizeof(struct nvme_command));
1821319436Sslm	req->DataLength = htole32(data_length);
1822319436Sslm
1823319436Sslm	/* Build NVMe DSM command */
1824319436Sslm	c = (struct nvme_command *) req->NVMe_Command;
1825319436Sslm	c->opc = NVME_OPC_DATASET_MANAGEMENT;
1826319436Sslm	c->nsid = htole32(csio->ccb_h.target_lun + 1);
1827319436Sslm	c->cdw10 = htole32(ndesc - 1);
1828319436Sslm	c->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE);
1829319436Sslm
1830319436Sslm	cm->cm_length = data_length;
1831319436Sslm	cm->cm_data = NULL;
1832319436Sslm
1833319436Sslm	cm->cm_complete = mprsas_scsiio_complete;
1834319436Sslm	cm->cm_complete_data = ccb;
1835319436Sslm	cm->cm_targ = targ;
1836319436Sslm	cm->cm_lun = csio->ccb_h.target_lun;
1837319436Sslm	cm->cm_ccb = ccb;
1838319436Sslm
1839319436Sslm	cm->cm_desc.Default.RequestFlags =
1840319436Sslm	    MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
1841319436Sslm
1842319436Sslm#if __FreeBSD_version >= 1000029
1843319436Sslm	callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0,
1844319436Sslm	    mprsas_scsiio_timeout, cm, 0);
1845319436Sslm#else //__FreeBSD_version < 1000029
1846319436Sslm	callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000,
1847319436Sslm	    mprsas_scsiio_timeout, cm);
1848319436Sslm#endif //__FreeBSD_version >= 1000029
1849319436Sslm
1850319436Sslm	targ->issued++;
1851319436Sslm	targ->outstanding++;
1852319436Sslm	TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link);
1853319436Sslm	ccb->ccb_h.status |= CAM_SIM_QUEUED;
1854319436Sslm
1855319436Sslm	mprsas_log_command(cm, MPR_XINFO, "%s cm %p ccb %p outstanding %u\n",
1856319436Sslm	    __func__, cm, ccb, targ->outstanding);
1857319436Sslm
1858319436Sslm	mpr_build_nvme_prp(sc, cm, req,
1859319436Sslm	    (void *)(uintptr_t)nvme_dsm_ranges_dma_handle, 0, data_length);
1860319436Sslm	mpr_map_command(sc, cm);
1861319436Sslm
1862319436Sslmout:
1863319436Sslm	free(plist, M_MPR);
1864319436Sslm	return 0;
1865319436Sslm}
1866319436Sslm
1867265236Skenstatic void
1868265236Skenmprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb)
1869265236Sken{
1870265236Sken	MPI2_SCSI_IO_REQUEST *req;
1871265236Sken	struct ccb_scsiio *csio;
1872265236Sken	struct mpr_softc *sc;
1873265236Sken	struct mprsas_target *targ;
1874265236Sken	struct mprsas_lun *lun;
1875265236Sken	struct mpr_command *cm;
1876319436Sslm	uint8_t i, lba_byte, *ref_tag_addr, scsi_opcode;
1877265236Sken	uint16_t eedp_flags;
1878265236Sken	uint32_t mpi_control;
1879319436Sslm	int rc;
1880265236Sken
1881265236Sken	sc = sassc->sc;
1882265236Sken	MPR_FUNCTRACE(sc);
1883265236Sken	mtx_assert(&sc->mpr_mtx, MA_OWNED);
1884265236Sken
1885265236Sken	csio = &ccb->csio;
1886283990Sslm	KASSERT(csio->ccb_h.target_id < sassc->maxtargets,
1887283990Sslm	    ("Target %d out of bounds in XPT_SCSI_IO\n",
1888283990Sslm	     csio->ccb_h.target_id));
1889265236Sken	targ = &sassc->targets[csio->ccb_h.target_id];
1890265236Sken	mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags);
1891265236Sken	if (targ->handle == 0x0) {
1892265236Sken		mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n",
1893265236Sken		    __func__, csio->ccb_h.target_id);
1894283990Sslm		mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
1895265236Sken		xpt_done(ccb);
1896265236Sken		return;
1897265236Sken	}
1898265236Sken	if (targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT) {
1899283990Sslm		mpr_dprint(sc, MPR_ERROR, "%s Raid component no SCSI IO "
1900265236Sken		    "supported %u\n", __func__, csio->ccb_h.target_id);
1901283990Sslm		mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
1902265236Sken		xpt_done(ccb);
1903265236Sken		return;
1904265236Sken	}
1905265236Sken	/*
1906265236Sken	 * Sometimes, it is possible to get a command that is not "In
1907265236Sken	 * Progress" and was actually aborted by the upper layer.  Check for
1908265236Sken	 * this here and complete the command without error.
1909265236Sken	 */
1910283990Sslm	if (mprsas_get_ccbstatus(ccb) != CAM_REQ_INPROG) {
1911265236Sken		mpr_dprint(sc, MPR_TRACE, "%s Command is not in progress for "
1912265236Sken		    "target %u\n", __func__, csio->ccb_h.target_id);
1913265236Sken		xpt_done(ccb);
1914265236Sken		return;
1915265236Sken	}
1916265236Sken	/*
1917265236Sken	 * If devinfo is 0 this will be a volume.  In that case don't tell CAM
1918265236Sken	 * that the volume has timed out.  We want volumes to be enumerated
1919265236Sken	 * until they are deleted/removed, not just failed.
1920265236Sken	 */
1921265236Sken	if (targ->flags & MPRSAS_TARGET_INREMOVAL) {
1922265236Sken		if (targ->devinfo == 0)
1923283990Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
1924265236Sken		else
1925283990Sslm			mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT);
1926265236Sken		xpt_done(ccb);
1927265236Sken		return;
1928265236Sken	}
1929265236Sken
1930265236Sken	if ((sc->mpr_flags & MPR_FLAGS_SHUTDOWN) != 0) {
1931283990Sslm		mpr_dprint(sc, MPR_INFO, "%s shutting down\n", __func__);
1932283990Sslm		mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
1933265236Sken		xpt_done(ccb);
1934265236Sken		return;
1935265236Sken	}
1936265236Sken
1937283990Sslm	/*
1938283990Sslm	 * If target has a reset in progress, freeze the devq and return.  The
1939283990Sslm	 * devq will be released when the TM reset is finished.
1940283990Sslm	 */
1941283990Sslm	if (targ->flags & MPRSAS_TARGET_INRESET) {
1942283990Sslm		ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
1943283990Sslm		mpr_dprint(sc, MPR_INFO, "%s: Freezing devq for target ID %d\n",
1944283990Sslm		    __func__, targ->tid);
1945283990Sslm		xpt_freeze_devq(ccb->ccb_h.path, 1);
1946283990Sslm		xpt_done(ccb);
1947283990Sslm		return;
1948283990Sslm	}
1949283990Sslm
1950265236Sken	cm = mpr_alloc_command(sc);
1951265236Sken	if (cm == NULL || (sc->mpr_flags & MPR_FLAGS_DIAGRESET)) {
1952265236Sken		if (cm != NULL) {
1953265236Sken			mpr_free_command(sc, cm);
1954265236Sken		}
1955265236Sken		if ((sassc->flags & MPRSAS_QUEUE_FROZEN) == 0) {
1956265236Sken			xpt_freeze_simq(sassc->sim, 1);
1957265236Sken			sassc->flags |= MPRSAS_QUEUE_FROZEN;
1958265236Sken		}
1959265236Sken		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1960265236Sken		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
1961265236Sken		xpt_done(ccb);
1962265236Sken		return;
1963265236Sken	}
1964265236Sken
1965319436Sslm	/* For NVME device's issue UNMAP command directly to NVME drives by
1966319436Sslm	 * constructing equivalent native NVMe DataSetManagement command.
1967319436Sslm	 */
1968319436Sslm#if __FreeBSD_version >= 1100103
1969319436Sslm	scsi_opcode = scsiio_cdb_ptr(csio)[0];
1970319436Sslm#else
1971319436Sslm	if (csio->ccb_h.flags & CAM_CDB_POINTER)
1972319436Sslm		scsi_opcode = csio->cdb_io.cdb_ptr[0];
1973319436Sslm	else
1974319436Sslm		scsi_opcode = csio->cdb_io.cdb_bytes[0];
1975319436Sslm#endif
1976319436Sslm	if (scsi_opcode == UNMAP &&
1977319436Sslm	    targ->is_nvme &&
1978319436Sslm	    (csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
1979319436Sslm		rc = mprsas_build_nvme_unmap(sc, cm, ccb, targ);
1980319436Sslm		if (rc == 1) { /* return command to CAM with success status */
1981319436Sslm			mpr_free_command(sc, cm);
1982319436Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
1983319436Sslm			xpt_done(ccb);
1984319436Sslm			return;
1985319436Sslm		} else if (!rc) /* Issued NVMe Encapsulated Request Message */
1986319436Sslm			return;
1987319436Sslm	}
1988319436Sslm
1989265236Sken	req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req;
1990265236Sken	bzero(req, sizeof(*req));
1991265236Sken	req->DevHandle = htole16(targ->handle);
1992265236Sken	req->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
1993265236Sken	req->MsgFlags = 0;
1994265236Sken	req->SenseBufferLowAddress = htole32(cm->cm_sense_busaddr);
1995265236Sken	req->SenseBufferLength = MPR_SENSE_LEN;
1996265236Sken	req->SGLFlags = 0;
1997265236Sken	req->ChainOffset = 0;
1998265236Sken	req->SGLOffset0 = 24;	/* 32bit word offset to the SGL */
1999265236Sken	req->SGLOffset1= 0;
2000265236Sken	req->SGLOffset2= 0;
2001265236Sken	req->SGLOffset3= 0;
2002265236Sken	req->SkipCount = 0;
2003265236Sken	req->DataLength = htole32(csio->dxfer_len);
2004265236Sken	req->BidirectionalDataLength = 0;
2005265236Sken	req->IoFlags = htole16(csio->cdb_len);
2006265236Sken	req->EEDPFlags = 0;
2007265236Sken
2008265236Sken	/* Note: BiDirectional transfers are not supported */
2009265236Sken	switch (csio->ccb_h.flags & CAM_DIR_MASK) {
2010265236Sken	case CAM_DIR_IN:
2011265236Sken		mpi_control = MPI2_SCSIIO_CONTROL_READ;
2012265236Sken		cm->cm_flags |= MPR_CM_FLAGS_DATAIN;
2013265236Sken		break;
2014265236Sken	case CAM_DIR_OUT:
2015265236Sken		mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
2016265236Sken		cm->cm_flags |= MPR_CM_FLAGS_DATAOUT;
2017265236Sken		break;
2018265236Sken	case CAM_DIR_NONE:
2019265236Sken	default:
2020265236Sken		mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
2021265236Sken		break;
2022265236Sken	}
2023265236Sken
2024265236Sken	if (csio->cdb_len == 32)
2025265236Sken		mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
2026265236Sken	/*
2027265236Sken	 * It looks like the hardware doesn't require an explicit tag
2028265236Sken	 * number for each transaction.  SAM Task Management not supported
2029265236Sken	 * at the moment.
2030265236Sken	 */
2031265236Sken	switch (csio->tag_action) {
2032265236Sken	case MSG_HEAD_OF_Q_TAG:
2033265236Sken		mpi_control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
2034265236Sken		break;
2035265236Sken	case MSG_ORDERED_Q_TAG:
2036265236Sken		mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
2037265236Sken		break;
2038265236Sken	case MSG_ACA_TASK:
2039265236Sken		mpi_control |= MPI2_SCSIIO_CONTROL_ACAQ;
2040265236Sken		break;
2041265236Sken	case CAM_TAG_ACTION_NONE:
2042265236Sken	case MSG_SIMPLE_Q_TAG:
2043265236Sken	default:
2044265236Sken		mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
2045265236Sken		break;
2046265236Sken	}
2047265236Sken	mpi_control |= sc->mapping_table[csio->ccb_h.target_id].TLR_bits;
2048265236Sken	req->Control = htole32(mpi_control);
2049265236Sken
2050265236Sken	if (MPR_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) {
2051265236Sken		mpr_free_command(sc, cm);
2052283990Sslm		mprsas_set_ccbstatus(ccb, CAM_LUN_INVALID);
2053265236Sken		xpt_done(ccb);
2054265236Sken		return;
2055265236Sken	}
2056265236Sken
2057265236Sken	if (csio->ccb_h.flags & CAM_CDB_POINTER)
2058265236Sken		bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len);
2059313103Sasomers	else {
2060313103Sasomers		KASSERT(csio->cdb_len <= IOCDBLEN,
2061319436Sslm		    ("cdb_len %d is greater than IOCDBLEN but CAM_CDB_POINTER "
2062319436Sslm		    "is not set", csio->cdb_len));
2063265236Sken		bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len);
2064313103Sasomers	}
2065265236Sken	req->IoFlags = htole16(csio->cdb_len);
2066265236Sken
2067265236Sken	/*
2068265236Sken	 * Check if EEDP is supported and enabled.  If it is then check if the
2069265236Sken	 * SCSI opcode could be using EEDP.  If so, make sure the LUN exists and
2070265236Sken	 * is formatted for EEDP support.  If all of this is true, set CDB up
2071265236Sken	 * for EEDP transfer.
2072265236Sken	 */
2073265236Sken	eedp_flags = op_code_prot[req->CDB.CDB32[0]];
2074265236Sken	if (sc->eedp_enabled && eedp_flags) {
2075265236Sken		SLIST_FOREACH(lun, &targ->luns, lun_link) {
2076265236Sken			if (lun->lun_id == csio->ccb_h.target_lun) {
2077265236Sken				break;
2078265236Sken			}
2079265236Sken		}
2080265236Sken
2081265236Sken		if ((lun != NULL) && (lun->eedp_formatted)) {
2082265236Sken			req->EEDPBlockSize = htole16(lun->eedp_block_size);
2083265236Sken			eedp_flags |= (MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
2084265236Sken			    MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
2085265236Sken			    MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD);
2086319436Sslm			if (sc->mpr_flags & MPR_FLAGS_GEN35_IOC) {
2087319436Sslm				eedp_flags |=
2088319436Sslm				    MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE;
2089319436Sslm			}
2090265236Sken			req->EEDPFlags = htole16(eedp_flags);
2091265236Sken
2092265236Sken			/*
2093265236Sken			 * If CDB less than 32, fill in Primary Ref Tag with
2094265236Sken			 * low 4 bytes of LBA.  If CDB is 32, tag stuff is
2095265236Sken			 * already there.  Also, set protection bit.  FreeBSD
2096265236Sken			 * currently does not support CDBs bigger than 16, but
2097265236Sken			 * the code doesn't hurt, and will be here for the
2098265236Sken			 * future.
2099265236Sken			 */
2100265236Sken			if (csio->cdb_len != 32) {
2101265236Sken				lba_byte = (csio->cdb_len == 16) ? 6 : 2;
2102265236Sken				ref_tag_addr = (uint8_t *)&req->CDB.EEDP32.
2103265236Sken				    PrimaryReferenceTag;
2104265236Sken				for (i = 0; i < 4; i++) {
2105265236Sken					*ref_tag_addr =
2106265236Sken					    req->CDB.CDB32[lba_byte + i];
2107265236Sken					ref_tag_addr++;
2108265236Sken				}
2109265236Sken				req->CDB.EEDP32.PrimaryReferenceTag =
2110265236Sken				    htole32(req->
2111265236Sken				    CDB.EEDP32.PrimaryReferenceTag);
2112265236Sken				req->CDB.EEDP32.PrimaryApplicationTagMask =
2113265236Sken				    0xFFFF;
2114265236Sken				req->CDB.CDB32[1] = (req->CDB.CDB32[1] & 0x1F) |
2115265236Sken				    0x20;
2116265236Sken			} else {
2117265236Sken				eedp_flags |=
2118265236Sken				    MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG;
2119265236Sken				req->EEDPFlags = htole16(eedp_flags);
2120265236Sken				req->CDB.CDB32[10] = (req->CDB.CDB32[10] &
2121265236Sken				    0x1F) | 0x20;
2122265236Sken			}
2123265236Sken		}
2124265236Sken	}
2125265236Sken
2126265236Sken	cm->cm_length = csio->dxfer_len;
2127265236Sken	if (cm->cm_length != 0) {
2128265236Sken		cm->cm_data = ccb;
2129265236Sken		cm->cm_flags |= MPR_CM_FLAGS_USE_CCB;
2130265236Sken	} else {
2131265236Sken		cm->cm_data = NULL;
2132265236Sken	}
2133265236Sken	cm->cm_sge = &req->SGL;
2134265236Sken	cm->cm_sglsize = (32 - 24) * 4;
2135265236Sken	cm->cm_complete = mprsas_scsiio_complete;
2136265236Sken	cm->cm_complete_data = ccb;
2137265236Sken	cm->cm_targ = targ;
2138265236Sken	cm->cm_lun = csio->ccb_h.target_lun;
2139265236Sken	cm->cm_ccb = ccb;
2140265236Sken	/*
2141265236Sken	 * If using FP desc type, need to set a bit in IoFlags (SCSI IO is 0)
2142265236Sken	 * and set descriptor type.
2143265236Sken	 */
2144265236Sken	if (targ->scsi_req_desc_type ==
2145265236Sken	    MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO) {
2146265236Sken		req->IoFlags |= MPI25_SCSIIO_IOFLAGS_FAST_PATH;
2147265236Sken		cm->cm_desc.FastPathSCSIIO.RequestFlags =
2148265236Sken		    MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
2149319436Sslm		if (!sc->atomic_desc_capable) {
2150319436Sslm			cm->cm_desc.FastPathSCSIIO.DevHandle =
2151319436Sslm			    htole16(targ->handle);
2152319436Sslm		}
2153265236Sken	} else {
2154265236Sken		cm->cm_desc.SCSIIO.RequestFlags =
2155265236Sken		    MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
2156319436Sslm		if (!sc->atomic_desc_capable)
2157319436Sslm			cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle);
2158265236Sken	}
2159265236Sken
2160299962Sslm#if __FreeBSD_version >= 1000029
2161275982Ssmh	callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0,
2162283990Sslm	    mprsas_scsiio_timeout, cm, 0);
2163299962Sslm#else //__FreeBSD_version < 1000029
2164299962Sslm	callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000,
2165299962Sslm	    mprsas_scsiio_timeout, cm);
2166299962Sslm#endif //__FreeBSD_version >= 1000029
2167265236Sken
2168265236Sken	targ->issued++;
2169265236Sken	targ->outstanding++;
2170265236Sken	TAILQ_INSERT_TAIL(&targ->commands, cm, cm_link);
2171265236Sken	ccb->ccb_h.status |= CAM_SIM_QUEUED;
2172265236Sken
2173265236Sken	mprsas_log_command(cm, MPR_XINFO, "%s cm %p ccb %p outstanding %u\n",
2174265236Sken	    __func__, cm, ccb, targ->outstanding);
2175265236Sken
2176265236Sken	mpr_map_command(sc, cm);
2177265236Sken	return;
2178265236Sken}
2179265236Sken
2180265236Skenstatic void
2181265236Skenmpr_response_code(struct mpr_softc *sc, u8 response_code)
2182265236Sken{
2183265236Sken        char *desc;
2184265236Sken
2185265236Sken        switch (response_code) {
2186265236Sken        case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
2187265236Sken                desc = "task management request completed";
2188265236Sken                break;
2189265236Sken        case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
2190265236Sken                desc = "invalid frame";
2191265236Sken                break;
2192265236Sken        case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2193265236Sken                desc = "task management request not supported";
2194265236Sken                break;
2195265236Sken        case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
2196265236Sken                desc = "task management request failed";
2197265236Sken                break;
2198265236Sken        case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2199265236Sken                desc = "task management request succeeded";
2200265236Sken                break;
2201265236Sken        case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2202265236Sken                desc = "invalid lun";
2203265236Sken                break;
2204265236Sken        case 0xA:
2205265236Sken                desc = "overlapped tag attempted";
2206265236Sken                break;
2207265236Sken        case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2208265236Sken                desc = "task queued, however not sent to target";
2209265236Sken                break;
2210265236Sken        default:
2211265236Sken                desc = "unknown";
2212265236Sken                break;
2213265236Sken        }
2214265236Sken	mpr_dprint(sc, MPR_XINFO, "response_code(0x%01x): %s\n", response_code,
2215265236Sken	    desc);
2216265236Sken}
2217265236Sken
2218265236Sken/**
2219265236Sken * mpr_sc_failed_io_info - translated non-succesfull SCSI_IO request
2220265236Sken */
2221265236Skenstatic void
2222265236Skenmpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio,
2223265236Sken    Mpi2SCSIIOReply_t *mpi_reply, struct mprsas_target *targ)
2224265236Sken{
2225265236Sken	u32 response_info;
2226265236Sken	u8 *response_bytes;
2227265236Sken	u16 ioc_status = le16toh(mpi_reply->IOCStatus) &
2228265236Sken	    MPI2_IOCSTATUS_MASK;
2229265236Sken	u8 scsi_state = mpi_reply->SCSIState;
2230265236Sken	u8 scsi_status = mpi_reply->SCSIStatus;
2231265236Sken	char *desc_ioc_state = NULL;
2232265236Sken	char *desc_scsi_status = NULL;
2233265236Sken	char *desc_scsi_state = sc->tmp_string;
2234265236Sken	u32 log_info = le32toh(mpi_reply->IOCLogInfo);
2235265236Sken
2236265236Sken	if (log_info == 0x31170000)
2237265236Sken		return;
2238265236Sken
2239265236Sken	switch (ioc_status) {
2240265236Sken	case MPI2_IOCSTATUS_SUCCESS:
2241265236Sken		desc_ioc_state = "success";
2242265236Sken		break;
2243265236Sken	case MPI2_IOCSTATUS_INVALID_FUNCTION:
2244265236Sken		desc_ioc_state = "invalid function";
2245265236Sken		break;
2246265236Sken	case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
2247265236Sken		desc_ioc_state = "scsi recovered error";
2248265236Sken		break;
2249265236Sken	case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
2250265236Sken		desc_ioc_state = "scsi invalid dev handle";
2251265236Sken		break;
2252265236Sken	case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
2253265236Sken		desc_ioc_state = "scsi device not there";
2254265236Sken		break;
2255265236Sken	case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
2256265236Sken		desc_ioc_state = "scsi data overrun";
2257265236Sken		break;
2258265236Sken	case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
2259265236Sken		desc_ioc_state = "scsi data underrun";
2260265236Sken		break;
2261265236Sken	case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
2262265236Sken		desc_ioc_state = "scsi io data error";
2263265236Sken		break;
2264265236Sken	case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
2265265236Sken		desc_ioc_state = "scsi protocol error";
2266265236Sken		break;
2267265236Sken	case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
2268265236Sken		desc_ioc_state = "scsi task terminated";
2269265236Sken		break;
2270265236Sken	case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
2271265236Sken		desc_ioc_state = "scsi residual mismatch";
2272265236Sken		break;
2273265236Sken	case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
2274265236Sken		desc_ioc_state = "scsi task mgmt failed";
2275265236Sken		break;
2276265236Sken	case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
2277265236Sken		desc_ioc_state = "scsi ioc terminated";
2278265236Sken		break;
2279265236Sken	case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
2280265236Sken		desc_ioc_state = "scsi ext terminated";
2281265236Sken		break;
2282265236Sken	case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
2283265236Sken		desc_ioc_state = "eedp guard error";
2284265236Sken		break;
2285265236Sken	case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
2286265236Sken		desc_ioc_state = "eedp ref tag error";
2287265236Sken		break;
2288265236Sken	case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
2289265236Sken		desc_ioc_state = "eedp app tag error";
2290265236Sken		break;
2291299962Sslm	case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
2292299962Sslm		desc_ioc_state = "insufficient power";
2293299962Sslm		break;
2294265236Sken	default:
2295265236Sken		desc_ioc_state = "unknown";
2296265236Sken		break;
2297265236Sken	}
2298265236Sken
2299265236Sken	switch (scsi_status) {
2300265236Sken	case MPI2_SCSI_STATUS_GOOD:
2301265236Sken		desc_scsi_status = "good";
2302265236Sken		break;
2303265236Sken	case MPI2_SCSI_STATUS_CHECK_CONDITION:
2304265236Sken		desc_scsi_status = "check condition";
2305265236Sken		break;
2306265236Sken	case MPI2_SCSI_STATUS_CONDITION_MET:
2307265236Sken		desc_scsi_status = "condition met";
2308265236Sken		break;
2309265236Sken	case MPI2_SCSI_STATUS_BUSY:
2310265236Sken		desc_scsi_status = "busy";
2311265236Sken		break;
2312265236Sken	case MPI2_SCSI_STATUS_INTERMEDIATE:
2313265236Sken		desc_scsi_status = "intermediate";
2314265236Sken		break;
2315265236Sken	case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
2316265236Sken		desc_scsi_status = "intermediate condmet";
2317265236Sken		break;
2318265236Sken	case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
2319265236Sken		desc_scsi_status = "reservation conflict";
2320265236Sken		break;
2321265236Sken	case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
2322265236Sken		desc_scsi_status = "command terminated";
2323265236Sken		break;
2324265236Sken	case MPI2_SCSI_STATUS_TASK_SET_FULL:
2325265236Sken		desc_scsi_status = "task set full";
2326265236Sken		break;
2327265236Sken	case MPI2_SCSI_STATUS_ACA_ACTIVE:
2328265236Sken		desc_scsi_status = "aca active";
2329265236Sken		break;
2330265236Sken	case MPI2_SCSI_STATUS_TASK_ABORTED:
2331265236Sken		desc_scsi_status = "task aborted";
2332265236Sken		break;
2333265236Sken	default:
2334265236Sken		desc_scsi_status = "unknown";
2335265236Sken		break;
2336265236Sken	}
2337265236Sken
2338265236Sken	desc_scsi_state[0] = '\0';
2339265236Sken	if (!scsi_state)
2340265236Sken		desc_scsi_state = " ";
2341265236Sken	if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
2342265236Sken		strcat(desc_scsi_state, "response info ");
2343265236Sken	if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
2344265236Sken		strcat(desc_scsi_state, "state terminated ");
2345265236Sken	if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
2346265236Sken		strcat(desc_scsi_state, "no status ");
2347265236Sken	if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
2348265236Sken		strcat(desc_scsi_state, "autosense failed ");
2349265236Sken	if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
2350265236Sken		strcat(desc_scsi_state, "autosense valid ");
2351265236Sken
2352265236Sken	mpr_dprint(sc, MPR_XINFO, "\thandle(0x%04x), ioc_status(%s)(0x%04x)\n",
2353265236Sken	    le16toh(mpi_reply->DevHandle), desc_ioc_state, ioc_status);
2354265236Sken	if (targ->encl_level_valid) {
2355265236Sken		mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, "
2356265236Sken		    "connector name (%4s)\n", targ->encl_level, targ->encl_slot,
2357265236Sken		    targ->connector_name);
2358265236Sken	}
2359265236Sken	/* We can add more detail about underflow data here
2360265236Sken	 * TO-DO
2361265236Sken	 * */
2362265236Sken	mpr_dprint(sc, MPR_XINFO, "\tscsi_status(%s)(0x%02x), "
2363265236Sken	    "scsi_state(%s)(0x%02x)\n", desc_scsi_status, scsi_status,
2364265236Sken	    desc_scsi_state, scsi_state);
2365265236Sken
2366265236Sken	if (sc->mpr_debug & MPR_XINFO &&
2367283990Sslm	    scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
2368265236Sken		mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : Start :\n");
2369265236Sken		scsi_sense_print(csio);
2370265236Sken		mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : End :\n");
2371265236Sken	}
2372265236Sken
2373265236Sken	if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
2374265236Sken		response_info = le32toh(mpi_reply->ResponseInfo);
2375265236Sken		response_bytes = (u8 *)&response_info;
2376265236Sken		mpr_response_code(sc,response_bytes[0]);
2377265236Sken	}
2378265236Sken}
2379265236Sken
2380319436Sslm/** mprsas_nvme_trans_status_code
2381319436Sslm *
2382319436Sslm * Convert Native NVMe command error status to
2383319436Sslm * equivalent SCSI error status.
2384319436Sslm *
2385319436Sslm * Returns appropriate scsi_status
2386319436Sslm */
2387319436Sslmstatic u8
2388319436Sslmmprsas_nvme_trans_status_code(struct nvme_status nvme_status,
2389319436Sslm    struct mpr_command *cm)
2390319436Sslm{
2391319436Sslm	u8 status = MPI2_SCSI_STATUS_GOOD;
2392319436Sslm	int skey, asc, ascq;
2393319436Sslm	union ccb *ccb = cm->cm_complete_data;
2394319436Sslm	int returned_sense_len;
2395319436Sslm
2396319436Sslm	status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2397319436Sslm	skey = SSD_KEY_ILLEGAL_REQUEST;
2398319436Sslm	asc = SCSI_ASC_NO_SENSE;
2399319436Sslm	ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2400319436Sslm
2401319436Sslm	switch (nvme_status.sct) {
2402319436Sslm	case NVME_SCT_GENERIC:
2403319436Sslm		switch (nvme_status.sc) {
2404319436Sslm		case NVME_SC_SUCCESS:
2405319436Sslm			status = MPI2_SCSI_STATUS_GOOD;
2406319436Sslm			skey = SSD_KEY_NO_SENSE;
2407319436Sslm			asc = SCSI_ASC_NO_SENSE;
2408319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2409319436Sslm			break;
2410319436Sslm		case NVME_SC_INVALID_OPCODE:
2411319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2412319436Sslm			skey = SSD_KEY_ILLEGAL_REQUEST;
2413319436Sslm			asc = SCSI_ASC_ILLEGAL_COMMAND;
2414319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2415319436Sslm			break;
2416319436Sslm		case NVME_SC_INVALID_FIELD:
2417319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2418319436Sslm			skey = SSD_KEY_ILLEGAL_REQUEST;
2419319436Sslm			asc = SCSI_ASC_INVALID_CDB;
2420319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2421319436Sslm			break;
2422319436Sslm		case NVME_SC_DATA_TRANSFER_ERROR:
2423319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2424319436Sslm			skey = SSD_KEY_MEDIUM_ERROR;
2425319436Sslm			asc = SCSI_ASC_NO_SENSE;
2426319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2427319436Sslm			break;
2428319436Sslm		case NVME_SC_ABORTED_POWER_LOSS:
2429319436Sslm			status = MPI2_SCSI_STATUS_TASK_ABORTED;
2430319436Sslm			skey = SSD_KEY_ABORTED_COMMAND;
2431319436Sslm			asc = SCSI_ASC_WARNING;
2432319436Sslm			ascq = SCSI_ASCQ_POWER_LOSS_EXPECTED;
2433319436Sslm			break;
2434319436Sslm		case NVME_SC_INTERNAL_DEVICE_ERROR:
2435319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2436319436Sslm			skey = SSD_KEY_HARDWARE_ERROR;
2437319436Sslm			asc = SCSI_ASC_INTERNAL_TARGET_FAILURE;
2438319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2439319436Sslm			break;
2440319436Sslm		case NVME_SC_ABORTED_BY_REQUEST:
2441319436Sslm		case NVME_SC_ABORTED_SQ_DELETION:
2442319436Sslm		case NVME_SC_ABORTED_FAILED_FUSED:
2443319436Sslm		case NVME_SC_ABORTED_MISSING_FUSED:
2444319436Sslm			status = MPI2_SCSI_STATUS_TASK_ABORTED;
2445319436Sslm			skey = SSD_KEY_ABORTED_COMMAND;
2446319436Sslm			asc = SCSI_ASC_NO_SENSE;
2447319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2448319436Sslm			break;
2449319436Sslm		case NVME_SC_INVALID_NAMESPACE_OR_FORMAT:
2450319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2451319436Sslm			skey = SSD_KEY_ILLEGAL_REQUEST;
2452319436Sslm			asc = SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID;
2453319436Sslm			ascq = SCSI_ASCQ_INVALID_LUN_ID;
2454319436Sslm			break;
2455319436Sslm		case NVME_SC_LBA_OUT_OF_RANGE:
2456319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2457319436Sslm			skey = SSD_KEY_ILLEGAL_REQUEST;
2458319436Sslm			asc = SCSI_ASC_ILLEGAL_BLOCK;
2459319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2460319436Sslm			break;
2461319436Sslm		case NVME_SC_CAPACITY_EXCEEDED:
2462319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2463319436Sslm			skey = SSD_KEY_MEDIUM_ERROR;
2464319436Sslm			asc = SCSI_ASC_NO_SENSE;
2465319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2466319436Sslm			break;
2467319436Sslm		case NVME_SC_NAMESPACE_NOT_READY:
2468319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2469319436Sslm			skey = SSD_KEY_NOT_READY;
2470319436Sslm			asc = SCSI_ASC_LUN_NOT_READY;
2471319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2472319436Sslm			break;
2473319436Sslm		}
2474319436Sslm		break;
2475319436Sslm	case NVME_SCT_COMMAND_SPECIFIC:
2476319436Sslm		switch (nvme_status.sc) {
2477319436Sslm		case NVME_SC_INVALID_FORMAT:
2478319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2479319436Sslm			skey = SSD_KEY_ILLEGAL_REQUEST;
2480319436Sslm			asc = SCSI_ASC_FORMAT_COMMAND_FAILED;
2481319436Sslm			ascq = SCSI_ASCQ_FORMAT_COMMAND_FAILED;
2482319436Sslm			break;
2483319436Sslm		case NVME_SC_CONFLICTING_ATTRIBUTES:
2484319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2485319436Sslm			skey = SSD_KEY_ILLEGAL_REQUEST;
2486319436Sslm			asc = SCSI_ASC_INVALID_CDB;
2487319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2488319436Sslm			break;
2489319436Sslm		}
2490319436Sslm		break;
2491319436Sslm	case NVME_SCT_MEDIA_ERROR:
2492319436Sslm		switch (nvme_status.sc) {
2493319436Sslm		case NVME_SC_WRITE_FAULTS:
2494319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2495319436Sslm			skey = SSD_KEY_MEDIUM_ERROR;
2496319436Sslm			asc = SCSI_ASC_PERIPHERAL_DEV_WRITE_FAULT;
2497319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2498319436Sslm			break;
2499319436Sslm		case NVME_SC_UNRECOVERED_READ_ERROR:
2500319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2501319436Sslm			skey = SSD_KEY_MEDIUM_ERROR;
2502319436Sslm			asc = SCSI_ASC_UNRECOVERED_READ_ERROR;
2503319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2504319436Sslm			break;
2505319436Sslm		case NVME_SC_GUARD_CHECK_ERROR:
2506319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2507319436Sslm			skey = SSD_KEY_MEDIUM_ERROR;
2508319436Sslm			asc = SCSI_ASC_LOG_BLOCK_GUARD_CHECK_FAILED;
2509319436Sslm			ascq = SCSI_ASCQ_LOG_BLOCK_GUARD_CHECK_FAILED;
2510319436Sslm			break;
2511319436Sslm		case NVME_SC_APPLICATION_TAG_CHECK_ERROR:
2512319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2513319436Sslm			skey = SSD_KEY_MEDIUM_ERROR;
2514319436Sslm			asc = SCSI_ASC_LOG_BLOCK_APPTAG_CHECK_FAILED;
2515319436Sslm			ascq = SCSI_ASCQ_LOG_BLOCK_APPTAG_CHECK_FAILED;
2516319436Sslm			break;
2517319436Sslm		case NVME_SC_REFERENCE_TAG_CHECK_ERROR:
2518319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2519319436Sslm			skey = SSD_KEY_MEDIUM_ERROR;
2520319436Sslm			asc = SCSI_ASC_LOG_BLOCK_REFTAG_CHECK_FAILED;
2521319436Sslm			ascq = SCSI_ASCQ_LOG_BLOCK_REFTAG_CHECK_FAILED;
2522319436Sslm			break;
2523319436Sslm		case NVME_SC_COMPARE_FAILURE:
2524319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2525319436Sslm			skey = SSD_KEY_MISCOMPARE;
2526319436Sslm			asc = SCSI_ASC_MISCOMPARE_DURING_VERIFY;
2527319436Sslm			ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
2528319436Sslm			break;
2529319436Sslm		case NVME_SC_ACCESS_DENIED:
2530319436Sslm			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
2531319436Sslm			skey = SSD_KEY_ILLEGAL_REQUEST;
2532319436Sslm			asc = SCSI_ASC_ACCESS_DENIED_INVALID_LUN_ID;
2533319436Sslm			ascq = SCSI_ASCQ_INVALID_LUN_ID;
2534319436Sslm			break;
2535319436Sslm		}
2536319436Sslm		break;
2537319436Sslm	}
2538319436Sslm
2539319436Sslm	returned_sense_len = sizeof(struct scsi_sense_data);
2540319436Sslm	if (returned_sense_len < ccb->csio.sense_len)
2541319436Sslm		ccb->csio.sense_resid = ccb->csio.sense_len -
2542319436Sslm		    returned_sense_len;
2543319436Sslm	else
2544319436Sslm		ccb->csio.sense_resid = 0;
2545319436Sslm
2546319436Sslm	scsi_set_sense_data(&ccb->csio.sense_data, SSD_TYPE_FIXED,
2547319436Sslm	    1, skey, asc, ascq, SSD_ELEM_NONE);
2548319436Sslm	ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
2549319436Sslm
2550319436Sslm	return status;
2551319436Sslm}
2552319436Sslm
2553319436Sslm/** mprsas_complete_nvme_unmap
2554319436Sslm *
2555319436Sslm * Complete native NVMe command issued using NVMe Encapsulated
2556319436Sslm * Request Message.
2557319436Sslm */
2558319436Sslmstatic u8
2559319436Sslmmprsas_complete_nvme_unmap(struct mpr_softc *sc, struct mpr_command *cm)
2560319436Sslm{
2561319436Sslm	Mpi26NVMeEncapsulatedErrorReply_t *mpi_reply;
2562319436Sslm	struct nvme_completion *nvme_completion = NULL;
2563319436Sslm	u8 scsi_status = MPI2_SCSI_STATUS_GOOD;
2564319436Sslm
2565319436Sslm	mpi_reply =(Mpi26NVMeEncapsulatedErrorReply_t *)cm->cm_reply;
2566319436Sslm	if (le16toh(mpi_reply->ErrorResponseCount)){
2567319436Sslm		nvme_completion = (struct nvme_completion *)cm->cm_sense;
2568319436Sslm		scsi_status = mprsas_nvme_trans_status_code(
2569319436Sslm		    nvme_completion->status, cm);
2570319436Sslm	}
2571319436Sslm	return scsi_status;
2572319436Sslm}
2573319436Sslm
2574265236Skenstatic void
2575265236Skenmprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm)
2576265236Sken{
2577265236Sken	MPI2_SCSI_IO_REPLY *rep;
2578265236Sken	union ccb *ccb;
2579265236Sken	struct ccb_scsiio *csio;
2580265236Sken	struct mprsas_softc *sassc;
2581265236Sken	struct scsi_vpd_supported_page_list *vpd_list = NULL;
2582319436Sslm	u8 *TLR_bits, TLR_on, *scsi_cdb;
2583265236Sken	int dir = 0, i;
2584265236Sken	u16 alloc_len;
2585283990Sslm	struct mprsas_target *target;
2586283990Sslm	target_id_t target_id;
2587265236Sken
2588265236Sken	MPR_FUNCTRACE(sc);
2589265236Sken	mpr_dprint(sc, MPR_TRACE,
2590265236Sken	    "cm %p SMID %u ccb %p reply %p outstanding %u\n", cm,
2591265236Sken	    cm->cm_desc.Default.SMID, cm->cm_ccb, cm->cm_reply,
2592265236Sken	    cm->cm_targ->outstanding);
2593265236Sken
2594265236Sken	callout_stop(&cm->cm_callout);
2595265236Sken	mtx_assert(&sc->mpr_mtx, MA_OWNED);
2596265236Sken
2597265236Sken	sassc = sc->sassc;
2598265236Sken	ccb = cm->cm_complete_data;
2599265236Sken	csio = &ccb->csio;
2600283990Sslm	target_id = csio->ccb_h.target_id;
2601265236Sken	rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply;
2602265236Sken	/*
2603265236Sken	 * XXX KDM if the chain allocation fails, does it matter if we do
2604265236Sken	 * the sync and unload here?  It is simpler to do it in every case,
2605265236Sken	 * assuming it doesn't cause problems.
2606265236Sken	 */
2607265236Sken	if (cm->cm_data != NULL) {
2608265236Sken		if (cm->cm_flags & MPR_CM_FLAGS_DATAIN)
2609265236Sken			dir = BUS_DMASYNC_POSTREAD;
2610265236Sken		else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT)
2611265236Sken			dir = BUS_DMASYNC_POSTWRITE;
2612265236Sken		bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
2613265236Sken		bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
2614265236Sken	}
2615265236Sken
2616265236Sken	cm->cm_targ->completed++;
2617265236Sken	cm->cm_targ->outstanding--;
2618265236Sken	TAILQ_REMOVE(&cm->cm_targ->commands, cm, cm_link);
2619265236Sken	ccb->ccb_h.status &= ~(CAM_STATUS_MASK | CAM_SIM_QUEUED);
2620265236Sken
2621265236Sken	if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) {
2622265236Sken		TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery);
2623265236Sken		if (cm->cm_reply != NULL)
2624265236Sken			mprsas_log_command(cm, MPR_RECOVERY,
2625265236Sken			    "completed timedout cm %p ccb %p during recovery "
2626265236Sken			    "ioc %x scsi %x state %x xfer %u\n", cm, cm->cm_ccb,
2627265236Sken			    le16toh(rep->IOCStatus), rep->SCSIStatus,
2628265236Sken			    rep->SCSIState, le32toh(rep->TransferCount));
2629265236Sken		else
2630265236Sken			mprsas_log_command(cm, MPR_RECOVERY,
2631265236Sken			    "completed timedout cm %p ccb %p during recovery\n",
2632265236Sken			    cm, cm->cm_ccb);
2633265236Sken	} else if (cm->cm_targ->tm != NULL) {
2634265236Sken		if (cm->cm_reply != NULL)
2635265236Sken			mprsas_log_command(cm, MPR_RECOVERY,
2636265236Sken			    "completed cm %p ccb %p during recovery "
2637265236Sken			    "ioc %x scsi %x state %x xfer %u\n",
2638265236Sken			    cm, cm->cm_ccb, le16toh(rep->IOCStatus),
2639265236Sken			    rep->SCSIStatus, rep->SCSIState,
2640265236Sken			    le32toh(rep->TransferCount));
2641265236Sken		else
2642265236Sken			mprsas_log_command(cm, MPR_RECOVERY,
2643265236Sken			    "completed cm %p ccb %p during recovery\n",
2644265236Sken			    cm, cm->cm_ccb);
2645265236Sken	} else if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) {
2646265236Sken		mprsas_log_command(cm, MPR_RECOVERY,
2647265236Sken		    "reset completed cm %p ccb %p\n", cm, cm->cm_ccb);
2648265236Sken	}
2649265236Sken
2650265236Sken	if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
2651265236Sken		/*
2652265236Sken		 * We ran into an error after we tried to map the command,
2653265236Sken		 * so we're getting a callback without queueing the command
2654265236Sken		 * to the hardware.  So we set the status here, and it will
2655265236Sken		 * be retained below.  We'll go through the "fast path",
2656265236Sken		 * because there can be no reply when we haven't actually
2657265236Sken		 * gone out to the hardware.
2658265236Sken		 */
2659283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ);
2660265236Sken
2661265236Sken		/*
2662265236Sken		 * Currently the only error included in the mask is
2663265236Sken		 * MPR_CM_FLAGS_CHAIN_FAILED, which means we're out of
2664265236Sken		 * chain frames.  We need to freeze the queue until we get
2665265236Sken		 * a command that completed without this error, which will
2666265236Sken		 * hopefully have some chain frames attached that we can
2667265236Sken		 * use.  If we wanted to get smarter about it, we would
2668265236Sken		 * only unfreeze the queue in this condition when we're
2669265236Sken		 * sure that we're getting some chain frames back.  That's
2670265236Sken		 * probably unnecessary.
2671265236Sken		 */
2672265236Sken		if ((sassc->flags & MPRSAS_QUEUE_FROZEN) == 0) {
2673265236Sken			xpt_freeze_simq(sassc->sim, 1);
2674265236Sken			sassc->flags |= MPRSAS_QUEUE_FROZEN;
2675322661Sken			mpr_dprint(sc, MPR_XINFO, "Error sending command, "
2676283990Sslm			    "freezing SIM queue\n");
2677265236Sken		}
2678265236Sken	}
2679265236Sken
2680265236Sken	/*
2681319436Sslm	 * Point to the SCSI CDB, which is dependent on the CAM_CDB_POINTER
2682319436Sslm	 * flag, and use it in a few places in the rest of this function for
2683319436Sslm	 * convenience. Use the macro if available.
2684319436Sslm	 */
2685319436Sslm#if __FreeBSD_version >= 1100103
2686319436Sslm	scsi_cdb = scsiio_cdb_ptr(csio);
2687319436Sslm#else
2688319436Sslm	if (csio->ccb_h.flags & CAM_CDB_POINTER)
2689319436Sslm		scsi_cdb = csio->cdb_io.cdb_ptr;
2690319436Sslm	else
2691319436Sslm		scsi_cdb = csio->cdb_io.cdb_bytes;
2692319436Sslm#endif
2693319436Sslm
2694319436Sslm	/*
2695265236Sken	 * If this is a Start Stop Unit command and it was issued by the driver
2696265236Sken	 * during shutdown, decrement the refcount to account for all of the
2697265236Sken	 * commands that were sent.  All SSU commands should be completed before
2698265236Sken	 * shutdown completes, meaning SSU_refcount will be 0 after SSU_started
2699265236Sken	 * is TRUE.
2700283990Sslm	 */
2701319436Sslm	if (sc->SSU_started && (scsi_cdb[0] == START_STOP_UNIT)) {
2702265236Sken		mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n");
2703265236Sken		sc->SSU_refcount--;
2704265236Sken	}
2705265236Sken
2706265236Sken	/* Take the fast path to completion */
2707265236Sken	if (cm->cm_reply == NULL) {
2708283990Sslm		if (mprsas_get_ccbstatus(ccb) == CAM_REQ_INPROG) {
2709265236Sken			if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0)
2710283990Sslm				mprsas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET);
2711265236Sken			else {
2712283990Sslm				mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
2713283990Sslm				csio->scsi_status = SCSI_STATUS_OK;
2714265236Sken			}
2715265236Sken			if (sassc->flags & MPRSAS_QUEUE_FROZEN) {
2716265236Sken				ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
2717265236Sken				sassc->flags &= ~MPRSAS_QUEUE_FROZEN;
2718265236Sken				mpr_dprint(sc, MPR_XINFO,
2719265236Sken				    "Unfreezing SIM queue\n");
2720265236Sken			}
2721265236Sken		}
2722265236Sken
2723265236Sken		/*
2724265236Sken		 * There are two scenarios where the status won't be
2725265236Sken		 * CAM_REQ_CMP.  The first is if MPR_CM_FLAGS_ERROR_MASK is
2726265236Sken		 * set, the second is in the MPR_FLAGS_DIAGRESET above.
2727265236Sken		 */
2728283990Sslm		if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) {
2729265236Sken			/*
2730265236Sken			 * Freeze the dev queue so that commands are
2731283990Sslm			 * executed in the correct order after error
2732265236Sken			 * recovery.
2733265236Sken			 */
2734265236Sken			ccb->ccb_h.status |= CAM_DEV_QFRZN;
2735265236Sken			xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1);
2736265236Sken		}
2737265236Sken		mpr_free_command(sc, cm);
2738265236Sken		xpt_done(ccb);
2739265236Sken		return;
2740265236Sken	}
2741265236Sken
2742319436Sslm	target = &sassc->targets[target_id];
2743319436Sslm	if (scsi_cdb[0] == UNMAP &&
2744319436Sslm	    target->is_nvme &&
2745319436Sslm	    (csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
2746319436Sslm		rep->SCSIStatus = mprsas_complete_nvme_unmap(sc, cm);
2747319436Sslm		csio->scsi_status = rep->SCSIStatus;
2748319436Sslm	}
2749319436Sslm
2750265236Sken	mprsas_log_command(cm, MPR_XINFO,
2751265236Sken	    "ioc %x scsi %x state %x xfer %u\n",
2752265236Sken	    le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState,
2753265236Sken	    le32toh(rep->TransferCount));
2754265236Sken
2755265236Sken	switch (le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) {
2756265236Sken	case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
2757265236Sken		csio->resid = cm->cm_length - le32toh(rep->TransferCount);
2758265236Sken		/* FALLTHROUGH */
2759265236Sken	case MPI2_IOCSTATUS_SUCCESS:
2760265236Sken	case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
2761265236Sken		if ((le16toh(rep->IOCStatus) & MPI2_IOCSTATUS_MASK) ==
2762265236Sken		    MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR)
2763265236Sken			mprsas_log_command(cm, MPR_XINFO, "recovered error\n");
2764265236Sken
2765265236Sken		/* Completion failed at the transport level. */
2766265236Sken		if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS |
2767265236Sken		    MPI2_SCSI_STATE_TERMINATED)) {
2768283990Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
2769265236Sken			break;
2770265236Sken		}
2771265236Sken
2772265236Sken		/* In a modern packetized environment, an autosense failure
2773265236Sken		 * implies that there's not much else that can be done to
2774265236Sken		 * recover the command.
2775265236Sken		 */
2776265236Sken		if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) {
2777283990Sslm			mprsas_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL);
2778265236Sken			break;
2779265236Sken		}
2780265236Sken
2781265236Sken		/*
2782265236Sken		 * CAM doesn't care about SAS Response Info data, but if this is
2783265236Sken		 * the state check if TLR should be done.  If not, clear the
2784265236Sken		 * TLR_bits for the target.
2785265236Sken		 */
2786265236Sken		if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) &&
2787265236Sken		    ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE)
2788265236Sken		    == MPR_SCSI_RI_INVALID_FRAME)) {
2789283990Sslm			sc->mapping_table[target_id].TLR_bits =
2790265236Sken			    (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
2791265236Sken		}
2792265236Sken
2793265236Sken		/*
2794265236Sken		 * Intentionally override the normal SCSI status reporting
2795265236Sken		 * for these two cases.  These are likely to happen in a
2796265236Sken		 * multi-initiator environment, and we want to make sure that
2797265236Sken		 * CAM retries these commands rather than fail them.
2798265236Sken		 */
2799265236Sken		if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) ||
2800265236Sken		    (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) {
2801283990Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED);
2802265236Sken			break;
2803265236Sken		}
2804265236Sken
2805265236Sken		/* Handle normal status and sense */
2806265236Sken		csio->scsi_status = rep->SCSIStatus;
2807265236Sken		if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD)
2808283990Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
2809265236Sken		else
2810283990Sslm			mprsas_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR);
2811265236Sken
2812265236Sken		if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
2813265236Sken			int sense_len, returned_sense_len;
2814265236Sken
2815265236Sken			returned_sense_len = min(le32toh(rep->SenseCount),
2816265236Sken			    sizeof(struct scsi_sense_data));
2817265236Sken			if (returned_sense_len < csio->sense_len)
2818265236Sken				csio->sense_resid = csio->sense_len -
2819265236Sken				    returned_sense_len;
2820265236Sken			else
2821265236Sken				csio->sense_resid = 0;
2822265236Sken
2823265236Sken			sense_len = min(returned_sense_len,
2824265236Sken			    csio->sense_len - csio->sense_resid);
2825265236Sken			bzero(&csio->sense_data, sizeof(csio->sense_data));
2826265236Sken			bcopy(cm->cm_sense, &csio->sense_data, sense_len);
2827265236Sken			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
2828265236Sken		}
2829265236Sken
2830265236Sken		/*
2831265236Sken		 * Check if this is an INQUIRY command.  If it's a VPD inquiry,
2832265236Sken		 * and it's page code 0 (Supported Page List), and there is
2833265236Sken		 * inquiry data, and this is for a sequential access device, and
2834265236Sken		 * the device is an SSP target, and TLR is supported by the
2835265236Sken		 * controller, turn the TLR_bits value ON if page 0x90 is
2836265236Sken		 * supported.
2837265236Sken		 */
2838319436Sslm		if ((scsi_cdb[0] == INQUIRY) &&
2839319436Sslm		    (scsi_cdb[1] & SI_EVPD) &&
2840319436Sslm		    (scsi_cdb[2] == SVPD_SUPPORTED_PAGE_LIST) &&
2841265236Sken		    ((csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) &&
2842266548Sken		    (csio->data_ptr != NULL) &&
2843266548Sken		    ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) &&
2844266548Sken		    (sc->control_TLR) &&
2845283990Sslm		    (sc->mapping_table[target_id].device_info &
2846265236Sken		    MPI2_SAS_DEVICE_INFO_SSP_TARGET)) {
2847265236Sken			vpd_list = (struct scsi_vpd_supported_page_list *)
2848265236Sken			    csio->data_ptr;
2849283990Sslm			TLR_bits = &sc->mapping_table[target_id].TLR_bits;
2850265236Sken			*TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
2851265236Sken			TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON;
2852319436Sslm			alloc_len = ((u16)scsi_cdb[3] << 8) + scsi_cdb[4];
2853266548Sken			alloc_len -= csio->resid;
2854265236Sken			for (i = 0; i < MIN(vpd_list->length, alloc_len); i++) {
2855265236Sken				if (vpd_list->list[i] == 0x90) {
2856265236Sken					*TLR_bits = TLR_on;
2857265236Sken					break;
2858265236Sken				}
2859265236Sken			}
2860265236Sken		}
2861283990Sslm
2862283990Sslm		/*
2863283990Sslm		 * If this is a SATA direct-access end device, mark it so that
2864283990Sslm		 * a SCSI StartStopUnit command will be sent to it when the
2865283990Sslm		 * driver is being shutdown.
2866283990Sslm		 */
2867319436Sslm		if ((scsi_cdb[0] == INQUIRY) &&
2868313103Sasomers		    (csio->data_ptr != NULL) &&
2869283990Sslm		    ((csio->data_ptr[0] & 0x1f) == T_DIRECT) &&
2870283990Sslm		    (sc->mapping_table[target_id].device_info &
2871283990Sslm		    MPI2_SAS_DEVICE_INFO_SATA_DEVICE) &&
2872283990Sslm		    ((sc->mapping_table[target_id].device_info &
2873283990Sslm		    MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
2874283990Sslm		    MPI2_SAS_DEVICE_INFO_END_DEVICE)) {
2875283990Sslm			target = &sassc->targets[target_id];
2876283990Sslm			target->supports_SSU = TRUE;
2877283990Sslm			mpr_dprint(sc, MPR_XINFO, "Target %d supports SSU\n",
2878283990Sslm			    target_id);
2879283990Sslm		}
2880265236Sken		break;
2881265236Sken	case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
2882265236Sken	case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
2883265236Sken		/*
2884265236Sken		 * If devinfo is 0 this will be a volume.  In that case don't
2885265236Sken		 * tell CAM that the volume is not there.  We want volumes to
2886265236Sken		 * be enumerated until they are deleted/removed, not just
2887265236Sken		 * failed.
2888265236Sken		 */
2889265236Sken		if (cm->cm_targ->devinfo == 0)
2890283990Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
2891265236Sken		else
2892283990Sslm			mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
2893265236Sken		break;
2894265236Sken	case MPI2_IOCSTATUS_INVALID_SGL:
2895265236Sken		mpr_print_scsiio_cmd(sc, cm);
2896283990Sslm		mprsas_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR);
2897265236Sken		break;
2898265236Sken	case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
2899265236Sken		/*
2900265236Sken		 * This is one of the responses that comes back when an I/O
2901265236Sken		 * has been aborted.  If it is because of a timeout that we
2902265236Sken		 * initiated, just set the status to CAM_CMD_TIMEOUT.
2903265236Sken		 * Otherwise set it to CAM_REQ_ABORTED.  The effect on the
2904265236Sken		 * command is the same (it gets retried, subject to the
2905265236Sken		 * retry counter), the only difference is what gets printed
2906265236Sken		 * on the console.
2907265236Sken		 */
2908265236Sken		if (cm->cm_state == MPR_CM_STATE_TIMEDOUT)
2909283990Sslm			mprsas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT);
2910265236Sken		else
2911283990Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED);
2912265236Sken		break;
2913265236Sken	case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
2914265236Sken		/* resid is ignored for this condition */
2915265236Sken		csio->resid = 0;
2916283990Sslm		mprsas_set_ccbstatus(ccb, CAM_DATA_RUN_ERR);
2917265236Sken		break;
2918265236Sken	case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
2919265236Sken	case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
2920265236Sken		/*
2921301211Sasomers		 * These can sometimes be transient transport-related
2922301211Sasomers		 * errors, and sometimes persistent drive-related errors.
2923301211Sasomers		 * We used to retry these without decrementing the retry
2924301211Sasomers		 * count by returning CAM_REQUEUE_REQ.  Unfortunately, if
2925301211Sasomers		 * we hit a persistent drive problem that returns one of
2926301211Sasomers		 * these error codes, we would retry indefinitely.  So,
2927301211Sasomers		 * return CAM_REQ_CMP_ERROR so that we decrement the retry
2928301211Sasomers		 * count and avoid infinite retries.  We're taking the
2929301211Sasomers		 * potential risk of flagging false failures in the event
2930301211Sasomers		 * of a topology-related error (e.g. a SAS expander problem
2931301211Sasomers		 * causes a command addressed to a drive to fail), but
2932301211Sasomers		 * avoiding getting into an infinite retry loop.
2933265236Sken		 */
2934301211Sasomers		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
2935265236Sken		mprsas_log_command(cm, MPR_INFO,
2936319436Sslm		    "terminated ioc %x loginfo %x scsi %x state %x xfer %u\n",
2937319436Sslm		    le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo),
2938319436Sslm		    rep->SCSIStatus, rep->SCSIState,
2939265236Sken		    le32toh(rep->TransferCount));
2940265236Sken		break;
2941265236Sken	case MPI2_IOCSTATUS_INVALID_FUNCTION:
2942265236Sken	case MPI2_IOCSTATUS_INTERNAL_ERROR:
2943265236Sken	case MPI2_IOCSTATUS_INVALID_VPID:
2944265236Sken	case MPI2_IOCSTATUS_INVALID_FIELD:
2945265236Sken	case MPI2_IOCSTATUS_INVALID_STATE:
2946265236Sken	case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
2947265236Sken	case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
2948265236Sken	case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
2949265236Sken	case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
2950265236Sken	case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
2951265236Sken	default:
2952265236Sken		mprsas_log_command(cm, MPR_XINFO,
2953319436Sslm		    "completed ioc %x loginfo %x scsi %x state %x xfer %u\n",
2954319436Sslm		    le16toh(rep->IOCStatus), le32toh(rep->IOCLogInfo),
2955319436Sslm		    rep->SCSIStatus, rep->SCSIState,
2956265236Sken		    le32toh(rep->TransferCount));
2957265236Sken		csio->resid = cm->cm_length;
2958319436Sslm
2959319436Sslm		if (scsi_cdb[0] == UNMAP &&
2960319436Sslm		    target->is_nvme &&
2961319436Sslm		    (csio->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR)
2962319436Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
2963319436Sslm		else
2964319436Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
2965319436Sslm
2966265236Sken		break;
2967265236Sken	}
2968265236Sken
2969265236Sken	mpr_sc_failed_io_info(sc, csio, rep, cm->cm_targ);
2970265236Sken
2971265236Sken	if (sassc->flags & MPRSAS_QUEUE_FROZEN) {
2972265236Sken		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
2973265236Sken		sassc->flags &= ~MPRSAS_QUEUE_FROZEN;
2974265236Sken		mpr_dprint(sc, MPR_XINFO, "Command completed, unfreezing SIM "
2975265236Sken		    "queue\n");
2976265236Sken	}
2977265236Sken
2978283990Sslm	if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) {
2979265236Sken		ccb->ccb_h.status |= CAM_DEV_QFRZN;
2980265236Sken		xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1);
2981265236Sken	}
2982265236Sken
2983265236Sken	mpr_free_command(sc, cm);
2984265236Sken	xpt_done(ccb);
2985265236Sken}
2986265236Sken
2987265236Sken#if __FreeBSD_version >= 900026
2988265236Skenstatic void
2989265236Skenmprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm)
2990265236Sken{
2991265236Sken	MPI2_SMP_PASSTHROUGH_REPLY *rpl;
2992265236Sken	MPI2_SMP_PASSTHROUGH_REQUEST *req;
2993265236Sken	uint64_t sasaddr;
2994265236Sken	union ccb *ccb;
2995265236Sken
2996265236Sken	ccb = cm->cm_complete_data;
2997265236Sken
2998265236Sken	/*
2999265236Sken	 * Currently there should be no way we can hit this case.  It only
3000265236Sken	 * happens when we have a failure to allocate chain frames, and SMP
3001265236Sken	 * commands require two S/G elements only.  That should be handled
3002265236Sken	 * in the standard request size.
3003265236Sken	 */
3004265236Sken	if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
3005283990Sslm		mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x on SMP "
3006283990Sslm		    "request!\n", __func__, cm->cm_flags);
3007283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
3008265236Sken		goto bailout;
3009265236Sken        }
3010265236Sken
3011265236Sken	rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply;
3012265236Sken	if (rpl == NULL) {
3013265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: NULL cm_reply!\n", __func__);
3014283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
3015265236Sken		goto bailout;
3016265236Sken	}
3017265236Sken
3018265236Sken	req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req;
3019265236Sken	sasaddr = le32toh(req->SASAddress.Low);
3020265236Sken	sasaddr |= ((uint64_t)(le32toh(req->SASAddress.High))) << 32;
3021265236Sken
3022265236Sken	if ((le16toh(rpl->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
3023265236Sken	    MPI2_IOCSTATUS_SUCCESS ||
3024265236Sken	    rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) {
3025265236Sken		mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus %04x SASStatus %02x\n",
3026265236Sken		    __func__, le16toh(rpl->IOCStatus), rpl->SASStatus);
3027283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
3028265236Sken		goto bailout;
3029265236Sken	}
3030265236Sken
3031283990Sslm	mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address %#jx "
3032283990Sslm	    "completed successfully\n", __func__, (uintmax_t)sasaddr);
3033265236Sken
3034265236Sken	if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED)
3035283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
3036265236Sken	else
3037283990Sslm		mprsas_set_ccbstatus(ccb, CAM_SMP_STATUS_ERROR);
3038265236Sken
3039265236Skenbailout:
3040265236Sken	/*
3041265236Sken	 * We sync in both directions because we had DMAs in the S/G list
3042265236Sken	 * in both directions.
3043265236Sken	 */
3044265236Sken	bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap,
3045265236Sken			BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
3046265236Sken	bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
3047265236Sken	mpr_free_command(sc, cm);
3048265236Sken	xpt_done(ccb);
3049265236Sken}
3050265236Sken
3051265236Skenstatic void
3052299962Sslmmprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, uint64_t sasaddr)
3053265236Sken{
3054265236Sken	struct mpr_command *cm;
3055265236Sken	uint8_t *request, *response;
3056265236Sken	MPI2_SMP_PASSTHROUGH_REQUEST *req;
3057265236Sken	struct mpr_softc *sc;
3058265236Sken	struct sglist *sg;
3059265236Sken	int error;
3060265236Sken
3061265236Sken	sc = sassc->sc;
3062265236Sken	sg = NULL;
3063265236Sken	error = 0;
3064265236Sken
3065265730Sken#if (__FreeBSD_version >= 1000028) || \
3066265730Sken    ((__FreeBSD_version >= 902001) && (__FreeBSD_version < 1000000))
3067265236Sken	switch (ccb->ccb_h.flags & CAM_DATA_MASK) {
3068265236Sken	case CAM_DATA_PADDR:
3069265236Sken	case CAM_DATA_SG_PADDR:
3070265236Sken		/*
3071265236Sken		 * XXX We don't yet support physical addresses here.
3072265236Sken		 */
3073265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not "
3074265236Sken		    "supported\n", __func__);
3075283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID);
3076265236Sken		xpt_done(ccb);
3077265236Sken		return;
3078265236Sken	case CAM_DATA_SG:
3079265236Sken		/*
3080265236Sken		 * The chip does not support more than one buffer for the
3081265236Sken		 * request or response.
3082265236Sken		 */
3083265236Sken		if ((ccb->smpio.smp_request_sglist_cnt > 1)
3084265236Sken		    || (ccb->smpio.smp_response_sglist_cnt > 1)) {
3085299962Sslm			mpr_dprint(sc, MPR_ERROR, "%s: multiple request or "
3086299962Sslm			    "response buffer segments not supported for SMP\n",
3087299962Sslm			    __func__);
3088283990Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID);
3089265236Sken			xpt_done(ccb);
3090265236Sken			return;
3091265236Sken		}
3092265236Sken
3093265236Sken		/*
3094265236Sken		 * The CAM_SCATTER_VALID flag was originally implemented
3095265236Sken		 * for the XPT_SCSI_IO CCB, which only has one data pointer.
3096265236Sken		 * We have two.  So, just take that flag to mean that we
3097265236Sken		 * might have S/G lists, and look at the S/G segment count
3098265236Sken		 * to figure out whether that is the case for each individual
3099265236Sken		 * buffer.
3100265236Sken		 */
3101265236Sken		if (ccb->smpio.smp_request_sglist_cnt != 0) {
3102265236Sken			bus_dma_segment_t *req_sg;
3103265236Sken
3104265236Sken			req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request;
3105265236Sken			request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr;
3106265236Sken		} else
3107265236Sken			request = ccb->smpio.smp_request;
3108265236Sken
3109265236Sken		if (ccb->smpio.smp_response_sglist_cnt != 0) {
3110265236Sken			bus_dma_segment_t *rsp_sg;
3111265236Sken
3112265236Sken			rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response;
3113265236Sken			response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr;
3114265236Sken		} else
3115265236Sken			response = ccb->smpio.smp_response;
3116265236Sken		break;
3117265236Sken	case CAM_DATA_VADDR:
3118265236Sken		request = ccb->smpio.smp_request;
3119265236Sken		response = ccb->smpio.smp_response;
3120265236Sken		break;
3121265236Sken	default:
3122283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID);
3123265236Sken		xpt_done(ccb);
3124265236Sken		return;
3125265236Sken	}
3126265730Sken#else /* __FreeBSD_version < 1000028 */
3127265236Sken	/*
3128265236Sken	 * XXX We don't yet support physical addresses here.
3129265236Sken	 */
3130265236Sken	if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) {
3131283990Sslm		mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not "
3132283990Sslm		    "supported\n", __func__);
3133283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID);
3134265236Sken		xpt_done(ccb);
3135265236Sken		return;
3136265236Sken	}
3137265236Sken
3138265236Sken	/*
3139265236Sken	 * If the user wants to send an S/G list, check to make sure they
3140265236Sken	 * have single buffers.
3141265236Sken	 */
3142265236Sken	if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
3143265236Sken		/*
3144265236Sken		 * The chip does not support more than one buffer for the
3145265236Sken		 * request or response.
3146265236Sken		 */
3147265236Sken	 	if ((ccb->smpio.smp_request_sglist_cnt > 1)
3148265236Sken		  || (ccb->smpio.smp_response_sglist_cnt > 1)) {
3149265236Sken			mpr_dprint(sc, MPR_ERROR, "%s: multiple request or "
3150265236Sken			    "response buffer segments not supported for SMP\n",
3151265236Sken			    __func__);
3152283990Sslm			mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID);
3153265236Sken			xpt_done(ccb);
3154265236Sken			return;
3155265236Sken		}
3156265236Sken
3157265236Sken		/*
3158265236Sken		 * The CAM_SCATTER_VALID flag was originally implemented
3159265236Sken		 * for the XPT_SCSI_IO CCB, which only has one data pointer.
3160265236Sken		 * We have two.  So, just take that flag to mean that we
3161265236Sken		 * might have S/G lists, and look at the S/G segment count
3162265236Sken		 * to figure out whether that is the case for each individual
3163265236Sken		 * buffer.
3164265236Sken		 */
3165265236Sken		if (ccb->smpio.smp_request_sglist_cnt != 0) {
3166265236Sken			bus_dma_segment_t *req_sg;
3167265236Sken
3168265236Sken			req_sg = (bus_dma_segment_t *)ccb->smpio.smp_request;
3169265730Sken			request = (uint8_t *)(uintptr_t)req_sg[0].ds_addr;
3170265236Sken		} else
3171265236Sken			request = ccb->smpio.smp_request;
3172265236Sken
3173265236Sken		if (ccb->smpio.smp_response_sglist_cnt != 0) {
3174265236Sken			bus_dma_segment_t *rsp_sg;
3175265236Sken
3176265236Sken			rsp_sg = (bus_dma_segment_t *)ccb->smpio.smp_response;
3177265730Sken			response = (uint8_t *)(uintptr_t)rsp_sg[0].ds_addr;
3178265236Sken		} else
3179265236Sken			response = ccb->smpio.smp_response;
3180265236Sken	} else {
3181265236Sken		request = ccb->smpio.smp_request;
3182265236Sken		response = ccb->smpio.smp_response;
3183265236Sken	}
3184265730Sken#endif /* __FreeBSD_version < 1000028 */
3185265236Sken
3186265236Sken	cm = mpr_alloc_command(sc);
3187265236Sken	if (cm == NULL) {
3188299962Sslm		mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n",
3189299962Sslm		    __func__);
3190283990Sslm		mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL);
3191265236Sken		xpt_done(ccb);
3192265236Sken		return;
3193265236Sken	}
3194265236Sken
3195265236Sken	req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req;
3196265236Sken	bzero(req, sizeof(*req));
3197265236Sken	req->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
3198265236Sken
3199265236Sken	/* Allow the chip to use any route to this SAS address. */
3200265236Sken	req->PhysicalPort = 0xff;
3201265236Sken
3202265236Sken	req->RequestDataLength = htole16(ccb->smpio.smp_request_len);
3203265236Sken	req->SGLFlags =
3204265236Sken	    MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE | MPI2_SGLFLAGS_SGL_TYPE_MPI;
3205265236Sken
3206265236Sken	mpr_dprint(sc, MPR_XINFO, "%s: sending SMP request to SAS address "
3207265236Sken	    "%#jx\n", __func__, (uintmax_t)sasaddr);
3208265236Sken
3209265236Sken	mpr_init_sge(cm, req, &req->SGL);
3210265236Sken
3211265236Sken	/*
3212265236Sken	 * Set up a uio to pass into mpr_map_command().  This allows us to
3213265236Sken	 * do one map command, and one busdma call in there.
3214265236Sken	 */
3215265236Sken	cm->cm_uio.uio_iov = cm->cm_iovec;
3216265236Sken	cm->cm_uio.uio_iovcnt = 2;
3217265236Sken	cm->cm_uio.uio_segflg = UIO_SYSSPACE;
3218265236Sken
3219265236Sken	/*
3220265236Sken	 * The read/write flag isn't used by busdma, but set it just in
3221265236Sken	 * case.  This isn't exactly accurate, either, since we're going in
3222265236Sken	 * both directions.
3223265236Sken	 */
3224265236Sken	cm->cm_uio.uio_rw = UIO_WRITE;
3225265236Sken
3226265236Sken	cm->cm_iovec[0].iov_base = request;
3227265236Sken	cm->cm_iovec[0].iov_len = le16toh(req->RequestDataLength);
3228265236Sken	cm->cm_iovec[1].iov_base = response;
3229265236Sken	cm->cm_iovec[1].iov_len = ccb->smpio.smp_response_len;
3230265236Sken
3231265236Sken	cm->cm_uio.uio_resid = cm->cm_iovec[0].iov_len +
3232265236Sken			       cm->cm_iovec[1].iov_len;
3233265236Sken
3234265236Sken	/*
3235265236Sken	 * Trigger a warning message in mpr_data_cb() for the user if we
3236265236Sken	 * wind up exceeding two S/G segments.  The chip expects one
3237265236Sken	 * segment for the request and another for the response.
3238265236Sken	 */
3239265236Sken	cm->cm_max_segs = 2;
3240265236Sken
3241265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
3242265236Sken	cm->cm_complete = mprsas_smpio_complete;
3243265236Sken	cm->cm_complete_data = ccb;
3244265236Sken
3245265236Sken	/*
3246265236Sken	 * Tell the mapping code that we're using a uio, and that this is
3247265236Sken	 * an SMP passthrough request.  There is a little special-case
3248265236Sken	 * logic there (in mpr_data_cb()) to handle the bidirectional
3249265236Sken	 * transfer.
3250265236Sken	 */
3251265236Sken	cm->cm_flags |= MPR_CM_FLAGS_USE_UIO | MPR_CM_FLAGS_SMP_PASS |
3252265236Sken			MPR_CM_FLAGS_DATAIN | MPR_CM_FLAGS_DATAOUT;
3253265236Sken
3254265236Sken	/* The chip data format is little endian. */
3255265236Sken	req->SASAddress.High = htole32(sasaddr >> 32);
3256265236Sken	req->SASAddress.Low = htole32(sasaddr);
3257265236Sken
3258265236Sken	/*
3259265236Sken	 * XXX Note that we don't have a timeout/abort mechanism here.
3260265236Sken	 * From the manual, it looks like task management requests only
3261265236Sken	 * work for SCSI IO and SATA passthrough requests.  We may need to
3262265236Sken	 * have a mechanism to retry requests in the event of a chip reset
3263265236Sken	 * at least.  Hopefully the chip will insure that any errors short
3264265236Sken	 * of that are relayed back to the driver.
3265265236Sken	 */
3266265236Sken	error = mpr_map_command(sc, cm);
3267265236Sken	if ((error != 0) && (error != EINPROGRESS)) {
3268265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: error %d returned from "
3269265236Sken		    "mpr_map_command()\n", __func__, error);
3270265236Sken		goto bailout_error;
3271265236Sken	}
3272265236Sken
3273265236Sken	return;
3274265236Sken
3275265236Skenbailout_error:
3276265236Sken	mpr_free_command(sc, cm);
3277283990Sslm	mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL);
3278265236Sken	xpt_done(ccb);
3279265236Sken	return;
3280265236Sken}
3281265236Sken
3282265236Skenstatic void
3283265236Skenmprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb)
3284265236Sken{
3285265236Sken	struct mpr_softc *sc;
3286265236Sken	struct mprsas_target *targ;
3287265236Sken	uint64_t sasaddr = 0;
3288265236Sken
3289265236Sken	sc = sassc->sc;
3290265236Sken
3291265236Sken	/*
3292265236Sken	 * Make sure the target exists.
3293265236Sken	 */
3294265236Sken	KASSERT(ccb->ccb_h.target_id < sassc->maxtargets,
3295265236Sken	    ("Target %d out of bounds in XPT_SMP_IO\n", ccb->ccb_h.target_id));
3296265236Sken	targ = &sassc->targets[ccb->ccb_h.target_id];
3297265236Sken	if (targ->handle == 0x0) {
3298265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: target %d does not exist!\n",
3299265236Sken		    __func__, ccb->ccb_h.target_id);
3300283990Sslm		mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT);
3301265236Sken		xpt_done(ccb);
3302265236Sken		return;
3303265236Sken	}
3304265236Sken
3305265236Sken	/*
3306265236Sken	 * If this device has an embedded SMP target, we'll talk to it
3307265236Sken	 * directly.
3308265236Sken	 * figure out what the expander's address is.
3309265236Sken	 */
3310265236Sken	if ((targ->devinfo & MPI2_SAS_DEVICE_INFO_SMP_TARGET) != 0)
3311265236Sken		sasaddr = targ->sasaddr;
3312265236Sken
3313265236Sken	/*
3314265236Sken	 * If we don't have a SAS address for the expander yet, try
3315265236Sken	 * grabbing it from the page 0x83 information cached in the
3316265236Sken	 * transport layer for this target.  LSI expanders report the
3317265236Sken	 * expander SAS address as the port-associated SAS address in
3318265236Sken	 * Inquiry VPD page 0x83.  Maxim expanders don't report it in page
3319265236Sken	 * 0x83.
3320265236Sken	 *
3321265236Sken	 * XXX KDM disable this for now, but leave it commented out so that
3322265236Sken	 * it is obvious that this is another possible way to get the SAS
3323265236Sken	 * address.
3324265236Sken	 *
3325265236Sken	 * The parent handle method below is a little more reliable, and
3326265236Sken	 * the other benefit is that it works for devices other than SES
3327265236Sken	 * devices.  So you can send a SMP request to a da(4) device and it
3328265236Sken	 * will get routed to the expander that device is attached to.
3329265236Sken	 * (Assuming the da(4) device doesn't contain an SMP target...)
3330265236Sken	 */
3331265236Sken#if 0
3332265236Sken	if (sasaddr == 0)
3333265236Sken		sasaddr = xpt_path_sas_addr(ccb->ccb_h.path);
3334265236Sken#endif
3335265236Sken
3336265236Sken	/*
3337265236Sken	 * If we still don't have a SAS address for the expander, look for
3338265236Sken	 * the parent device of this device, which is probably the expander.
3339265236Sken	 */
3340265236Sken	if (sasaddr == 0) {
3341265236Sken#ifdef OLD_MPR_PROBE
3342265236Sken		struct mprsas_target *parent_target;
3343265236Sken#endif
3344265236Sken
3345265236Sken		if (targ->parent_handle == 0x0) {
3346265236Sken			mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have "
3347265236Sken			    "a valid parent handle!\n", __func__, targ->handle);
3348283990Sslm			mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
3349265236Sken			goto bailout;
3350265236Sken		}
3351265236Sken#ifdef OLD_MPR_PROBE
3352265236Sken		parent_target = mprsas_find_target_by_handle(sassc, 0,
3353265236Sken		    targ->parent_handle);
3354265236Sken
3355265236Sken		if (parent_target == NULL) {
3356265236Sken			mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have "
3357265236Sken			    "a valid parent target!\n", __func__, targ->handle);
3358283990Sslm			mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
3359265236Sken			goto bailout;
3360265236Sken		}
3361265236Sken
3362265236Sken		if ((parent_target->devinfo &
3363265236Sken		     MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) {
3364265236Sken			mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d "
3365265236Sken			    "does not have an SMP target!\n", __func__,
3366265236Sken			    targ->handle, parent_target->handle);
3367283990Sslm			mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
3368265236Sken			goto bailout;
3369265236Sken		}
3370265236Sken
3371265236Sken		sasaddr = parent_target->sasaddr;
3372265236Sken#else /* OLD_MPR_PROBE */
3373265236Sken		if ((targ->parent_devinfo &
3374265236Sken		     MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) {
3375265236Sken			mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d "
3376265236Sken			    "does not have an SMP target!\n", __func__,
3377265236Sken			    targ->handle, targ->parent_handle);
3378283990Sslm			mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
3379265236Sken			goto bailout;
3380265236Sken
3381265236Sken		}
3382265236Sken		if (targ->parent_sasaddr == 0x0) {
3383265236Sken			mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent handle "
3384265236Sken			    "%d does not have a valid SAS address!\n", __func__,
3385265236Sken			    targ->handle, targ->parent_handle);
3386283990Sslm			mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
3387265236Sken			goto bailout;
3388265236Sken		}
3389265236Sken
3390265236Sken		sasaddr = targ->parent_sasaddr;
3391265236Sken#endif /* OLD_MPR_PROBE */
3392265236Sken
3393265236Sken	}
3394265236Sken
3395265236Sken	if (sasaddr == 0) {
3396265236Sken		mpr_dprint(sc, MPR_INFO, "%s: unable to find SAS address for "
3397265236Sken		    "handle %d\n", __func__, targ->handle);
3398283990Sslm		mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
3399265236Sken		goto bailout;
3400265236Sken	}
3401265236Sken	mprsas_send_smpcmd(sassc, ccb, sasaddr);
3402265236Sken
3403265236Sken	return;
3404265236Sken
3405265236Skenbailout:
3406265236Sken	xpt_done(ccb);
3407265236Sken
3408265236Sken}
3409265236Sken#endif //__FreeBSD_version >= 900026
3410265236Sken
3411265236Skenstatic void
3412265236Skenmprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb)
3413265236Sken{
3414265236Sken	MPI2_SCSI_TASK_MANAGE_REQUEST *req;
3415265236Sken	struct mpr_softc *sc;
3416265236Sken	struct mpr_command *tm;
3417265236Sken	struct mprsas_target *targ;
3418265236Sken
3419265236Sken	MPR_FUNCTRACE(sassc->sc);
3420265236Sken	mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED);
3421265236Sken
3422299962Sslm	KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, ("Target %d out of "
3423299962Sslm	    "bounds in XPT_RESET_DEV\n", ccb->ccb_h.target_id));
3424265236Sken	sc = sassc->sc;
3425265236Sken	tm = mpr_alloc_command(sc);
3426265236Sken	if (tm == NULL) {
3427299962Sslm		mpr_dprint(sc, MPR_ERROR, "command alloc failure in "
3428299962Sslm		    "mprsas_action_resetdev\n");
3429283990Sslm		mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL);
3430265236Sken		xpt_done(ccb);
3431265236Sken		return;
3432265236Sken	}
3433265236Sken
3434265236Sken	targ = &sassc->targets[ccb->ccb_h.target_id];
3435265236Sken	req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
3436265236Sken	req->DevHandle = htole16(targ->handle);
3437265236Sken	req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3438265236Sken	req->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3439265236Sken
3440265236Sken	/* SAS Hard Link Reset / SATA Link Reset */
3441265236Sken	req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
3442265236Sken
3443265236Sken	tm->cm_data = NULL;
3444265236Sken	tm->cm_desc.HighPriority.RequestFlags =
3445265236Sken	    MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
3446265236Sken	tm->cm_complete = mprsas_resetdev_complete;
3447265236Sken	tm->cm_complete_data = ccb;
3448283990Sslm
3449283990Sslm	mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n",
3450283990Sslm	    __func__, targ->tid);
3451265236Sken	tm->cm_targ = targ;
3452283990Sslm	targ->flags |= MPRSAS_TARGET_INRESET;
3453283990Sslm
3454265236Sken	mpr_map_command(sc, tm);
3455265236Sken}
3456265236Sken
3457265236Skenstatic void
3458265236Skenmprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm)
3459265236Sken{
3460265236Sken	MPI2_SCSI_TASK_MANAGE_REPLY *resp;
3461265236Sken	union ccb *ccb;
3462265236Sken
3463265236Sken	MPR_FUNCTRACE(sc);
3464265236Sken	mtx_assert(&sc->mpr_mtx, MA_OWNED);
3465265236Sken
3466265236Sken	resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply;
3467265236Sken	ccb = tm->cm_complete_data;
3468265236Sken
3469265236Sken	/*
3470265236Sken	 * Currently there should be no way we can hit this case.  It only
3471265236Sken	 * happens when we have a failure to allocate chain frames, and
3472265236Sken	 * task management commands don't have S/G lists.
3473265236Sken	 */
3474265236Sken	if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
3475265236Sken		MPI2_SCSI_TASK_MANAGE_REQUEST *req;
3476265236Sken
3477265236Sken		req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req;
3478265236Sken
3479265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of "
3480265236Sken		    "handle %#04x! This should not happen!\n", __func__,
3481265236Sken		    tm->cm_flags, req->DevHandle);
3482283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
3483265236Sken		goto bailout;
3484265236Sken	}
3485265236Sken
3486299962Sslm	mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n",
3487299962Sslm	    __func__, le16toh(resp->IOCStatus), le32toh(resp->ResponseCode));
3488265236Sken
3489265236Sken	if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) {
3490283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP);
3491265236Sken		mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid,
3492265236Sken		    CAM_LUN_WILDCARD);
3493265236Sken	}
3494265236Sken	else
3495283990Sslm		mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
3496265236Sken
3497265236Skenbailout:
3498265236Sken
3499265236Sken	mprsas_free_tm(sc, tm);
3500265236Sken	xpt_done(ccb);
3501265236Sken}
3502265236Sken
3503265236Skenstatic void
3504265236Skenmprsas_poll(struct cam_sim *sim)
3505265236Sken{
3506265236Sken	struct mprsas_softc *sassc;
3507265236Sken
3508265236Sken	sassc = cam_sim_softc(sim);
3509265236Sken
3510265236Sken	if (sassc->sc->mpr_debug & MPR_TRACE) {
3511265236Sken		/* frequent debug messages during a panic just slow
3512265236Sken		 * everything down too much.
3513265236Sken		 */
3514283990Sslm		mpr_dprint(sassc->sc, MPR_XINFO, "%s clearing MPR_TRACE\n",
3515283990Sslm		    __func__);
3516265236Sken		sassc->sc->mpr_debug &= ~MPR_TRACE;
3517265236Sken	}
3518265236Sken
3519265236Sken	mpr_intr_locked(sassc->sc);
3520265236Sken}
3521265236Sken
3522265236Skenstatic void
3523265236Skenmprsas_async(void *callback_arg, uint32_t code, struct cam_path *path,
3524265236Sken    void *arg)
3525265236Sken{
3526265236Sken	struct mpr_softc *sc;
3527265236Sken
3528265236Sken	sc = (struct mpr_softc *)callback_arg;
3529265236Sken
3530265236Sken	switch (code) {
3531265236Sken#if (__FreeBSD_version >= 1000006) || \
3532265236Sken    ((__FreeBSD_version >= 901503) && (__FreeBSD_version < 1000000))
3533265236Sken	case AC_ADVINFO_CHANGED: {
3534265236Sken		struct mprsas_target *target;
3535265236Sken		struct mprsas_softc *sassc;
3536265236Sken		struct scsi_read_capacity_data_long rcap_buf;
3537265236Sken		struct ccb_dev_advinfo cdai;
3538265236Sken		struct mprsas_lun *lun;
3539265236Sken		lun_id_t lunid;
3540265236Sken		int found_lun;
3541265236Sken		uintptr_t buftype;
3542265236Sken
3543265236Sken		buftype = (uintptr_t)arg;
3544265236Sken
3545265236Sken		found_lun = 0;
3546265236Sken		sassc = sc->sassc;
3547265236Sken
3548265236Sken		/*
3549265236Sken		 * We're only interested in read capacity data changes.
3550265236Sken		 */
3551265236Sken		if (buftype != CDAI_TYPE_RCAPLONG)
3552265236Sken			break;
3553265236Sken
3554265236Sken		/*
3555265730Sken		 * See the comment in mpr_attach_sas() for a detailed
3556265730Sken		 * explanation.  In these versions of FreeBSD we register
3557265730Sken		 * for all events and filter out the events that don't
3558265730Sken		 * apply to us.
3559265730Sken		 */
3560265730Sken#if (__FreeBSD_version < 1000703) || \
3561265730Sken    ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002))
3562265730Sken		if (xpt_path_path_id(path) != sassc->sim->path_id)
3563265730Sken			break;
3564265730Sken#endif
3565265730Sken
3566265730Sken		/*
3567265236Sken		 * We should have a handle for this, but check to make sure.
3568265236Sken		 */
3569265236Sken		KASSERT(xpt_path_target_id(path) < sassc->maxtargets,
3570265236Sken		    ("Target %d out of bounds in mprsas_async\n",
3571265236Sken		    xpt_path_target_id(path)));
3572265236Sken		target = &sassc->targets[xpt_path_target_id(path)];
3573265236Sken		if (target->handle == 0)
3574265236Sken			break;
3575265236Sken
3576265236Sken		lunid = xpt_path_lun_id(path);
3577265236Sken
3578265236Sken		SLIST_FOREACH(lun, &target->luns, lun_link) {
3579265236Sken			if (lun->lun_id == lunid) {
3580265236Sken				found_lun = 1;
3581265236Sken				break;
3582265236Sken			}
3583265236Sken		}
3584265236Sken
3585265236Sken		if (found_lun == 0) {
3586265236Sken			lun = malloc(sizeof(struct mprsas_lun), M_MPR,
3587265236Sken			    M_NOWAIT | M_ZERO);
3588265236Sken			if (lun == NULL) {
3589265236Sken				mpr_dprint(sc, MPR_ERROR, "Unable to alloc "
3590265236Sken				    "LUN for EEDP support.\n");
3591265236Sken				break;
3592265236Sken			}
3593265236Sken			lun->lun_id = lunid;
3594265236Sken			SLIST_INSERT_HEAD(&target->luns, lun, lun_link);
3595265236Sken		}
3596265236Sken
3597265236Sken		bzero(&rcap_buf, sizeof(rcap_buf));
3598265236Sken		xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL);
3599265236Sken		cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
3600265236Sken		cdai.ccb_h.flags = CAM_DIR_IN;
3601265236Sken		cdai.buftype = CDAI_TYPE_RCAPLONG;
3602280448Sken#if (__FreeBSD_version >= 1100061) || \
3603280448Sken    ((__FreeBSD_version >= 1001510) && (__FreeBSD_version < 1100000))
3604279329Sken		cdai.flags = CDAI_FLAG_NONE;
3605279329Sken#else
3606265236Sken		cdai.flags = 0;
3607279329Sken#endif
3608265236Sken		cdai.bufsiz = sizeof(rcap_buf);
3609265236Sken		cdai.buf = (uint8_t *)&rcap_buf;
3610265236Sken		xpt_action((union ccb *)&cdai);
3611265236Sken		if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
3612265236Sken			cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
3613265236Sken
3614283990Sslm		if ((mprsas_get_ccbstatus((union ccb *)&cdai) == CAM_REQ_CMP)
3615265236Sken		    && (rcap_buf.prot & SRC16_PROT_EN)) {
3616265236Sken			lun->eedp_formatted = TRUE;
3617265236Sken			lun->eedp_block_size = scsi_4btoul(rcap_buf.length);
3618265236Sken		} else {
3619265236Sken			lun->eedp_formatted = FALSE;
3620265236Sken			lun->eedp_block_size = 0;
3621265236Sken		}
3622265236Sken		break;
3623265236Sken	}
3624265236Sken#endif
3625265236Sken	case AC_FOUND_DEVICE: {
3626265236Sken		struct ccb_getdev *cgd;
3627265236Sken
3628265730Sken		/*
3629265730Sken		 * See the comment in mpr_attach_sas() for a detailed
3630265730Sken		 * explanation.  In these versions of FreeBSD we register
3631265730Sken		 * for all events and filter out the events that don't
3632265730Sken		 * apply to us.
3633265730Sken		 */
3634265730Sken#if (__FreeBSD_version < 1000703) || \
3635265730Sken    ((__FreeBSD_version >= 1100000) && (__FreeBSD_version < 1100002))
3636265730Sken		if (xpt_path_path_id(path) != sc->sassc->sim->path_id)
3637265730Sken			break;
3638265730Sken#endif
3639265730Sken
3640265236Sken		cgd = arg;
3641265236Sken#if (__FreeBSD_version < 901503) || \
3642265236Sken    ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006))
3643265236Sken		mprsas_check_eedp(sc, path, cgd);
3644265236Sken#endif
3645265236Sken		break;
3646265236Sken	}
3647265236Sken	default:
3648265236Sken		break;
3649265236Sken	}
3650265236Sken}
3651265236Sken
3652265236Sken#if (__FreeBSD_version < 901503) || \
3653265236Sken    ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006))
3654265236Skenstatic void
3655265236Skenmprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path,
3656265236Sken    struct ccb_getdev *cgd)
3657265236Sken{
3658265236Sken	struct mprsas_softc *sassc = sc->sassc;
3659265236Sken	struct ccb_scsiio *csio;
3660265236Sken	struct scsi_read_capacity_16 *scsi_cmd;
3661265236Sken	struct scsi_read_capacity_eedp *rcap_buf;
3662265236Sken	path_id_t pathid;
3663265236Sken	target_id_t targetid;
3664265236Sken	lun_id_t lunid;
3665265236Sken	union ccb *ccb;
3666265236Sken	struct cam_path *local_path;
3667265236Sken	struct mprsas_target *target;
3668265236Sken	struct mprsas_lun *lun;
3669265236Sken	uint8_t	found_lun;
3670265236Sken	char path_str[64];
3671265236Sken
3672265236Sken	pathid = cam_sim_path(sassc->sim);
3673265236Sken	targetid = xpt_path_target_id(path);
3674265236Sken	lunid = xpt_path_lun_id(path);
3675265236Sken
3676299962Sslm	KASSERT(targetid < sassc->maxtargets, ("Target %d out of bounds in "
3677299962Sslm	    "mprsas_check_eedp\n", targetid));
3678265236Sken	target = &sassc->targets[targetid];
3679265236Sken	if (target->handle == 0x0)
3680265236Sken		return;
3681265236Sken
3682265236Sken	/*
3683265236Sken	 * Determine if the device is EEDP capable.
3684265236Sken	 *
3685265236Sken	 * If this flag is set in the inquiry data, the device supports
3686265236Sken	 * protection information, and must support the 16 byte read capacity
3687299962Sslm	 * command, otherwise continue without sending read cap 16.
3688265236Sken	 */
3689265236Sken	if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0)
3690265236Sken		return;
3691265236Sken
3692265236Sken	/*
3693265236Sken	 * Issue a READ CAPACITY 16 command.  This info is used to determine if
3694265236Sken	 * the LUN is formatted for EEDP support.
3695265236Sken	 */
3696265236Sken	ccb = xpt_alloc_ccb_nowait();
3697265236Sken	if (ccb == NULL) {
3698265236Sken		mpr_dprint(sc, MPR_ERROR, "Unable to alloc CCB for EEDP "
3699265236Sken		    "support.\n");
3700265236Sken		return;
3701265236Sken	}
3702265236Sken
3703299962Sslm	if (xpt_create_path(&local_path, xpt_periph, pathid, targetid, lunid) !=
3704299962Sslm	    CAM_REQ_CMP) {
3705265236Sken		mpr_dprint(sc, MPR_ERROR, "Unable to create path for EEDP "
3706299962Sslm		    "support.\n");
3707265236Sken		xpt_free_ccb(ccb);
3708265236Sken		return;
3709265236Sken	}
3710265236Sken
3711265236Sken	/*
3712265236Sken	 * If LUN is already in list, don't create a new one.
3713265236Sken	 */
3714265236Sken	found_lun = FALSE;
3715265236Sken	SLIST_FOREACH(lun, &target->luns, lun_link) {
3716265236Sken		if (lun->lun_id == lunid) {
3717265236Sken			found_lun = TRUE;
3718265236Sken			break;
3719265236Sken		}
3720265236Sken	}
3721265236Sken	if (!found_lun) {
3722265236Sken		lun = malloc(sizeof(struct mprsas_lun), M_MPR,
3723265236Sken		    M_NOWAIT | M_ZERO);
3724265236Sken		if (lun == NULL) {
3725265236Sken			mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for "
3726265236Sken			    "EEDP support.\n");
3727265236Sken			xpt_free_path(local_path);
3728265236Sken			xpt_free_ccb(ccb);
3729265236Sken			return;
3730265236Sken		}
3731265236Sken		lun->lun_id = lunid;
3732265236Sken		SLIST_INSERT_HEAD(&target->luns, lun, lun_link);
3733265236Sken	}
3734265236Sken
3735265236Sken	xpt_path_string(local_path, path_str, sizeof(path_str));
3736265236Sken	mpr_dprint(sc, MPR_INFO, "Sending read cap: path %s handle %d\n",
3737265236Sken	    path_str, target->handle);
3738265236Sken
3739265236Sken	/*
3740265236Sken	 * Issue a READ CAPACITY 16 command for the LUN.  The
3741265236Sken	 * mprsas_read_cap_done function will load the read cap info into the
3742265236Sken	 * LUN struct.
3743265236Sken	 */
3744265236Sken	rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), M_MPR,
3745265236Sken	    M_NOWAIT | M_ZERO);
3746265236Sken	if (rcap_buf == NULL) {
3747283990Sslm		mpr_dprint(sc, MPR_ERROR, "Unable to alloc read capacity "
3748265236Sken		    "buffer for EEDP support.\n");
3749265236Sken		xpt_free_path(ccb->ccb_h.path);
3750265236Sken		xpt_free_ccb(ccb);
3751265236Sken		return;
3752265236Sken	}
3753265236Sken	xpt_setup_ccb(&ccb->ccb_h, local_path, CAM_PRIORITY_XPT);
3754265236Sken	csio = &ccb->csio;
3755265236Sken	csio->ccb_h.func_code = XPT_SCSI_IO;
3756265236Sken	csio->ccb_h.flags = CAM_DIR_IN;
3757265236Sken	csio->ccb_h.retry_count = 4;
3758265236Sken	csio->ccb_h.cbfcnp = mprsas_read_cap_done;
3759265236Sken	csio->ccb_h.timeout = 60000;
3760265236Sken	csio->data_ptr = (uint8_t *)rcap_buf;
3761265236Sken	csio->dxfer_len = sizeof(struct scsi_read_capacity_eedp);
3762265236Sken	csio->sense_len = MPR_SENSE_LEN;
3763265236Sken	csio->cdb_len = sizeof(*scsi_cmd);
3764265236Sken	csio->tag_action = MSG_SIMPLE_Q_TAG;
3765265236Sken
3766265236Sken	scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes;
3767265236Sken	bzero(scsi_cmd, sizeof(*scsi_cmd));
3768265236Sken	scsi_cmd->opcode = 0x9E;
3769265236Sken	scsi_cmd->service_action = SRC16_SERVICE_ACTION;
3770265236Sken	((uint8_t *)scsi_cmd)[13] = sizeof(struct scsi_read_capacity_eedp);
3771265236Sken
3772265236Sken	ccb->ccb_h.ppriv_ptr1 = sassc;
3773265236Sken	xpt_action(ccb);
3774265236Sken}
3775265236Sken
3776265236Skenstatic void
3777265236Skenmprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb)
3778265236Sken{
3779265236Sken	struct mprsas_softc *sassc;
3780265236Sken	struct mprsas_target *target;
3781265236Sken	struct mprsas_lun *lun;
3782265236Sken	struct scsi_read_capacity_eedp *rcap_buf;
3783265236Sken
3784265236Sken	if (done_ccb == NULL)
3785265236Sken		return;
3786265236Sken
3787265236Sken	/* Driver need to release devq, it Scsi command is
3788265236Sken	 * generated by driver internally.
3789265236Sken	 * Currently there is a single place where driver
3790265236Sken	 * calls scsi command internally. In future if driver
3791265236Sken	 * calls more scsi command internally, it needs to release
3792265236Sken	 * devq internally, since those command will not go back to
3793265236Sken	 * cam_periph.
3794265236Sken	 */
3795265236Sken	if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) ) {
3796265236Sken        	done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
3797265236Sken		xpt_release_devq(done_ccb->ccb_h.path,
3798265236Sken			       	/*count*/ 1, /*run_queue*/TRUE);
3799265236Sken	}
3800283990Sslm
3801265236Sken	rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr;
3802265236Sken
3803265236Sken	/*
3804265236Sken	 * Get the LUN ID for the path and look it up in the LUN list for the
3805265236Sken	 * target.
3806265236Sken	 */
3807265236Sken	sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1;
3808299962Sslm	KASSERT(done_ccb->ccb_h.target_id < sassc->maxtargets, ("Target %d out "
3809299962Sslm	    "of bounds in mprsas_read_cap_done\n", done_ccb->ccb_h.target_id));
3810265236Sken	target = &sassc->targets[done_ccb->ccb_h.target_id];
3811265236Sken	SLIST_FOREACH(lun, &target->luns, lun_link) {
3812265236Sken		if (lun->lun_id != done_ccb->ccb_h.target_lun)
3813265236Sken			continue;
3814265236Sken
3815265236Sken		/*
3816265236Sken		 * Got the LUN in the target's LUN list.  Fill it in with EEDP
3817283990Sslm		 * info. If the READ CAP 16 command had some SCSI error (common
3818265236Sken		 * if command is not supported), mark the lun as not supporting
3819265236Sken		 * EEDP and set the block size to 0.
3820265236Sken		 */
3821283990Sslm		if ((mprsas_get_ccbstatus(done_ccb) != CAM_REQ_CMP) ||
3822283990Sslm		    (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) {
3823265236Sken			lun->eedp_formatted = FALSE;
3824265236Sken			lun->eedp_block_size = 0;
3825265236Sken			break;
3826265236Sken		}
3827265236Sken
3828265236Sken		if (rcap_buf->protect & 0x01) {
3829283990Sslm			mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for target ID "
3830283990Sslm			    "%d is formatted for EEDP support.\n",
3831283990Sslm			    done_ccb->ccb_h.target_lun,
3832265236Sken			    done_ccb->ccb_h.target_id);
3833265236Sken			lun->eedp_formatted = TRUE;
3834265236Sken			lun->eedp_block_size = scsi_4btoul(rcap_buf->length);
3835265236Sken		}
3836265236Sken		break;
3837265236Sken	}
3838265236Sken
3839265236Sken	// Finished with this CCB and path.
3840265236Sken	free(rcap_buf, M_MPR);
3841265236Sken	xpt_free_path(done_ccb->ccb_h.path);
3842265236Sken	xpt_free_ccb(done_ccb);
3843265236Sken}
3844265236Sken#endif /* (__FreeBSD_version < 901503) || \
3845265236Sken          ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */
3846265236Sken
3847283990Sslmvoid
3848283990Sslmmprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm,
3849283990Sslm    struct mprsas_target *target, lun_id_t lun_id)
3850283990Sslm{
3851283990Sslm	union ccb *ccb;
3852283990Sslm	path_id_t path_id;
3853283990Sslm
3854283990Sslm	/*
3855283990Sslm	 * Set the INRESET flag for this target so that no I/O will be sent to
3856283990Sslm	 * the target until the reset has completed.  If an I/O request does
3857283990Sslm	 * happen, the devq will be frozen.  The CCB holds the path which is
3858283990Sslm	 * used to release the devq.  The devq is released and the CCB is freed
3859283990Sslm	 * when the TM completes.
3860283990Sslm	 */
3861283990Sslm	ccb = xpt_alloc_ccb_nowait();
3862283990Sslm	if (ccb) {
3863283990Sslm		path_id = cam_sim_path(sc->sassc->sim);
3864283990Sslm		if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id,
3865283990Sslm		    target->tid, lun_id) != CAM_REQ_CMP) {
3866283990Sslm			xpt_free_ccb(ccb);
3867283990Sslm		} else {
3868283990Sslm			tm->cm_ccb = ccb;
3869283990Sslm			tm->cm_targ = target;
3870283990Sslm			target->flags |= MPRSAS_TARGET_INRESET;
3871283990Sslm		}
3872283990Sslm	}
3873283990Sslm}
3874283990Sslm
3875265236Skenint
3876265236Skenmprsas_startup(struct mpr_softc *sc)
3877265236Sken{
3878265236Sken	/*
3879265236Sken	 * Send the port enable message and set the wait_for_port_enable flag.
3880265236Sken	 * This flag helps to keep the simq frozen until all discovery events
3881265236Sken	 * are processed.
3882265236Sken	 */
3883265236Sken	sc->wait_for_port_enable = 1;
3884265236Sken	mprsas_send_portenable(sc);
3885265236Sken	return (0);
3886265236Sken}
3887265236Sken
3888265236Skenstatic int
3889265236Skenmprsas_send_portenable(struct mpr_softc *sc)
3890265236Sken{
3891265236Sken	MPI2_PORT_ENABLE_REQUEST *request;
3892265236Sken	struct mpr_command *cm;
3893265236Sken
3894265236Sken	MPR_FUNCTRACE(sc);
3895265236Sken
3896265236Sken	if ((cm = mpr_alloc_command(sc)) == NULL)
3897265236Sken		return (EBUSY);
3898265236Sken	request = (MPI2_PORT_ENABLE_REQUEST *)cm->cm_req;
3899265236Sken	request->Function = MPI2_FUNCTION_PORT_ENABLE;
3900265236Sken	request->MsgFlags = 0;
3901265236Sken	request->VP_ID = 0;
3902265236Sken	cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
3903265236Sken	cm->cm_complete = mprsas_portenable_complete;
3904265236Sken	cm->cm_data = NULL;
3905265236Sken	cm->cm_sge = NULL;
3906265236Sken
3907265236Sken	mpr_map_command(sc, cm);
3908265236Sken	mpr_dprint(sc, MPR_XINFO,
3909265236Sken	    "mpr_send_portenable finished cm %p req %p complete %p\n",
3910265236Sken	    cm, cm->cm_req, cm->cm_complete);
3911265236Sken	return (0);
3912265236Sken}
3913265236Sken
3914265236Skenstatic void
3915265236Skenmprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm)
3916265236Sken{
3917265236Sken	MPI2_PORT_ENABLE_REPLY *reply;
3918265236Sken	struct mprsas_softc *sassc;
3919265236Sken
3920265236Sken	MPR_FUNCTRACE(sc);
3921265236Sken	sassc = sc->sassc;
3922265236Sken
3923265236Sken	/*
3924265236Sken	 * Currently there should be no way we can hit this case.  It only
3925265236Sken	 * happens when we have a failure to allocate chain frames, and
3926265236Sken	 * port enable commands don't have S/G lists.
3927265236Sken	 */
3928265236Sken	if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) {
3929265236Sken		mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for port enable! "
3930265236Sken		    "This should not happen!\n", __func__, cm->cm_flags);
3931265236Sken	}
3932265236Sken
3933265236Sken	reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply;
3934265236Sken	if (reply == NULL)
3935265236Sken		mpr_dprint(sc, MPR_FAULT, "Portenable NULL reply\n");
3936265236Sken	else if (le16toh(reply->IOCStatus & MPI2_IOCSTATUS_MASK) !=
3937265236Sken	    MPI2_IOCSTATUS_SUCCESS)
3938265236Sken		mpr_dprint(sc, MPR_FAULT, "Portenable failed\n");
3939265236Sken
3940265236Sken	mpr_free_command(sc, cm);
3941265236Sken	if (sc->mpr_ich.ich_arg != NULL) {
3942265236Sken		mpr_dprint(sc, MPR_XINFO, "disestablish config intrhook\n");
3943265236Sken		config_intrhook_disestablish(&sc->mpr_ich);
3944265236Sken		sc->mpr_ich.ich_arg = NULL;
3945265236Sken	}
3946265236Sken
3947265236Sken	/*
3948265236Sken	 * Done waiting for port enable to complete.  Decrement the refcount.
3949265236Sken	 * If refcount is 0, discovery is complete and a rescan of the bus can
3950265236Sken	 * take place.
3951265236Sken	 */
3952265236Sken	sc->wait_for_port_enable = 0;
3953265236Sken	sc->port_enable_complete = 1;
3954265236Sken	wakeup(&sc->port_enable_complete);
3955265236Sken	mprsas_startup_decrement(sassc);
3956265236Sken}
3957265236Sken
3958265236Skenint
3959265236Skenmprsas_check_id(struct mprsas_softc *sassc, int id)
3960265236Sken{
3961265236Sken	struct mpr_softc *sc = sassc->sc;
3962265236Sken	char *ids;
3963265236Sken	char *name;
3964265236Sken
3965265236Sken	ids = &sc->exclude_ids[0];
3966265236Sken	while((name = strsep(&ids, ",")) != NULL) {
3967265236Sken		if (name[0] == '\0')
3968265236Sken			continue;
3969265236Sken		if (strtol(name, NULL, 0) == (long)id)
3970265236Sken			return (1);
3971265236Sken	}
3972265236Sken
3973265236Sken	return (0);
3974265236Sken}
3975283990Sslm
3976283990Sslmvoid
3977283990Sslmmprsas_realloc_targets(struct mpr_softc *sc, int maxtargets)
3978283990Sslm{
3979283990Sslm	struct mprsas_softc *sassc;
3980283990Sslm	struct mprsas_lun *lun, *lun_tmp;
3981283990Sslm	struct mprsas_target *targ;
3982283990Sslm	int i;
3983283990Sslm
3984283990Sslm	sassc = sc->sassc;
3985283990Sslm	/*
3986283990Sslm	 * The number of targets is based on IOC Facts, so free all of
3987283990Sslm	 * the allocated LUNs for each target and then the target buffer
3988283990Sslm	 * itself.
3989283990Sslm	 */
3990283990Sslm	for (i=0; i< maxtargets; i++) {
3991283990Sslm		targ = &sassc->targets[i];
3992283990Sslm		SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) {
3993283990Sslm			free(lun, M_MPR);
3994283990Sslm		}
3995283990Sslm	}
3996283990Sslm	free(sassc->targets, M_MPR);
3997283990Sslm
3998283990Sslm	sassc->targets = malloc(sizeof(struct mprsas_target) * maxtargets,
3999283990Sslm	    M_MPR, M_WAITOK|M_ZERO);
4000283990Sslm	if (!sassc->targets) {
4001283990Sslm		panic("%s failed to alloc targets with error %d\n",
4002283990Sslm		    __func__, ENOMEM);
4003283990Sslm	}
4004283990Sslm}
4005