xref: /freebsd-14.2/sys/dev/mpi3mr/mpi3mr_cam.c (revision ae8388f7)
1 /*
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020-2023, Broadcom Inc. All rights reserved.
5  * Support: <[email protected]>
6  *
7  * Authors: Sumit Saxena <[email protected]>
8  *	    Chandrakanth Patil <[email protected]>
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are
12  * met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation and/or other
18  *    materials provided with the distribution.
19  * 3. Neither the name of the Broadcom Inc. nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software without
21  *    specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * The views and conclusions contained in the software and documentation are
36  * those of the authors and should not be interpreted as representing
37  * official policies,either expressed or implied, of the FreeBSD Project.
38  *
39  * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131
40  *
41  * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD
42  */
43 
44 #include <sys/cdefs.h>
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/selinfo.h>
50 #include <sys/module.h>
51 #include <sys/bus.h>
52 #include <sys/conf.h>
53 #include <sys/bio.h>
54 #include <sys/malloc.h>
55 #include <sys/uio.h>
56 #include <sys/sysctl.h>
57 #include <sys/endian.h>
58 #include <sys/queue.h>
59 #include <sys/kthread.h>
60 #include <sys/taskqueue.h>
61 #include <sys/sbuf.h>
62 
63 #include <machine/bus.h>
64 #include <machine/resource.h>
65 #include <sys/rman.h>
66 
67 #include <machine/stdarg.h>
68 
69 #include <cam/cam.h>
70 #include <cam/cam_ccb.h>
71 #include <cam/cam_debug.h>
72 #include <cam/cam_sim.h>
73 #include <cam/cam_xpt_sim.h>
74 #include <cam/cam_xpt_periph.h>
75 #include <cam/cam_periph.h>
76 #include <cam/scsi/scsi_all.h>
77 #include <cam/scsi/scsi_message.h>
78 #include <cam/scsi/smp_all.h>
79 
80 #include <dev/nvme/nvme.h>
81 #include "mpi/mpi30_api.h"
82 #include "mpi3mr_cam.h"
83 #include "mpi3mr.h"
84 #include <sys/time.h>			/* XXX for pcpu.h */
85 #include <sys/pcpu.h>			/* XXX for PCPU_GET */
86 
87 #define	smp_processor_id()  PCPU_GET(cpuid)
88 
89 static void
90 mpi3mr_enqueue_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm);
91 static void
92 mpi3mr_map_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm);
93 void
94 mpi3mr_release_simq_reinit(struct mpi3mr_cam_softc *cam_sc);
95 static void
96 mpi3mr_freeup_events(struct mpi3mr_softc *sc);
97 
98 extern int
99 mpi3mr_register_events(struct mpi3mr_softc *sc);
100 extern void mpi3mr_add_sg_single(void *paddr, U8 flags, U32 length,
101     bus_addr_t dma_addr);
102 
103 static U32 event_count;
104 
mpi3mr_prepare_sgls(void * arg,bus_dma_segment_t * segs,int nsegs,int error)105 static void mpi3mr_prepare_sgls(void *arg,
106 	bus_dma_segment_t *segs, int nsegs, int error)
107 {
108 	struct mpi3mr_softc *sc;
109 	struct mpi3mr_cmd *cm;
110 	u_int i;
111 	bus_addr_t chain_dma;
112 	void *chain;
113 	U8 *sg_local;
114 	U32 chain_length;
115 	int sges_left;
116 	U32 sges_in_segment;
117 	U8 simple_sgl_flags;
118 	U8 simple_sgl_flags_last;
119 	U8 last_chain_sgl_flags;
120 	struct mpi3mr_chain *chain_req;
121 	Mpi3SCSIIORequest_t *scsiio_req;
122 	union ccb *ccb;
123 
124 	cm = (struct mpi3mr_cmd *)arg;
125 	sc = cm->sc;
126 	scsiio_req = (Mpi3SCSIIORequest_t *) &cm->io_request;
127 	ccb = cm->ccb;
128 
129 	if (error) {
130 		device_printf(sc->mpi3mr_dev, "%s: error=%d\n",__func__, error);
131 		if (error == EFBIG) {
132 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_TOO_BIG);
133 		} else {
134 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
135 		}
136 		mpi3mr_release_command(cm);
137 		xpt_done(ccb);
138 		return;
139 	}
140 
141 	if (cm->data_dir == MPI3MR_READ)
142 		bus_dmamap_sync(sc->buffer_dmat, cm->dmamap,
143 		    BUS_DMASYNC_PREREAD);
144 	if (cm->data_dir == MPI3MR_WRITE)
145 		bus_dmamap_sync(sc->buffer_dmat, cm->dmamap,
146 		    BUS_DMASYNC_PREWRITE);
147 
148 	KASSERT(nsegs <= MPI3MR_SG_DEPTH && nsegs > 0,
149 	    ("%s: bad SGE count: %d\n", device_get_nameunit(sc->mpi3mr_dev), nsegs));
150 	KASSERT(scsiio_req->DataLength != 0,
151 	    ("%s: Data segments (%d), but DataLength == 0\n",
152 		device_get_nameunit(sc->mpi3mr_dev), nsegs));
153 
154 	simple_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE |
155 	    MPI3_SGE_FLAGS_DLAS_SYSTEM;
156 	simple_sgl_flags_last = simple_sgl_flags |
157 	    MPI3_SGE_FLAGS_END_OF_LIST;
158 	last_chain_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN |
159 	    MPI3_SGE_FLAGS_DLAS_SYSTEM;
160 
161 	sg_local = (U8 *)&scsiio_req->SGL;
162 
163 	sges_left = nsegs;
164 
165 	sges_in_segment = (sc->facts.op_req_sz -
166 	    offsetof(Mpi3SCSIIORequest_t, SGL))/sizeof(Mpi3SGESimple_t);
167 
168 	i = 0;
169 
170 	mpi3mr_dprint(sc, MPI3MR_TRACE, "SGE count: %d IO size: %d\n",
171 		nsegs, scsiio_req->DataLength);
172 
173 	if (sges_left <= sges_in_segment)
174 		goto fill_in_last_segment;
175 
176 	/* fill in main message segment when there is a chain following */
177 	while (sges_in_segment > 1) {
178 		mpi3mr_add_sg_single(sg_local, simple_sgl_flags,
179 		    segs[i].ds_len, segs[i].ds_addr);
180 		sg_local += sizeof(Mpi3SGESimple_t);
181 		sges_left--;
182 		sges_in_segment--;
183 		i++;
184 	}
185 
186 	chain_req = &sc->chain_sgl_list[cm->hosttag];
187 
188 	chain = chain_req->buf;
189 	chain_dma = chain_req->buf_phys;
190 	memset(chain_req->buf, 0, PAGE_SIZE);
191 	sges_in_segment = sges_left;
192 	chain_length = sges_in_segment * sizeof(Mpi3SGESimple_t);
193 
194 	mpi3mr_add_sg_single(sg_local, last_chain_sgl_flags,
195 	    chain_length, chain_dma);
196 
197 	sg_local = chain;
198 
199 fill_in_last_segment:
200 	while (sges_left > 0) {
201 		if (sges_left == 1)
202 			mpi3mr_add_sg_single(sg_local,
203 			    simple_sgl_flags_last, segs[i].ds_len,
204 			    segs[i].ds_addr);
205 		else
206 			mpi3mr_add_sg_single(sg_local, simple_sgl_flags,
207 			    segs[i].ds_len, segs[i].ds_addr);
208 		sg_local += sizeof(Mpi3SGESimple_t);
209 		sges_left--;
210 		i++;
211 	}
212 
213 	/*
214 	 * Now that we've created the sgls, we send the request to the device.
215 	 * Unlike in Linux, dmaload isn't guaranteed to load every time, but
216 	 * this function is always called when the resources are available, so
217 	 * we can send the request to hardware here always. mpi3mr_map_request
218 	 * knows about this quirk and will only take evasive action when an
219 	 * error other than EINPROGRESS is returned from dmaload.
220 	 */
221 	mpi3mr_enqueue_request(sc, cm);
222 
223 	return;
224 }
225 
226 static void
mpi3mr_map_request(struct mpi3mr_softc * sc,struct mpi3mr_cmd * cm)227 mpi3mr_map_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm)
228 {
229 	u_int32_t retcode = 0;
230 	union ccb *ccb;
231 
232 	ccb = cm->ccb;
233 	if (cm->data != NULL) {
234 		mtx_lock(&sc->io_lock);
235 		/* Map data buffer into bus space */
236 		retcode = bus_dmamap_load_ccb(sc->buffer_dmat, cm->dmamap,
237 		    ccb, mpi3mr_prepare_sgls, cm, 0);
238 		mtx_unlock(&sc->io_lock);
239 		if (retcode != 0 && retcode != EINPROGRESS) {
240 			device_printf(sc->mpi3mr_dev,
241 			    "bus_dmamap_load(): retcode = %d\n", retcode);
242 			/*
243 			 * Any other error means prepare_sgls wasn't called, and
244 			 * will never be called, so we have to mop up. This error
245 			 * should never happen, though.
246 			 */
247 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
248 			mpi3mr_release_command(cm);
249 			xpt_done(ccb);
250 		}
251 	} else {
252 		/*
253 		 * No data, we enqueue it directly here.
254 		 */
255 		mpi3mr_enqueue_request(sc, cm);
256 	}
257 }
258 
259 void
mpi3mr_unmap_request(struct mpi3mr_softc * sc,struct mpi3mr_cmd * cmd)260 mpi3mr_unmap_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd)
261 {
262 	if (cmd->data != NULL) {
263 		if (cmd->data_dir == MPI3MR_READ)
264 			bus_dmamap_sync(sc->buffer_dmat, cmd->dmamap, BUS_DMASYNC_POSTREAD);
265 		if (cmd->data_dir == MPI3MR_WRITE)
266 			bus_dmamap_sync(sc->buffer_dmat, cmd->dmamap, BUS_DMASYNC_POSTWRITE);
267 		mtx_lock(&sc->io_lock);
268 		bus_dmamap_unload(sc->buffer_dmat, cmd->dmamap);
269 		mtx_unlock(&sc->io_lock);
270 	}
271 }
272 
273 /**
274  * mpi3mr_allow_unmap_to_fw - Whether an unmap is allowed to fw
275  * @sc: Adapter instance reference
276  * @ccb: SCSI Command reference
277  *
278  * The controller hardware cannot handle certain unmap commands
279  * for NVMe drives, this routine checks those and return true
280  * and completes the SCSI command with proper status and sense
281  * data.
282  *
283  * Return: TRUE for allowed unmap, FALSE otherwise.
284  */
mpi3mr_allow_unmap_to_fw(struct mpi3mr_softc * sc,union ccb * ccb)285 static bool mpi3mr_allow_unmap_to_fw(struct mpi3mr_softc *sc,
286 	union ccb *ccb)
287 {
288 	struct ccb_scsiio *csio;
289 	uint16_t param_list_len, block_desc_len, trunc_param_len = 0;
290 
291 	csio = &ccb->csio;
292 	param_list_len = (uint16_t) ((scsiio_cdb_ptr(csio)[7] << 8) | scsiio_cdb_ptr(csio)[8]);
293 
294 	switch(pci_get_revid(sc->mpi3mr_dev)) {
295 	case SAS4116_CHIP_REV_A0:
296 		if (!param_list_len) {
297 			mpi3mr_dprint(sc, MPI3MR_ERROR,
298 			    "%s: CDB received with zero parameter length\n",
299 			    __func__);
300 			mpi3mr_print_cdb(ccb);
301 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
302 			xpt_done(ccb);
303 			return false;
304 		}
305 
306 		if (param_list_len < 24) {
307 			mpi3mr_dprint(sc, MPI3MR_ERROR,
308 			    "%s: CDB received with invalid param_list_len: %d\n",
309 			    __func__, param_list_len);
310 			mpi3mr_print_cdb(ccb);
311 			scsi_set_sense_data(&ccb->csio.sense_data,
312 				/*sense_format*/ SSD_TYPE_FIXED,
313 				/*current_error*/ 1,
314 				/*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
315 				/*asc*/ 0x1A,
316 				/*ascq*/ 0x00,
317 				/*extra args*/ SSD_ELEM_NONE);
318 			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
319 			ccb->ccb_h.status =
320 			    CAM_SCSI_STATUS_ERROR |
321 			    CAM_AUTOSNS_VALID;
322 			return false;
323 		}
324 
325 		if (param_list_len != csio->dxfer_len) {
326 			mpi3mr_dprint(sc, MPI3MR_ERROR,
327 			    "%s: CDB received with param_list_len: %d bufflen: %d\n",
328 			    __func__, param_list_len, csio->dxfer_len);
329 			mpi3mr_print_cdb(ccb);
330 			scsi_set_sense_data(&ccb->csio.sense_data,
331 				/*sense_format*/ SSD_TYPE_FIXED,
332 				/*current_error*/ 1,
333 				/*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
334 				/*asc*/ 0x1A,
335 				/*ascq*/ 0x00,
336 				/*extra args*/ SSD_ELEM_NONE);
337 			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
338 			ccb->ccb_h.status =
339 			    CAM_SCSI_STATUS_ERROR |
340 			    CAM_AUTOSNS_VALID;
341 			xpt_done(ccb);
342 			return false;
343 		}
344 
345 		block_desc_len = (uint16_t) (csio->data_ptr[2] << 8 | csio->data_ptr[3]);
346 
347 		if (block_desc_len < 16) {
348 			mpi3mr_dprint(sc, MPI3MR_ERROR,
349 			    "%s: Invalid descriptor length in param list: %d\n",
350 			    __func__, block_desc_len);
351 			mpi3mr_print_cdb(ccb);
352 			scsi_set_sense_data(&ccb->csio.sense_data,
353 				/*sense_format*/ SSD_TYPE_FIXED,
354 				/*current_error*/ 1,
355 				/*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
356 				/*asc*/ 0x26,
357 				/*ascq*/ 0x00,
358 				/*extra args*/ SSD_ELEM_NONE);
359 			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
360 			ccb->ccb_h.status =
361 			    CAM_SCSI_STATUS_ERROR |
362 			    CAM_AUTOSNS_VALID;
363 			xpt_done(ccb);
364 			return false;
365 		}
366 
367 		if (param_list_len > (block_desc_len + 8)) {
368 			mpi3mr_print_cdb(ccb);
369 			mpi3mr_dprint(sc, MPI3MR_INFO,
370 			    "%s: Truncating param_list_len(%d) to block_desc_len+8(%d)\n",
371 			    __func__, param_list_len, (block_desc_len + 8));
372 			param_list_len = block_desc_len + 8;
373 			scsiio_cdb_ptr(csio)[7] = (param_list_len >> 8) | 0xff;
374 			scsiio_cdb_ptr(csio)[8] = param_list_len | 0xff;
375 			mpi3mr_print_cdb(ccb);
376 		}
377 		break;
378 
379 	case SAS4116_CHIP_REV_B0:
380 		if ((param_list_len > 24) && ((param_list_len - 8) & 0xF)) {
381 			trunc_param_len -= (param_list_len - 8) & 0xF;
382 			mpi3mr_print_cdb(ccb);
383 			mpi3mr_dprint(sc, MPI3MR_INFO,
384 			    "%s: Truncating param_list_len from (%d) to (%d)\n",
385 			    __func__, param_list_len, trunc_param_len);
386 			scsiio_cdb_ptr(csio)[7] = (param_list_len >> 8) | 0xff;
387 			scsiio_cdb_ptr(csio)[8] = param_list_len | 0xff;
388 			mpi3mr_print_cdb(ccb);
389 		}
390 		break;
391 	}
392 
393 	return true;
394 }
395 
396 /**
397  * mpi3mr_tm_response_name -  get TM response as a string
398  * @resp_code: TM response code
399  *
400  * Convert known task management response code as a readable
401  * string.
402  *
403  * Return: response code string.
404  */
mpi3mr_tm_response_name(U8 resp_code)405 static const char* mpi3mr_tm_response_name(U8 resp_code)
406 {
407 	char *desc;
408 
409 	switch (resp_code) {
410 	case MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE:
411 		desc = "task management request completed";
412 		break;
413 	case MPI3_SCSITASKMGMT_RSPCODE_INVALID_FRAME:
414 		desc = "invalid frame";
415 		break;
416 	case MPI3_SCSITASKMGMT_RSPCODE_TM_FUNCTION_NOT_SUPPORTED:
417 		desc = "task management request not supported";
418 		break;
419 	case MPI3_SCSITASKMGMT_RSPCODE_TM_FAILED:
420 		desc = "task management request failed";
421 		break;
422 	case MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED:
423 		desc = "task management request succeeded";
424 		break;
425 	case MPI3_SCSITASKMGMT_RSPCODE_TM_INVALID_LUN:
426 		desc = "invalid LUN";
427 		break;
428 	case MPI3_SCSITASKMGMT_RSPCODE_TM_OVERLAPPED_TAG:
429 		desc = "overlapped tag attempted";
430 		break;
431 	case MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC:
432 		desc = "task queued, however not sent to target";
433 		break;
434 	case MPI3_SCSITASKMGMT_RSPCODE_TM_NVME_DENIED:
435 		desc = "task management request denied by NVMe device";
436 		break;
437 	default:
438 		desc = "unknown";
439 		break;
440 	}
441 
442 	return desc;
443 }
444 
mpi3mr_poll_pend_io_completions(struct mpi3mr_softc * sc)445 void mpi3mr_poll_pend_io_completions(struct mpi3mr_softc *sc)
446 {
447 	int i;
448 	int num_of_reply_queues = sc->num_queues;
449 	struct mpi3mr_irq_context *irq_ctx;
450 
451 	for (i = 0; i < num_of_reply_queues; i++) {
452 		irq_ctx = &sc->irq_ctx[i];
453 		mpi3mr_complete_io_cmd(sc, irq_ctx);
454 	}
455 }
456 
457 void
trigger_reset_from_watchdog(struct mpi3mr_softc * sc,U8 reset_type,U32 reset_reason)458 trigger_reset_from_watchdog(struct mpi3mr_softc *sc, U8 reset_type, U32 reset_reason)
459 {
460 	if (sc->reset_in_progress) {
461 		mpi3mr_dprint(sc, MPI3MR_INFO, "Another reset is in progress, no need to trigger the reset\n");
462 		return;
463 	}
464 	sc->reset.type = reset_type;
465 	sc->reset.reason = reset_reason;
466 
467 	return;
468 }
469 
470 /**
471  * mpi3mr_issue_tm - Issue Task Management request
472  * @sc: Adapter instance reference
473  * @tm_type: Task Management type
474  * @handle: Device handle
475  * @lun: lun ID
476  * @htag: Host tag of the TM request
477  * @timeout: TM timeout value
478  * @drv_cmd: Internal command tracker
479  * @resp_code: Response code place holder
480  * @cmd: Timed out command reference
481  *
482  * Issues a Task Management Request to the controller for a
483  * specified target, lun and command and wait for its completion
484  * and check TM response. Recover the TM if it timed out by
485  * issuing controller reset.
486  *
487  * Return: 0 on success, non-zero on errors
488  */
489 static int
mpi3mr_issue_tm(struct mpi3mr_softc * sc,struct mpi3mr_cmd * cmd,U8 tm_type,unsigned long timeout)490 mpi3mr_issue_tm(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd,
491 		U8 tm_type, unsigned long timeout)
492 {
493 	int retval = 0;
494 	MPI3_SCSI_TASK_MGMT_REQUEST tm_req;
495 	MPI3_SCSI_TASK_MGMT_REPLY *tm_reply = NULL;
496 	struct mpi3mr_drvr_cmd *drv_cmd = NULL;
497 	struct mpi3mr_target *tgtdev = NULL;
498 	struct mpi3mr_op_req_queue *op_req_q = NULL;
499 	union ccb *ccb;
500 	U8 resp_code;
501 
502 
503 	if (sc->unrecoverable) {
504 		mpi3mr_dprint(sc, MPI3MR_INFO,
505 			"Controller is in unrecoverable state!! TM not required\n");
506 		return retval;
507 	}
508 	if (sc->reset_in_progress) {
509 		mpi3mr_dprint(sc, MPI3MR_INFO,
510 			"controller reset in progress!! TM not required\n");
511 		return retval;
512 	}
513 
514 	if (!cmd->ccb) {
515 		mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n");
516 		return retval;
517 	}
518 	ccb = cmd->ccb;
519 
520 	tgtdev = cmd->targ;
521 	if (tgtdev == NULL)  {
522 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Device does not exist target ID:0x%x,"
523 			      "TM is not required\n", ccb->ccb_h.target_id);
524 		return retval;
525 	}
526 	if (tgtdev->dev_removed == 1)  {
527 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Device(0x%x) is removed, TM is not required\n",
528 			      ccb->ccb_h.target_id);
529 		return retval;
530 	}
531 
532 	drv_cmd = &sc->host_tm_cmds;
533 	mtx_lock(&drv_cmd->lock);
534 
535 	memset(&tm_req, 0, sizeof(tm_req));
536 	tm_req.DevHandle = htole16(tgtdev->dev_handle);
537 	tm_req.TaskType = tm_type;
538 	tm_req.HostTag = htole16(MPI3MR_HOSTTAG_TMS);
539 	int_to_lun(ccb->ccb_h.target_lun, tm_req.LUN);
540 	tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT;
541 	drv_cmd->state = MPI3MR_CMD_PENDING;
542 	drv_cmd->is_waiting = 1;
543 	drv_cmd->callback = NULL;
544 
545 	if (ccb) {
546 		if (tm_type == MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
547 			op_req_q = &sc->op_req_q[cmd->req_qidx];
548 			tm_req.TaskHostTag = htole16(cmd->hosttag);
549 			tm_req.TaskRequestQueueID = htole16(op_req_q->qid);
550 		}
551 	}
552 
553 	if (tgtdev)
554 		mpi3mr_atomic_inc(&tgtdev->block_io);
555 
556 	if (tgtdev && (tgtdev->dev_type == MPI3_DEVICE_DEVFORM_PCIE)) {
557 		if ((tm_type == MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
558 		     && tgtdev->dev_spec.pcie_inf.abort_to)
559  			timeout = tgtdev->dev_spec.pcie_inf.abort_to;
560 		else if ((tm_type == MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET)
561 			 && tgtdev->dev_spec.pcie_inf.reset_to)
562 			 timeout = tgtdev->dev_spec.pcie_inf.reset_to;
563 	}
564 
565 	sc->tm_chan = (void *)&drv_cmd;
566 
567 	mpi3mr_dprint(sc, MPI3MR_DEBUG_TM,
568 		      "posting task management request: type(%d), handle(0x%04x)\n",
569 		       tm_type, tgtdev->dev_handle);
570 
571 	init_completion(&drv_cmd->completion);
572 	retval = mpi3mr_submit_admin_cmd(sc, &tm_req, sizeof(tm_req));
573 	if (retval) {
574 		mpi3mr_dprint(sc, MPI3MR_ERROR,
575 			      "posting task management request is failed\n");
576 		retval = -1;
577 		goto out_unlock;
578 	}
579 	wait_for_completion_timeout_tm(&drv_cmd->completion, timeout, sc);
580 
581 	if (!(drv_cmd->state & MPI3MR_CMD_COMPLETE)) {
582 		drv_cmd->is_waiting = 0;
583 		retval = -1;
584 		if (!(drv_cmd->state & MPI3MR_CMD_RESET)) {
585 			mpi3mr_dprint(sc, MPI3MR_ERROR,
586 				      "task management request timed out after %ld seconds\n", timeout);
587 			if (sc->mpi3mr_debug & MPI3MR_DEBUG_TM) {
588 				mpi3mr_dprint(sc, MPI3MR_INFO, "tm_request dump\n");
589 				mpi3mr_hexdump(&tm_req, sizeof(tm_req), 8);
590 			}
591 			trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_TM_TIMEOUT);
592 			retval = ETIMEDOUT;
593 		}
594 		goto out_unlock;
595 	}
596 
597 	if (!(drv_cmd->state & MPI3MR_CMD_REPLYVALID)) {
598 		mpi3mr_dprint(sc, MPI3MR_ERROR,
599 			      "invalid task management reply message\n");
600 		retval = -1;
601 		goto out_unlock;
602 	}
603 	tm_reply = (MPI3_SCSI_TASK_MGMT_REPLY *)drv_cmd->reply;
604 
605 	switch (drv_cmd->ioc_status) {
606 	case MPI3_IOCSTATUS_SUCCESS:
607 		resp_code = tm_reply->ResponseData & MPI3MR_RI_MASK_RESPCODE;
608 		break;
609 	case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED:
610 		resp_code = MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE;
611 		break;
612 	default:
613 		mpi3mr_dprint(sc, MPI3MR_ERROR,
614 			      "task management request to handle(0x%04x) is failed with ioc_status(0x%04x) log_info(0x%08x)\n",
615 			       tgtdev->dev_handle, drv_cmd->ioc_status, drv_cmd->ioc_loginfo);
616 		retval = -1;
617 		goto out_unlock;
618 	}
619 
620 	switch (resp_code) {
621 	case MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED:
622 	case MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE:
623 		break;
624 	case MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC:
625 		if (tm_type != MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK)
626 			retval = -1;
627 		break;
628 	default:
629 		retval = -1;
630 		break;
631 	}
632 
633 	mpi3mr_dprint(sc, MPI3MR_DEBUG_TM,
634 		      "task management request type(%d) completed for handle(0x%04x) with ioc_status(0x%04x), log_info(0x%08x)"
635 		      "termination_count(%u), response:%s(0x%x)\n", tm_type, tgtdev->dev_handle, drv_cmd->ioc_status, drv_cmd->ioc_loginfo,
636 		      tm_reply->TerminationCount, mpi3mr_tm_response_name(resp_code), resp_code);
637 
638 	if (retval)
639 		goto out_unlock;
640 
641 	mpi3mr_disable_interrupts(sc);
642 	mpi3mr_poll_pend_io_completions(sc);
643 	mpi3mr_enable_interrupts(sc);
644 	mpi3mr_poll_pend_io_completions(sc);
645 
646 	switch (tm_type) {
647 	case MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
648 		if (cmd->state == MPI3MR_CMD_STATE_IN_TM) {
649 			mpi3mr_dprint(sc, MPI3MR_ERROR,
650 				      "%s: task abort returned success from firmware but corresponding CCB (%p) was not terminated"
651 				      "marking task abort failed!\n", sc->name, cmd->ccb);
652 			retval = -1;
653 		}
654 		break;
655 	case MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
656 		if (mpi3mr_atomic_read(&tgtdev->outstanding)) {
657 			mpi3mr_dprint(sc, MPI3MR_ERROR,
658 				      "%s: target reset returned success from firmware but IOs are still pending on the target (%p)"
659 				      "marking target reset failed!\n",
660 				      sc->name, tgtdev);
661 			retval = -1;
662 		}
663 		break;
664 	default:
665 		break;
666 	}
667 
668 out_unlock:
669 	drv_cmd->state = MPI3MR_CMD_NOTUSED;
670 	mtx_unlock(&drv_cmd->lock);
671 	if (tgtdev && mpi3mr_atomic_read(&tgtdev->block_io) > 0)
672 		mpi3mr_atomic_dec(&tgtdev->block_io);
673 
674 	return retval;
675 }
676 
677 /**
678  * mpi3mr_task_abort- Abort error handling callback
679  * @cmd: Timed out command reference
680  *
681  * Issue Abort Task Management if the command is in LLD scope
682  * and verify if it is aborted successfully and return status
683  * accordingly.
684  *
685  * Return: SUCCESS of successful abort the SCSI command else FAILED
686  */
mpi3mr_task_abort(struct mpi3mr_cmd * cmd)687 static int mpi3mr_task_abort(struct mpi3mr_cmd *cmd)
688 {
689 	int retval = 0;
690 	struct mpi3mr_softc *sc;
691 	union ccb *ccb;
692 
693 	sc = cmd->sc;
694 
695 	if (!cmd->ccb) {
696 		mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n");
697 		return retval;
698 	}
699 	ccb = cmd->ccb;
700 
701 	mpi3mr_dprint(sc, MPI3MR_INFO,
702 		      "attempting abort task for ccb(%p)\n", ccb);
703 
704 	mpi3mr_print_cdb(ccb);
705 
706 	if (cmd->state != MPI3MR_CMD_STATE_BUSY) {
707 		mpi3mr_dprint(sc, MPI3MR_INFO,
708 			      "%s: ccb is not in driver scope, abort task is not required\n",
709 			      sc->name);
710 		return retval;
711 	}
712 	cmd->state = MPI3MR_CMD_STATE_IN_TM;
713 
714 	retval = mpi3mr_issue_tm(sc, cmd, MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK, MPI3MR_ABORTTM_TIMEOUT);
715 
716 	mpi3mr_dprint(sc, MPI3MR_INFO,
717 		      "abort task is %s for ccb(%p)\n", ((retval == 0) ? "SUCCESS" : "FAILED"), ccb);
718 
719 	return retval;
720 }
721 
722 /**
723  * mpi3mr_target_reset - Target reset error handling callback
724  * @cmd: Timed out command reference
725  *
726  * Issue Target reset Task Management and verify the SCSI commands are
727  * terminated successfully and return status accordingly.
728  *
729  * Return: SUCCESS of successful termination of the SCSI commands else
730  *         FAILED
731  */
mpi3mr_target_reset(struct mpi3mr_cmd * cmd)732 static int mpi3mr_target_reset(struct mpi3mr_cmd *cmd)
733 {
734 	int retval = 0;
735 	struct mpi3mr_softc *sc;
736 	struct mpi3mr_target *target;
737 
738 	sc = cmd->sc;
739 
740 	target = cmd->targ;
741 	if (target == NULL)  {
742 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Device does not exist for target:0x%p,"
743 			      "target reset is not required\n", target);
744 		return retval;
745 	}
746 
747 	mpi3mr_dprint(sc, MPI3MR_INFO,
748 		      "attempting target reset on target(%d)\n", target->per_id);
749 
750 
751 	if (mpi3mr_atomic_read(&target->outstanding)) {
752 		mpi3mr_dprint(sc, MPI3MR_INFO,
753 			      "no outstanding IOs on the target(%d),"
754 			      " target reset not required.\n", target->per_id);
755 		return retval;
756 	}
757 
758 	retval = mpi3mr_issue_tm(sc, cmd, MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET, MPI3MR_RESETTM_TIMEOUT);
759 
760 	mpi3mr_dprint(sc, MPI3MR_INFO,
761 		      "target reset is %s for target(%d)\n", ((retval == 0) ? "SUCCESS" : "FAILED"),
762 		      target->per_id);
763 
764 	return retval;
765 }
766 
767 /**
768  * mpi3mr_get_fw_pending_ios - Calculate pending I/O count
769  * @sc: Adapter instance reference
770  *
771  * Calculate the pending I/Os for the controller and return.
772  *
773  * Return: Number of pending I/Os
774  */
mpi3mr_get_fw_pending_ios(struct mpi3mr_softc * sc)775 static inline int mpi3mr_get_fw_pending_ios(struct mpi3mr_softc *sc)
776 {
777 	U16 i, pend_ios = 0;
778 
779 	for (i = 0; i < sc->num_queues; i++)
780 		pend_ios += mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios);
781 	return pend_ios;
782 }
783 
784 /**
785  * mpi3mr_wait_for_host_io - block for I/Os to complete
786  * @sc: Adapter instance reference
787  * @timeout: time out in seconds
788  *
789  * Waits for pending I/Os for the given adapter to complete or
790  * to hit the timeout.
791  *
792  * Return: Nothing
793  */
mpi3mr_wait_for_host_io(struct mpi3mr_softc * sc,U32 timeout)794 static int mpi3mr_wait_for_host_io(struct mpi3mr_softc *sc, U32 timeout)
795 {
796 	enum mpi3mr_iocstate iocstate;
797 
798 	iocstate = mpi3mr_get_iocstate(sc);
799 	if (iocstate != MRIOC_STATE_READY) {
800 		mpi3mr_dprint(sc, MPI3MR_XINFO, "%s :Controller is in NON-READY state! Proceed with Reset\n", __func__);
801 		return -1;
802 	}
803 
804 	if (!mpi3mr_get_fw_pending_ios(sc))
805 		return 0;
806 
807 	mpi3mr_dprint(sc, MPI3MR_INFO,
808 		      "%s :Waiting for %d seconds prior to reset for %d pending I/Os to complete\n",
809 		      __func__, timeout, mpi3mr_get_fw_pending_ios(sc));
810 
811 	int i;
812 	for (i = 0; i < timeout; i++) {
813 		if (!mpi3mr_get_fw_pending_ios(sc)) {
814 			mpi3mr_dprint(sc, MPI3MR_INFO, "%s :All pending I/Os got completed while waiting! Reset not required\n", __func__);
815 			return 0;
816 
817 		}
818 		iocstate = mpi3mr_get_iocstate(sc);
819 		if (iocstate != MRIOC_STATE_READY) {
820 			mpi3mr_dprint(sc, MPI3MR_XINFO, "%s :Controller state becomes NON-READY while waiting! dont wait further"
821 				      "Proceed with Reset\n", __func__);
822 			return -1;
823 		}
824 		DELAY(1000 * 1000);
825 	}
826 
827 	mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Pending I/Os after wait exaust is %d! Proceed with Reset\n", __func__,
828 		      mpi3mr_get_fw_pending_ios(sc));
829 
830 	return -1;
831 }
832 
833 static void
mpi3mr_scsiio_timeout(void * data)834 mpi3mr_scsiio_timeout(void *data)
835 {
836 	int retval = 0;
837 	struct mpi3mr_softc *sc;
838 	struct mpi3mr_cmd *cmd;
839 	struct mpi3mr_target *targ_dev = NULL;
840 
841 	if (!data)
842 		return;
843 
844 	cmd = (struct mpi3mr_cmd *)data;
845 	sc = cmd->sc;
846 
847 	if (cmd->ccb == NULL) {
848 		mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n");
849 		return;
850 	}
851 
852 	/*
853 	 * TMs are not supported for IO timeouts on VD/LD, so directly issue controller reset
854 	 * with max timeout for outstanding IOs to complete is 180sec.
855 	 */
856 	targ_dev = cmd->targ;
857 	if (targ_dev && (targ_dev->dev_type == MPI3_DEVICE_DEVFORM_VD)) {
858 		if (mpi3mr_wait_for_host_io(sc, MPI3MR_RAID_ERRREC_RESET_TIMEOUT))
859 			trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_SCSIIO_TIMEOUT);
860 		return;
861  	}
862 
863 	/* Issue task abort to recover the timed out IO */
864 	retval = mpi3mr_task_abort(cmd);
865 	if (!retval || (retval == ETIMEDOUT))
866 		return;
867 
868 	/*
869 	 * task abort has failed to recover the timed out IO,
870 	 * try with the target reset
871 	 */
872 	retval = mpi3mr_target_reset(cmd);
873 	if (!retval || (retval == ETIMEDOUT))
874 		return;
875 
876 	/*
877 	 * task abort and target reset has failed. So issue Controller reset(soft reset)
878 	 * through OCR thread context
879 	 */
880 	trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_SCSIIO_TIMEOUT);
881 
882 	return;
883 }
884 
int_to_lun(unsigned int lun,U8 * req_lun)885 void int_to_lun(unsigned int lun, U8 *req_lun)
886 {
887 	int i;
888 
889 	memset(req_lun, 0, sizeof(*req_lun));
890 
891 	for (i = 0; i < sizeof(lun); i += 2) {
892 		req_lun[i] = (lun >> 8) & 0xFF;
893 		req_lun[i+1] = lun & 0xFF;
894 		lun = lun >> 16;
895 	}
896 
897 }
898 
get_req_queue_index(struct mpi3mr_softc * sc)899 static U16 get_req_queue_index(struct mpi3mr_softc *sc)
900 {
901 	U16 i = 0, reply_q_index = 0, reply_q_pend_ios = 0;
902 
903 	reply_q_pend_ios = mpi3mr_atomic_read(&sc->op_reply_q[0].pend_ios);
904 	for (i = 0; i < sc->num_queues; i++) {
905 		if (reply_q_pend_ios > mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios)) {
906 			reply_q_pend_ios = mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios);
907 			reply_q_index = i;
908 		}
909 	}
910 
911 	return reply_q_index;
912 }
913 
914 static void
mpi3mr_action_scsiio(struct mpi3mr_cam_softc * cam_sc,union ccb * ccb)915 mpi3mr_action_scsiio(struct mpi3mr_cam_softc *cam_sc, union ccb *ccb)
916 {
917 	Mpi3SCSIIORequest_t *req = NULL;
918 	struct ccb_scsiio *csio;
919 	struct mpi3mr_softc *sc;
920 	struct mpi3mr_target *targ;
921 	struct mpi3mr_cmd *cm;
922 	uint8_t scsi_opcode, queue_idx;
923 	uint32_t mpi_control;
924 
925 	sc = cam_sc->sc;
926 	mtx_assert(&sc->mpi3mr_mtx, MA_OWNED);
927 
928 	if (sc->unrecoverable) {
929 		mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
930 		xpt_done(ccb);
931 		return;
932 	}
933 
934 	csio = &ccb->csio;
935 	KASSERT(csio->ccb_h.target_id < cam_sc->maxtargets,
936 	    ("Target %d out of bounds in XPT_SCSI_IO\n",
937 	     csio->ccb_h.target_id));
938 
939 	scsi_opcode = scsiio_cdb_ptr(csio)[0];
940 
941 	if ((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) &&
942 	    !((scsi_opcode == SYNCHRONIZE_CACHE) ||
943 	      (scsi_opcode == START_STOP_UNIT))) {
944 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
945 		xpt_done(ccb);
946 		return;
947 	}
948 
949 	targ = mpi3mr_find_target_by_per_id(cam_sc, csio->ccb_h.target_id);
950 	if (targ == NULL)  {
951 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x does not exist\n",
952 			      csio->ccb_h.target_id);
953 		mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
954 		xpt_done(ccb);
955 		return;
956 	}
957 
958 	if (targ && targ->is_hidden)  {
959 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x is hidden\n",
960 			      csio->ccb_h.target_id);
961 		mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
962 		xpt_done(ccb);
963 		return;
964 	}
965 
966 	if (targ->dev_removed == 1)  {
967 		mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x is removed\n", csio->ccb_h.target_id);
968 		mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
969 		xpt_done(ccb);
970 		return;
971 	}
972 
973 	if (targ->dev_handle == 0x0) {
974 		mpi3mr_dprint(sc, MPI3MR_ERROR, "%s NULL handle for target 0x%x\n",
975 		    __func__, csio->ccb_h.target_id);
976 		mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
977 		xpt_done(ccb);
978 		return;
979 	}
980 
981 	if (mpi3mr_atomic_read(&targ->block_io) ||
982 		(sc->reset_in_progress == 1) || (sc->prepare_for_reset == 1)) {
983 		mpi3mr_dprint(sc, MPI3MR_TRACE, "%s target is busy target_id: 0x%x\n",
984 		    __func__, csio->ccb_h.target_id);
985 		mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ);
986 		xpt_done(ccb);
987 		return;
988 	}
989 
990 	/*
991 	 * Sometimes, it is possible to get a command that is not "In
992 	 * Progress" and was actually aborted by the upper layer.  Check for
993 	 * this here and complete the command without error.
994 	 */
995 	if (mpi3mr_get_ccbstatus(ccb) != CAM_REQ_INPROG) {
996 		mpi3mr_dprint(sc, MPI3MR_TRACE, "%s Command is not in progress for "
997 		    "target %u\n", __func__, csio->ccb_h.target_id);
998 		xpt_done(ccb);
999 		return;
1000 	}
1001 	/*
1002 	 * If devinfo is 0 this will be a volume.  In that case don't tell CAM
1003 	 * that the volume has timed out.  We want volumes to be enumerated
1004 	 * until they are deleted/removed, not just failed.
1005 	 */
1006 	if (targ->flags & MPI3MRSAS_TARGET_INREMOVAL) {
1007 		if (targ->devinfo == 0)
1008 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
1009 		else
1010 			mpi3mr_set_ccbstatus(ccb, CAM_SEL_TIMEOUT);
1011 		xpt_done(ccb);
1012 		return;
1013 	}
1014 
1015 	if ((scsi_opcode == UNMAP) &&
1016 		(pci_get_device(sc->mpi3mr_dev) == MPI3_MFGPAGE_DEVID_SAS4116) &&
1017 		(targ->dev_type == MPI3_DEVICE_DEVFORM_PCIE) &&
1018 		(mpi3mr_allow_unmap_to_fw(sc, ccb) == false))
1019 		return;
1020 
1021 	cm = mpi3mr_get_command(sc);
1022 	if (cm == NULL || (sc->mpi3mr_flags & MPI3MR_FLAGS_DIAGRESET)) {
1023 		if (cm != NULL) {
1024 			mpi3mr_release_command(cm);
1025 		}
1026 		if ((cam_sc->flags & MPI3MRSAS_QUEUE_FROZEN) == 0) {
1027 			xpt_freeze_simq(cam_sc->sim, 1);
1028 			cam_sc->flags |= MPI3MRSAS_QUEUE_FROZEN;
1029 		}
1030 		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1031 		mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ);
1032 		xpt_done(ccb);
1033 		return;
1034 	}
1035 
1036 	switch (csio->ccb_h.flags & CAM_DIR_MASK) {
1037 	case CAM_DIR_IN:
1038 		mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_READ;
1039 		cm->data_dir = MPI3MR_READ;
1040 		break;
1041 	case CAM_DIR_OUT:
1042 		mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_WRITE;
1043 		cm->data_dir = MPI3MR_WRITE;
1044 		break;
1045 	case CAM_DIR_NONE:
1046 	default:
1047 		mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_NO_DATA_TRANSFER;
1048 		break;
1049 	}
1050 
1051 	if (csio->cdb_len > 16)
1052 		mpi_control |= MPI3_SCSIIO_FLAGS_CDB_GREATER_THAN_16;
1053 
1054 	req = (Mpi3SCSIIORequest_t *)&cm->io_request;
1055 	bzero(req, sizeof(*req));
1056 	req->Function = MPI3_FUNCTION_SCSI_IO;
1057 	req->HostTag = cm->hosttag;
1058 	req->DataLength = htole32(csio->dxfer_len);
1059 	req->DevHandle = htole16(targ->dev_handle);
1060 
1061 	/*
1062 	 * It looks like the hardware doesn't require an explicit tag
1063 	 * number for each transaction.  SAM Task Management not supported
1064 	 * at the moment.
1065 	 */
1066 	switch (csio->tag_action) {
1067 	case MSG_HEAD_OF_Q_TAG:
1068 		mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_HEADOFQ;
1069 		break;
1070 	case MSG_ORDERED_Q_TAG:
1071 		mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ORDEREDQ;
1072 		break;
1073 	case MSG_ACA_TASK:
1074 		mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ACAQ;
1075 		break;
1076 	case CAM_TAG_ACTION_NONE:
1077 	case MSG_SIMPLE_Q_TAG:
1078 	default:
1079 		mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_SIMPLEQ;
1080 		break;
1081 	}
1082 
1083 	req->Flags = htole32(mpi_control);
1084 
1085 	if (csio->ccb_h.flags & CAM_CDB_POINTER)
1086 		bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len);
1087 	else {
1088 		KASSERT(csio->cdb_len <= IOCDBLEN,
1089 		    ("cdb_len %d is greater than IOCDBLEN but CAM_CDB_POINTER "
1090 		    "is not set", csio->cdb_len));
1091 		bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len);
1092 	}
1093 
1094 	cm->length = csio->dxfer_len;
1095 	cm->targ = targ;
1096 	int_to_lun(csio->ccb_h.target_lun, req->LUN);
1097 	cm->ccb = ccb;
1098 	csio->ccb_h.qos.sim_data = sbinuptime();
1099 	queue_idx = get_req_queue_index(sc);
1100 	cm->req_qidx = queue_idx;
1101 
1102 	mpi3mr_dprint(sc, MPI3MR_TRACE, "[QID:%d]: func: %s line:%d CDB: 0x%x targetid: %x SMID: 0x%x\n",
1103 		(queue_idx + 1), __func__, __LINE__, scsi_opcode, csio->ccb_h.target_id, cm->hosttag);
1104 
1105 	switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) {
1106 	case CAM_DATA_PADDR:
1107 	case CAM_DATA_SG_PADDR:
1108 		device_printf(sc->mpi3mr_dev, "%s: physical addresses not supported\n",
1109 		    __func__);
1110 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_INVALID);
1111 		mpi3mr_release_command(cm);
1112 		xpt_done(ccb);
1113 		return;
1114 	case CAM_DATA_SG:
1115 		device_printf(sc->mpi3mr_dev, "%s: scatter gather is not supported\n",
1116 		    __func__);
1117 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_INVALID);
1118 		mpi3mr_release_command(cm);
1119 		xpt_done(ccb);
1120 		return;
1121 	case CAM_DATA_VADDR:
1122 	case CAM_DATA_BIO:
1123 		if (csio->dxfer_len > (MPI3MR_SG_DEPTH * MPI3MR_4K_PGSZ)) {
1124 			mpi3mr_set_ccbstatus(ccb, CAM_REQ_TOO_BIG);
1125 			mpi3mr_release_command(cm);
1126 			xpt_done(ccb);
1127 			return;
1128 		}
1129 		ccb->ccb_h.status |= CAM_SIM_QUEUED;
1130 		cm->length = csio->dxfer_len;
1131 		if (cm->length)
1132 			cm->data = csio->data_ptr;
1133 		break;
1134 	default:
1135 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_INVALID);
1136 		mpi3mr_release_command(cm);
1137 		xpt_done(ccb);
1138 		return;
1139 	}
1140 
1141 	/* Prepare SGEs and queue to hardware */
1142 	mpi3mr_map_request(sc, cm);
1143 }
1144 
1145 static void
mpi3mr_enqueue_request(struct mpi3mr_softc * sc,struct mpi3mr_cmd * cm)1146 mpi3mr_enqueue_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm)
1147 {
1148 	static int ratelimit;
1149 	struct mpi3mr_op_req_queue *opreqq = &sc->op_req_q[cm->req_qidx];
1150 	struct mpi3mr_throttle_group_info *tg = NULL;
1151 	uint32_t data_len_blks = 0;
1152 	uint32_t tracked_io_sz = 0;
1153 	uint32_t ioc_pend_data_len = 0, tg_pend_data_len = 0;
1154 	struct mpi3mr_target *targ = cm->targ;
1155 	union ccb *ccb = cm->ccb;
1156 	Mpi3SCSIIORequest_t *req = (Mpi3SCSIIORequest_t *)&cm->io_request;
1157 
1158 	if (sc->iot_enable) {
1159 		data_len_blks = ccb->csio.dxfer_len >> 9;
1160 
1161 		if ((data_len_blks >= sc->io_throttle_data_length) &&
1162 		    targ->io_throttle_enabled) {
1163 
1164 			tracked_io_sz = data_len_blks;
1165 			tg = targ->throttle_group;
1166 			if (tg) {
1167 				mpi3mr_atomic_add(&sc->pend_large_data_sz, data_len_blks);
1168 				mpi3mr_atomic_add(&tg->pend_large_data_sz, data_len_blks);
1169 
1170 				ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz);
1171 				tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz);
1172 
1173 				if (ratelimit % 1000) {
1174 					mpi3mr_dprint(sc, MPI3MR_IOT,
1175 						"large vd_io persist_id(%d), handle(0x%04x), data_len(%d),"
1176 						"ioc_pending(%d), tg_pending(%d), ioc_high(%d), tg_high(%d)\n",
1177 						targ->per_id, targ->dev_handle,
1178 						data_len_blks, ioc_pend_data_len,
1179 						tg_pend_data_len, sc->io_throttle_high,
1180 						tg->high);
1181 					ratelimit++;
1182 				}
1183 
1184 				if (!tg->io_divert  && ((ioc_pend_data_len >=
1185 				    sc->io_throttle_high) ||
1186 				    (tg_pend_data_len >= tg->high))) {
1187 					tg->io_divert = 1;
1188 					mpi3mr_dprint(sc, MPI3MR_IOT,
1189 						"VD: Setting divert flag for tg_id(%d), persist_id(%d)\n",
1190 						tg->id, targ->per_id);
1191 					if (sc->mpi3mr_debug | MPI3MR_IOT)
1192 						mpi3mr_print_cdb(ccb);
1193 					mpi3mr_set_io_divert_for_all_vd_in_tg(sc,
1194 					    tg, 1);
1195 				}
1196 			} else {
1197 				mpi3mr_atomic_add(&sc->pend_large_data_sz, data_len_blks);
1198 				ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz);
1199 				if (ratelimit % 1000) {
1200 					mpi3mr_dprint(sc, MPI3MR_IOT,
1201 					    "large pd_io persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_high(%d)\n",
1202 					    targ->per_id, targ->dev_handle,
1203 					    data_len_blks, ioc_pend_data_len,
1204 					    sc->io_throttle_high);
1205 					ratelimit++;
1206 				}
1207 
1208 				if (ioc_pend_data_len >= sc->io_throttle_high) {
1209 					targ->io_divert = 1;
1210 					mpi3mr_dprint(sc, MPI3MR_IOT,
1211 						"PD: Setting divert flag for persist_id(%d)\n",
1212 						targ->per_id);
1213 					if (sc->mpi3mr_debug | MPI3MR_IOT)
1214 						mpi3mr_print_cdb(ccb);
1215 				}
1216 			}
1217 		}
1218 
1219 		if (targ->io_divert) {
1220 			req->MsgFlags |= MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE;
1221 			req->Flags = htole32(le32toh(req->Flags) | MPI3_SCSIIO_FLAGS_DIVERT_REASON_IO_THROTTLING);
1222 		}
1223 	}
1224 
1225 	if (mpi3mr_submit_io(sc, opreqq, (U8 *)&cm->io_request)) {
1226 		if (tracked_io_sz) {
1227 			mpi3mr_atomic_sub(&sc->pend_large_data_sz, tracked_io_sz);
1228 			if (tg)
1229 				mpi3mr_atomic_sub(&tg->pend_large_data_sz, tracked_io_sz);
1230 		}
1231 		mpi3mr_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL);
1232 		mpi3mr_release_command(cm);
1233 		xpt_done(ccb);
1234 	} else {
1235 		callout_reset_sbt(&cm->callout, mstosbt(ccb->ccb_h.timeout), 0,
1236 		    mpi3mr_scsiio_timeout, cm, 0);
1237 		cm->callout_owner = true;
1238 		mpi3mr_atomic_inc(&sc->fw_outstanding);
1239 		mpi3mr_atomic_inc(&targ->outstanding);
1240 		if (mpi3mr_atomic_read(&sc->fw_outstanding) > sc->io_cmds_highwater)
1241 			sc->io_cmds_highwater++;
1242 	}
1243 
1244 	return;
1245 }
1246 
1247 static void
mpi3mr_cam_poll(struct cam_sim * sim)1248 mpi3mr_cam_poll(struct cam_sim *sim)
1249 {
1250 	struct mpi3mr_cam_softc *cam_sc;
1251 	struct mpi3mr_irq_context *irq_ctx;
1252 	struct mpi3mr_softc *sc;
1253 	int i;
1254 
1255 	cam_sc = cam_sim_softc(sim);
1256 	sc = cam_sc->sc;
1257 
1258 	mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "func: %s line: %d is called\n",
1259 		__func__, __LINE__);
1260 
1261 	for (i = 0; i < sc->num_queues; i++) {
1262 		irq_ctx = sc->irq_ctx + i;
1263 		if (irq_ctx->op_reply_q->qid) {
1264 			mpi3mr_complete_io_cmd(sc, irq_ctx);
1265 		}
1266 	}
1267 }
1268 
1269 static void
mpi3mr_cam_action(struct cam_sim * sim,union ccb * ccb)1270 mpi3mr_cam_action(struct cam_sim *sim, union ccb *ccb)
1271 {
1272 	struct mpi3mr_cam_softc *cam_sc;
1273 	struct mpi3mr_target *targ;
1274 
1275 	cam_sc = cam_sim_softc(sim);
1276 
1277 	mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "ccb func_code 0x%x target id: 0x%x\n",
1278 	    ccb->ccb_h.func_code, ccb->ccb_h.target_id);
1279 
1280 	mtx_assert(&cam_sc->sc->mpi3mr_mtx, MA_OWNED);
1281 
1282 	switch (ccb->ccb_h.func_code) {
1283 	case XPT_PATH_INQ:
1284 	{
1285 		struct ccb_pathinq *cpi = &ccb->cpi;
1286 
1287 		cpi->version_num = 1;
1288 		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
1289 		cpi->target_sprt = 0;
1290 		cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN;
1291 		cpi->hba_eng_cnt = 0;
1292 		cpi->max_target = cam_sc->maxtargets - 1;
1293 		cpi->max_lun = 0;
1294 
1295 		/*
1296 		 * initiator_id is set here to an ID outside the set of valid
1297 		 * target IDs (including volumes).
1298 		 */
1299 		cpi->initiator_id = cam_sc->maxtargets;
1300 		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1301 		strlcpy(cpi->hba_vid, "Broadcom", HBA_IDLEN);
1302 		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1303 		cpi->unit_number = cam_sim_unit(sim);
1304 		cpi->bus_id = cam_sim_bus(sim);
1305 		/*
1306 		 * XXXSLM-I think this needs to change based on config page or
1307 		 * something instead of hardcoded to 150000.
1308 		 */
1309 		cpi->base_transfer_speed = 150000;
1310 		cpi->transport = XPORT_SAS;
1311 		cpi->transport_version = 0;
1312 		cpi->protocol = PROTO_SCSI;
1313 		cpi->protocol_version = SCSI_REV_SPC;
1314 
1315 		targ = mpi3mr_find_target_by_per_id(cam_sc, ccb->ccb_h.target_id);
1316 
1317 		if (targ && (targ->dev_type == MPI3_DEVICE_DEVFORM_PCIE) &&
1318 		    ((targ->dev_spec.pcie_inf.dev_info &
1319 		    MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) ==
1320 		    MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE)) {
1321 			cpi->maxio = targ->dev_spec.pcie_inf.mdts;
1322 			mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO,
1323 				"PCI device target_id: %u max io size: %u\n",
1324 				ccb->ccb_h.target_id, cpi->maxio);
1325 		} else {
1326 			cpi->maxio = PAGE_SIZE * (MPI3MR_SG_DEPTH - 1);
1327 		}
1328 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
1329 		break;
1330 	}
1331 	case XPT_GET_TRAN_SETTINGS:
1332 	{
1333 		struct ccb_trans_settings	*cts;
1334 		struct ccb_trans_settings_sas	*sas;
1335 		struct ccb_trans_settings_scsi	*scsi;
1336 
1337 		cts = &ccb->cts;
1338 		sas = &cts->xport_specific.sas;
1339 		scsi = &cts->proto_specific.scsi;
1340 
1341 		KASSERT(cts->ccb_h.target_id < cam_sc->maxtargets,
1342 		    ("Target %d out of bounds in XPT_GET_TRAN_SETTINGS\n",
1343 		    cts->ccb_h.target_id));
1344 		targ = mpi3mr_find_target_by_per_id(cam_sc, cts->ccb_h.target_id);
1345 
1346 		if (targ == NULL) {
1347 			mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "Device with target ID: 0x%x does not exist\n",
1348 			cts->ccb_h.target_id);
1349 			mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
1350 			break;
1351 		}
1352 
1353 		if ((targ->dev_handle == 0x0) || (targ->dev_removed == 1))  {
1354 			mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
1355 			break;
1356 		}
1357 
1358 		cts->protocol_version = SCSI_REV_SPC2;
1359 		cts->transport = XPORT_SAS;
1360 		cts->transport_version = 0;
1361 
1362 		sas->valid = CTS_SAS_VALID_SPEED;
1363 
1364 		switch (targ->link_rate) {
1365 		case 0x08:
1366 			sas->bitrate = 150000;
1367 			break;
1368 		case 0x09:
1369 			sas->bitrate = 300000;
1370 			break;
1371 		case 0x0a:
1372 			sas->bitrate = 600000;
1373 			break;
1374 		case 0x0b:
1375 			sas->bitrate = 1200000;
1376 			break;
1377 		default:
1378 			sas->valid = 0;
1379 		}
1380 
1381 		cts->protocol = PROTO_SCSI;
1382 		scsi->valid = CTS_SCSI_VALID_TQ;
1383 		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
1384 
1385 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
1386 		break;
1387 	}
1388 	case XPT_CALC_GEOMETRY:
1389 		cam_calc_geometry(&ccb->ccg, /*extended*/1);
1390 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
1391 		break;
1392 	case XPT_RESET_DEV:
1393 		mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "mpi3mr_action "
1394 		    "XPT_RESET_DEV\n");
1395 		return;
1396 	case XPT_RESET_BUS:
1397 	case XPT_ABORT:
1398 	case XPT_TERM_IO:
1399 		mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "mpi3mr_action faking success "
1400 		    "for abort or reset\n");
1401 		mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
1402 		break;
1403 	case XPT_SCSI_IO:
1404 		mpi3mr_action_scsiio(cam_sc, ccb);
1405 		return;
1406 	default:
1407 		mpi3mr_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL);
1408 		break;
1409 	}
1410 	xpt_done(ccb);
1411 }
1412 
1413 void
mpi3mr_startup_increment(struct mpi3mr_cam_softc * cam_sc)1414 mpi3mr_startup_increment(struct mpi3mr_cam_softc *cam_sc)
1415 {
1416 	if ((cam_sc->flags & MPI3MRSAS_IN_STARTUP) != 0) {
1417 		if (cam_sc->startup_refcount++ == 0) {
1418 			/* just starting, freeze the simq */
1419 			mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO,
1420 			    "%s freezing simq\n", __func__);
1421 			xpt_hold_boot();
1422 		}
1423 		mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "%s refcount %u\n", __func__,
1424 		    cam_sc->startup_refcount);
1425 	}
1426 }
1427 
1428 void
mpi3mr_release_simq_reinit(struct mpi3mr_cam_softc * cam_sc)1429 mpi3mr_release_simq_reinit(struct mpi3mr_cam_softc *cam_sc)
1430 {
1431 	if (cam_sc->flags & MPI3MRSAS_QUEUE_FROZEN) {
1432 		cam_sc->flags &= ~MPI3MRSAS_QUEUE_FROZEN;
1433 		xpt_release_simq(cam_sc->sim, 1);
1434 		mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "Unfreezing SIM queue\n");
1435 	}
1436 }
1437 
1438 void
mpi3mr_rescan_target(struct mpi3mr_softc * sc,struct mpi3mr_target * targ)1439 mpi3mr_rescan_target(struct mpi3mr_softc *sc, struct mpi3mr_target *targ)
1440 {
1441 	struct mpi3mr_cam_softc *cam_sc = sc->cam_sc;
1442 	path_id_t pathid;
1443 	target_id_t targetid;
1444 	union ccb *ccb;
1445 
1446 	pathid = cam_sim_path(cam_sc->sim);
1447 	if (targ == NULL)
1448 		targetid = CAM_TARGET_WILDCARD;
1449 	else
1450 		targetid = targ->per_id;
1451 
1452 	/*
1453 	 * Allocate a CCB and schedule a rescan.
1454 	 */
1455 	ccb = xpt_alloc_ccb_nowait();
1456 	if (ccb == NULL) {
1457 		mpi3mr_dprint(sc, MPI3MR_ERROR, "unable to alloc CCB for rescan\n");
1458 		return;
1459 	}
1460 
1461 	if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid,
1462 	    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1463 		mpi3mr_dprint(sc, MPI3MR_ERROR, "unable to create path for rescan\n");
1464 		xpt_free_ccb(ccb);
1465 		return;
1466 	}
1467 
1468 	if (targetid == CAM_TARGET_WILDCARD)
1469 		ccb->ccb_h.func_code = XPT_SCAN_BUS;
1470 	else
1471 		ccb->ccb_h.func_code = XPT_SCAN_TGT;
1472 
1473 	mpi3mr_dprint(sc, MPI3MR_EVENT, "%s target id 0x%x\n", __func__, targetid);
1474 	xpt_rescan(ccb);
1475 }
1476 
1477 void
mpi3mr_startup_decrement(struct mpi3mr_cam_softc * cam_sc)1478 mpi3mr_startup_decrement(struct mpi3mr_cam_softc *cam_sc)
1479 {
1480 	if ((cam_sc->flags & MPI3MRSAS_IN_STARTUP) != 0) {
1481 		if (--cam_sc->startup_refcount == 0) {
1482 			/* finished all discovery-related actions, release
1483 			 * the simq and rescan for the latest topology.
1484 			 */
1485 			mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO,
1486 			    "%s releasing simq\n", __func__);
1487 			cam_sc->flags &= ~MPI3MRSAS_IN_STARTUP;
1488 			xpt_release_simq(cam_sc->sim, 1);
1489 			xpt_release_boot();
1490 		}
1491 		mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "%s refcount %u\n", __func__,
1492 		    cam_sc->startup_refcount);
1493 	}
1494 }
1495 
1496 static void
mpi3mr_fw_event_free(struct mpi3mr_softc * sc,struct mpi3mr_fw_event_work * fw_event)1497 mpi3mr_fw_event_free(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fw_event)
1498 {
1499 	if (!fw_event)
1500 		return;
1501 
1502 	if (fw_event->event_data != NULL) {
1503 		free(fw_event->event_data, M_MPI3MR);
1504 		fw_event->event_data = NULL;
1505 	}
1506 
1507 	free(fw_event, M_MPI3MR);
1508 	fw_event = NULL;
1509 }
1510 
1511 static void
mpi3mr_freeup_events(struct mpi3mr_softc * sc)1512 mpi3mr_freeup_events(struct mpi3mr_softc *sc)
1513 {
1514 	struct mpi3mr_fw_event_work *fw_event = NULL;
1515 	mtx_lock(&sc->mpi3mr_mtx);
1516 	while ((fw_event = TAILQ_FIRST(&sc->cam_sc->ev_queue)) != NULL) {
1517 		TAILQ_REMOVE(&sc->cam_sc->ev_queue, fw_event, ev_link);
1518 		mpi3mr_fw_event_free(sc, fw_event);
1519 	}
1520 	mtx_unlock(&sc->mpi3mr_mtx);
1521 }
1522 
1523 static void
mpi3mr_sastopochg_evt_debug(struct mpi3mr_softc * sc,Mpi3EventDataSasTopologyChangeList_t * event_data)1524 mpi3mr_sastopochg_evt_debug(struct mpi3mr_softc *sc,
1525 	Mpi3EventDataSasTopologyChangeList_t *event_data)
1526 {
1527 	int i;
1528 	U16 handle;
1529 	U8 reason_code, phy_number;
1530 	char *status_str = NULL;
1531 	U8 link_rate, prev_link_rate;
1532 
1533 	switch (event_data->ExpStatus) {
1534 	case MPI3_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
1535 		status_str = "remove";
1536 		break;
1537 	case MPI3_EVENT_SAS_TOPO_ES_RESPONDING:
1538 		status_str =  "responding";
1539 		break;
1540 	case MPI3_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
1541 		status_str = "remove delay";
1542 		break;
1543 	case MPI3_EVENT_SAS_TOPO_ES_NO_EXPANDER:
1544 		status_str = "direct attached";
1545 		break;
1546 	default:
1547 		status_str = "unknown status";
1548 		break;
1549 	}
1550 
1551 	mpi3mr_dprint(sc, MPI3MR_INFO, "%s :sas topology change: (%s)\n",
1552 	    __func__, status_str);
1553 	mpi3mr_dprint(sc, MPI3MR_INFO,
1554 		"%s :\texpander_handle(0x%04x), enclosure_handle(0x%04x) "
1555 	    "start_phy(%02d), num_entries(%d)\n", __func__,
1556 	    (event_data->ExpanderDevHandle),
1557 	    (event_data->EnclosureHandle),
1558 	    event_data->StartPhyNum, event_data->NumEntries);
1559 	for (i = 0; i < event_data->NumEntries; i++) {
1560 		handle = (event_data->PhyEntry[i].AttachedDevHandle);
1561 		if (!handle)
1562 			continue;
1563 		phy_number = event_data->StartPhyNum + i;
1564 		reason_code = event_data->PhyEntry[i].Status &
1565 		    MPI3_EVENT_SAS_TOPO_PHY_RC_MASK;
1566 		switch (reason_code) {
1567 		case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING:
1568 			status_str = "target remove";
1569 			break;
1570 		case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING:
1571 			status_str = "delay target remove";
1572 			break;
1573 		case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED:
1574 			status_str = "link rate change";
1575 			break;
1576 		case MPI3_EVENT_SAS_TOPO_PHY_RC_NO_CHANGE:
1577 			status_str = "target responding";
1578 			break;
1579 		default:
1580 			status_str = "unknown";
1581 			break;
1582 		}
1583 		link_rate = event_data->PhyEntry[i].LinkRate >> 4;
1584 		prev_link_rate = event_data->PhyEntry[i].LinkRate & 0xF;
1585 		mpi3mr_dprint(sc, MPI3MR_INFO, "%s :\tphy(%02d), attached_handle(0x%04x): %s:"
1586 		    " link rate: new(0x%02x), old(0x%02x)\n", __func__,
1587 		    phy_number, handle, status_str, link_rate, prev_link_rate);
1588 	}
1589 }
1590 
1591 static void
mpi3mr_process_sastopochg_evt(struct mpi3mr_softc * sc,struct mpi3mr_fw_event_work * fwevt)1592 mpi3mr_process_sastopochg_evt(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fwevt)
1593 {
1594 
1595 	Mpi3EventDataSasTopologyChangeList_t *event_data =
1596 		    (Mpi3EventDataSasTopologyChangeList_t *)fwevt->event_data;
1597 	int i;
1598 	U16 handle;
1599 	U8 reason_code, link_rate;
1600 	struct mpi3mr_target *target = NULL;
1601 
1602 
1603 	mpi3mr_sastopochg_evt_debug(sc, event_data);
1604 
1605 	for (i = 0; i < event_data->NumEntries; i++) {
1606 		handle = le16toh(event_data->PhyEntry[i].AttachedDevHandle);
1607 		link_rate = event_data->PhyEntry[i].LinkRate >> 4;
1608 
1609 		if (!handle)
1610 			continue;
1611 		target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle);
1612 
1613 		if (!target)
1614 			continue;
1615 
1616 		target->link_rate = link_rate;
1617 		reason_code = event_data->PhyEntry[i].Status &
1618 			MPI3_EVENT_SAS_TOPO_PHY_RC_MASK;
1619 
1620 		switch (reason_code) {
1621 		case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING:
1622 			if (target->exposed_to_os)
1623 				mpi3mr_remove_device_from_os(sc, target->dev_handle);
1624 			mpi3mr_remove_device_from_list(sc, target, false);
1625 			break;
1626 		case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED:
1627 			break;
1628 		default:
1629 			break;
1630 		}
1631 	}
1632 
1633 	/*
1634 	 * refcount was incremented for this event in
1635 	 * mpi3mr_evt_handler. Decrement it here because the event has
1636 	 * been processed.
1637 	 */
1638 	mpi3mr_startup_decrement(sc->cam_sc);
1639 	return;
1640 }
1641 
1642 static inline void
mpi3mr_logdata_evt_bh(struct mpi3mr_softc * sc,struct mpi3mr_fw_event_work * fwevt)1643 mpi3mr_logdata_evt_bh(struct mpi3mr_softc *sc,
1644 		      struct mpi3mr_fw_event_work *fwevt)
1645 {
1646 	mpi3mr_app_save_logdata(sc, fwevt->event_data,
1647 				fwevt->event_data_size);
1648 }
1649 
1650 static void
mpi3mr_pcietopochg_evt_debug(struct mpi3mr_softc * sc,Mpi3EventDataPcieTopologyChangeList_t * event_data)1651 mpi3mr_pcietopochg_evt_debug(struct mpi3mr_softc *sc,
1652 	Mpi3EventDataPcieTopologyChangeList_t *event_data)
1653 {
1654 	int i;
1655 	U16 handle;
1656 	U16 reason_code;
1657 	U8 port_number;
1658 	char *status_str = NULL;
1659 	U8 link_rate, prev_link_rate;
1660 
1661 	switch (event_data->SwitchStatus) {
1662 	case MPI3_EVENT_PCIE_TOPO_SS_NOT_RESPONDING:
1663 		status_str = "remove";
1664 		break;
1665 	case MPI3_EVENT_PCIE_TOPO_SS_RESPONDING:
1666 		status_str =  "responding";
1667 		break;
1668 	case MPI3_EVENT_PCIE_TOPO_SS_DELAY_NOT_RESPONDING:
1669 		status_str = "remove delay";
1670 		break;
1671 	case MPI3_EVENT_PCIE_TOPO_SS_NO_PCIE_SWITCH:
1672 		status_str = "direct attached";
1673 		break;
1674 	default:
1675 		status_str = "unknown status";
1676 		break;
1677 	}
1678 	mpi3mr_dprint(sc, MPI3MR_INFO, "%s :pcie topology change: (%s)\n",
1679 		__func__, status_str);
1680 	mpi3mr_dprint(sc, MPI3MR_INFO,
1681 		"%s :\tswitch_handle(0x%04x), enclosure_handle(0x%04x)"
1682 		"start_port(%02d), num_entries(%d)\n", __func__,
1683 		le16toh(event_data->SwitchDevHandle),
1684 		le16toh(event_data->EnclosureHandle),
1685 		event_data->StartPortNum, event_data->NumEntries);
1686 	for (i = 0; i < event_data->NumEntries; i++) {
1687 		handle =
1688 			le16toh(event_data->PortEntry[i].AttachedDevHandle);
1689 		if (!handle)
1690 			continue;
1691 		port_number = event_data->StartPortNum + i;
1692 		reason_code = event_data->PortEntry[i].PortStatus;
1693 		switch (reason_code) {
1694 		case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING:
1695 			status_str = "target remove";
1696 			break;
1697 		case MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING:
1698 			status_str = "delay target remove";
1699 			break;
1700 		case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED:
1701 			status_str = "link rate change";
1702 			break;
1703 		case MPI3_EVENT_PCIE_TOPO_PS_NO_CHANGE:
1704 			status_str = "target responding";
1705 			break;
1706 		default:
1707 			status_str = "unknown";
1708 			break;
1709 		}
1710 		link_rate = event_data->PortEntry[i].CurrentPortInfo &
1711 			MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK;
1712 		prev_link_rate = event_data->PortEntry[i].PreviousPortInfo &
1713 			MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK;
1714 		mpi3mr_dprint(sc, MPI3MR_INFO, "%s :\tport(%02d), attached_handle(0x%04x): %s:"
1715 		    " link rate: new(0x%02x), old(0x%02x)\n", __func__,
1716 		    port_number, handle, status_str, link_rate, prev_link_rate);
1717 	}
1718 }
1719 
mpi3mr_process_pcietopochg_evt(struct mpi3mr_softc * sc,struct mpi3mr_fw_event_work * fwevt)1720 static void mpi3mr_process_pcietopochg_evt(struct mpi3mr_softc *sc,
1721     struct mpi3mr_fw_event_work *fwevt)
1722 {
1723 	Mpi3EventDataPcieTopologyChangeList_t *event_data =
1724 		    (Mpi3EventDataPcieTopologyChangeList_t *)fwevt->event_data;
1725 	int i;
1726 	U16 handle;
1727 	U8 reason_code, link_rate;
1728 	struct mpi3mr_target *target = NULL;
1729 
1730 
1731 	mpi3mr_pcietopochg_evt_debug(sc, event_data);
1732 
1733 	for (i = 0; i < event_data->NumEntries; i++) {
1734 		handle =
1735 			le16toh(event_data->PortEntry[i].AttachedDevHandle);
1736 		if (!handle)
1737 			continue;
1738 		target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle);
1739 		if (!target)
1740 			continue;
1741 
1742 		link_rate = event_data->PortEntry[i].CurrentPortInfo &
1743 			MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK;
1744 		target->link_rate = link_rate;
1745 
1746 		reason_code = event_data->PortEntry[i].PortStatus;
1747 
1748 		switch (reason_code) {
1749 		case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING:
1750 			if (target->exposed_to_os)
1751 				mpi3mr_remove_device_from_os(sc, target->dev_handle);
1752 			mpi3mr_remove_device_from_list(sc, target, false);
1753 			break;
1754 		case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED:
1755 			break;
1756 		default:
1757 			break;
1758 		}
1759 	}
1760 
1761 	/*
1762 	 * refcount was incremented for this event in
1763 	 * mpi3mr_evt_handler. Decrement it here because the event has
1764 	 * been processed.
1765 	 */
1766 	mpi3mr_startup_decrement(sc->cam_sc);
1767 	return;
1768 }
1769 
mpi3mr_add_device(struct mpi3mr_softc * sc,U16 per_id)1770 void mpi3mr_add_device(struct mpi3mr_softc *sc, U16 per_id)
1771 {
1772 	struct mpi3mr_target *target;
1773 
1774 	mpi3mr_dprint(sc, MPI3MR_EVENT,
1775 		"Adding device(persistent id: 0x%x)\n", per_id);
1776 
1777 	mpi3mr_startup_increment(sc->cam_sc);
1778 	target = mpi3mr_find_target_by_per_id(sc->cam_sc, per_id);
1779 
1780 	if (!target) {
1781 		mpi3mr_dprint(sc, MPI3MR_INFO, "Not available in driver's"
1782 		    "internal target list, persistent_id: %d\n",
1783 		    per_id);
1784 		goto out;
1785 	}
1786 
1787 	if (target->is_hidden) {
1788 		mpi3mr_dprint(sc, MPI3MR_EVENT, "Target is hidden, persistent_id: %d\n",
1789 			per_id);
1790 		goto out;
1791 	}
1792 
1793 	if (!target->exposed_to_os && !sc->reset_in_progress) {
1794 		mpi3mr_rescan_target(sc, target);
1795 		mpi3mr_dprint(sc, MPI3MR_INFO,
1796 			"Added device persistent_id: %d dev_handle: %d\n", per_id, target->dev_handle);
1797 		target->exposed_to_os = 1;
1798 	}
1799 
1800 out:
1801 	mpi3mr_startup_decrement(sc->cam_sc);
1802 }
1803 
mpi3mr_remove_device_from_os(struct mpi3mr_softc * sc,U16 handle)1804 int mpi3mr_remove_device_from_os(struct mpi3mr_softc *sc, U16 handle)
1805 {
1806 	U32 i = 0;
1807 	int retval = 0;
1808 	struct mpi3mr_target *target;
1809 
1810 	mpi3mr_dprint(sc, MPI3MR_EVENT,
1811 		"Removing Device (dev_handle: %d)\n", handle);
1812 
1813 	target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle);
1814 
1815 	if (!target) {
1816 		mpi3mr_dprint(sc, MPI3MR_INFO,
1817 			"Device (persistent_id: %d dev_handle: %d) is already removed from driver's list\n",
1818 			target->per_id, handle);
1819 		mpi3mr_rescan_target(sc, NULL);
1820 		retval = -1;
1821 		goto out;
1822 	}
1823 
1824 	target->flags |= MPI3MRSAS_TARGET_INREMOVAL;
1825 
1826 	while (mpi3mr_atomic_read(&target->outstanding) && (i < 30)) {
1827 		i++;
1828 		if (!(i % 2)) {
1829 			mpi3mr_dprint(sc, MPI3MR_INFO,
1830 			    "[%2d]waiting for "
1831 			    "waiting for outstanding commands to complete on target: %d\n",
1832 			    i, target->per_id);
1833 		}
1834 		DELAY(1000 * 1000);
1835 	}
1836 
1837 	if (target->exposed_to_os && !sc->reset_in_progress) {
1838 		mpi3mr_rescan_target(sc, target);
1839 		mpi3mr_dprint(sc, MPI3MR_INFO,
1840 			"Removed device(persistent_id: %d dev_handle: %d)\n", target->per_id, handle);
1841 		target->exposed_to_os = 0;
1842 	}
1843 
1844 	target->flags &= ~MPI3MRSAS_TARGET_INREMOVAL;
1845 out:
1846 	return retval;
1847 }
1848 
mpi3mr_remove_device_from_list(struct mpi3mr_softc * sc,struct mpi3mr_target * target,bool must_delete)1849 void mpi3mr_remove_device_from_list(struct mpi3mr_softc *sc,
1850 	struct mpi3mr_target *target, bool must_delete)
1851 {
1852 	mtx_lock_spin(&sc->target_lock);
1853 	if ((target->state == MPI3MR_DEV_REMOVE_HS_STARTED) ||
1854 	    (must_delete == true)) {
1855 		TAILQ_REMOVE(&sc->cam_sc->tgt_list, target, tgt_next);
1856 		target->state = MPI3MR_DEV_DELETED;
1857 	}
1858 	mtx_unlock_spin(&sc->target_lock);
1859 
1860 	if (target->state == MPI3MR_DEV_DELETED) {
1861  		free(target, M_MPI3MR);
1862  		target = NULL;
1863  	}
1864 
1865 	return;
1866 }
1867 
1868 /**
1869  * mpi3mr_devstatuschg_evt_bh - DevStatusChange evt bottomhalf
1870  * @sc: Adapter instance reference
1871  * @fwevt: Firmware event
1872  *
1873  * Process Device Status Change event and based on device's new
1874  * information, either expose the device to the upper layers, or
1875  * remove the device from upper layers.
1876  *
1877  * Return: Nothing.
1878  */
mpi3mr_devstatuschg_evt_bh(struct mpi3mr_softc * sc,struct mpi3mr_fw_event_work * fwevt)1879 static void mpi3mr_devstatuschg_evt_bh(struct mpi3mr_softc *sc,
1880 	struct mpi3mr_fw_event_work *fwevt)
1881 {
1882 	U16 dev_handle = 0;
1883 	U8 uhide = 0, delete = 0, cleanup = 0;
1884 	struct mpi3mr_target *tgtdev = NULL;
1885 	Mpi3EventDataDeviceStatusChange_t *evtdata =
1886 	    (Mpi3EventDataDeviceStatusChange_t *)fwevt->event_data;
1887 
1888 
1889 
1890 	dev_handle = le16toh(evtdata->DevHandle);
1891 	mpi3mr_dprint(sc, MPI3MR_INFO,
1892 	    "%s :device status change: handle(0x%04x): reason code(0x%x)\n",
1893 	    __func__, dev_handle, evtdata->ReasonCode);
1894 	switch (evtdata->ReasonCode) {
1895 	case MPI3_EVENT_DEV_STAT_RC_HIDDEN:
1896 		delete = 1;
1897 		break;
1898 	case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN:
1899 		uhide = 1;
1900 		break;
1901 	case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING:
1902 		delete = 1;
1903 		cleanup = 1;
1904 		break;
1905 	default:
1906 		mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Unhandled reason code(0x%x)\n", __func__,
1907 		    evtdata->ReasonCode);
1908 		break;
1909 	}
1910 
1911 	tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle);
1912 	if (!tgtdev)
1913 		return;
1914 
1915 	if (uhide) {
1916 		if (!tgtdev->exposed_to_os)
1917 			mpi3mr_add_device(sc, tgtdev->per_id);
1918 	}
1919 
1920 	if (delete)
1921 		mpi3mr_remove_device_from_os(sc, dev_handle);
1922 
1923 	if (cleanup)
1924 		mpi3mr_remove_device_from_list(sc, tgtdev, false);
1925 }
1926 
1927 /**
1928  * mpi3mr_devinfochg_evt_bh - DeviceInfoChange evt bottomhalf
1929  * @sc: Adapter instance reference
1930  * @dev_pg0: New device page0
1931  *
1932  * Process Device Info Change event and based on device's new
1933  * information, either expose the device to the upper layers, or
1934  * remove the device from upper layers or update the details of
1935  * the device.
1936  *
1937  * Return: Nothing.
1938  */
mpi3mr_devinfochg_evt_bh(struct mpi3mr_softc * sc,Mpi3DevicePage0_t * dev_pg0)1939 static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_softc *sc,
1940 	Mpi3DevicePage0_t *dev_pg0)
1941 {
1942 	struct mpi3mr_target *tgtdev = NULL;
1943 	U16 dev_handle = 0, perst_id = 0;
1944 
1945 	perst_id = le16toh(dev_pg0->PersistentID);
1946 	dev_handle = le16toh(dev_pg0->DevHandle);
1947 	mpi3mr_dprint(sc, MPI3MR_INFO,
1948 	    "%s :Device info change: handle(0x%04x): persist_id(0x%x)\n",
1949 	    __func__, dev_handle, perst_id);
1950 	tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle);
1951 	if (!tgtdev)
1952 		return;
1953 
1954 	mpi3mr_update_device(sc, tgtdev, dev_pg0, false);
1955 	if (!tgtdev->is_hidden && !tgtdev->exposed_to_os)
1956 		mpi3mr_add_device(sc, perst_id);
1957 
1958 	if (tgtdev->is_hidden && tgtdev->exposed_to_os)
1959 		mpi3mr_remove_device_from_os(sc, tgtdev->dev_handle);
1960 }
1961 
1962 static void
mpi3mr_fw_work(struct mpi3mr_softc * sc,struct mpi3mr_fw_event_work * fw_event)1963 mpi3mr_fw_work(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fw_event)
1964 {
1965 	if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN)
1966 		goto out;
1967 
1968 	if (!fw_event->process_event)
1969 		goto evt_ack;
1970 
1971 	mpi3mr_dprint(sc, MPI3MR_EVENT, "(%d)->(%s) Working on  Event: [%x]\n",
1972 	    event_count++, __func__, fw_event->event);
1973 
1974 	switch (fw_event->event) {
1975 	case MPI3_EVENT_DEVICE_ADDED:
1976 	{
1977 		Mpi3DevicePage0_t *dev_pg0 =
1978 			(Mpi3DevicePage0_t *) fw_event->event_data;
1979 		mpi3mr_add_device(sc, dev_pg0->PersistentID);
1980 		break;
1981 	}
1982 	case MPI3_EVENT_DEVICE_INFO_CHANGED:
1983 	{
1984 		mpi3mr_devinfochg_evt_bh(sc,
1985 		    (Mpi3DevicePage0_t *) fw_event->event_data);
1986 		break;
1987 	}
1988 	case MPI3_EVENT_DEVICE_STATUS_CHANGE:
1989 	{
1990 		mpi3mr_devstatuschg_evt_bh(sc, fw_event);
1991 		break;
1992 	}
1993 	case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
1994 	{
1995 		mpi3mr_process_sastopochg_evt(sc, fw_event);
1996 		break;
1997 	}
1998 	case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
1999 	{
2000 		mpi3mr_process_pcietopochg_evt(sc, fw_event);
2001 		break;
2002 	}
2003 	case MPI3_EVENT_LOG_DATA:
2004 	{
2005 		mpi3mr_logdata_evt_bh(sc, fw_event);
2006 		break;
2007 	}
2008 	default:
2009 		mpi3mr_dprint(sc, MPI3MR_TRACE,"Unhandled event 0x%0X\n",
2010 		    fw_event->event);
2011 		break;
2012 
2013 	}
2014 
2015 evt_ack:
2016 	if (fw_event->send_ack) {
2017 		mpi3mr_dprint(sc, MPI3MR_EVENT,"Process event ACK for event 0x%0X\n",
2018 		    fw_event->event);
2019 		mpi3mr_process_event_ack(sc, fw_event->event,
2020 		    fw_event->event_context);
2021 	}
2022 
2023 out:
2024 	mpi3mr_dprint(sc, MPI3MR_EVENT, "(%d)->(%s) Event Free: [%x]\n", event_count,
2025 	    __func__, fw_event->event);
2026 
2027 	mpi3mr_fw_event_free(sc, fw_event);
2028 }
2029 
2030 void
mpi3mr_firmware_event_work(void * arg,int pending)2031 mpi3mr_firmware_event_work(void *arg, int pending)
2032 {
2033 	struct mpi3mr_fw_event_work *fw_event;
2034 	struct mpi3mr_softc *sc;
2035 
2036 	sc = (struct mpi3mr_softc *)arg;
2037 
2038 	mtx_lock(&sc->fwevt_lock);
2039 	while ((fw_event = TAILQ_FIRST(&sc->cam_sc->ev_queue)) != NULL) {
2040 		TAILQ_REMOVE(&sc->cam_sc->ev_queue, fw_event, ev_link);
2041 		mtx_unlock(&sc->fwevt_lock);
2042 		mpi3mr_fw_work(sc, fw_event);
2043 		mtx_lock(&sc->fwevt_lock);
2044 	}
2045 	mtx_unlock(&sc->fwevt_lock);
2046 }
2047 
2048 
2049 /*
2050  * mpi3mr_cam_attach - CAM layer registration
2051  * @sc: Adapter reference
2052  *
2053  * This function does simq allocation, cam registration, xpt_bus registration,
2054  * event taskqueue initialization and async event handler registration.
2055  *
2056  * Return: 0 on success and proper error codes on failure
2057  */
2058 int
mpi3mr_cam_attach(struct mpi3mr_softc * sc)2059 mpi3mr_cam_attach(struct mpi3mr_softc *sc)
2060 {
2061 	struct mpi3mr_cam_softc *cam_sc;
2062 	cam_status status;
2063 	int unit, error = 0, reqs;
2064 
2065 	mpi3mr_dprint(sc, MPI3MR_XINFO, "Starting CAM Attach\n");
2066 
2067 	cam_sc = malloc(sizeof(struct mpi3mr_cam_softc), M_MPI3MR, M_WAITOK|M_ZERO);
2068 	cam_sc->maxtargets = sc->facts.max_perids + 1;
2069 
2070 	TAILQ_INIT(&cam_sc->tgt_list);
2071 
2072 	sc->cam_sc = cam_sc;
2073 	cam_sc->sc = sc;
2074 
2075 	reqs = sc->max_host_ios;
2076 
2077 	if ((cam_sc->devq = cam_simq_alloc(reqs)) == NULL) {
2078 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate SIMQ\n");
2079 		error = ENOMEM;
2080 		goto out;
2081 	}
2082 
2083 	unit = device_get_unit(sc->mpi3mr_dev);
2084 	cam_sc->sim = cam_sim_alloc(mpi3mr_cam_action, mpi3mr_cam_poll, "mpi3mr", cam_sc,
2085 	    unit, &sc->mpi3mr_mtx, reqs, reqs, cam_sc->devq);
2086 	if (cam_sc->sim == NULL) {
2087 		mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate SIM\n");
2088 		error = EINVAL;
2089 		goto out;
2090 	}
2091 
2092 	TAILQ_INIT(&cam_sc->ev_queue);
2093 
2094 	/* Initialize taskqueue for Event Handling */
2095 	TASK_INIT(&cam_sc->ev_task, 0, mpi3mr_firmware_event_work, sc);
2096 	cam_sc->ev_tq = taskqueue_create("mpi3mr_taskq", M_NOWAIT | M_ZERO,
2097 	    taskqueue_thread_enqueue, &cam_sc->ev_tq);
2098 	taskqueue_start_threads(&cam_sc->ev_tq, 1, PRIBIO, "%s taskq",
2099 	    device_get_nameunit(sc->mpi3mr_dev));
2100 
2101 	mtx_lock(&sc->mpi3mr_mtx);
2102 
2103 	/*
2104 	 * XXX There should be a bus for every port on the adapter, but since
2105 	 * we're just going to fake the topology for now, we'll pretend that
2106 	 * everything is just a target on a single bus.
2107 	 */
2108 	if ((error = xpt_bus_register(cam_sc->sim, sc->mpi3mr_dev, 0)) != 0) {
2109 		mpi3mr_dprint(sc, MPI3MR_ERROR,
2110 		    "Error 0x%x registering SCSI bus\n", error);
2111 		mtx_unlock(&sc->mpi3mr_mtx);
2112 		goto out;
2113 	}
2114 
2115 	/*
2116 	 * Assume that discovery events will start right away.
2117 	 *
2118 	 * Hold off boot until discovery is complete.
2119 	 */
2120 	cam_sc->flags |= MPI3MRSAS_IN_STARTUP | MPI3MRSAS_IN_DISCOVERY;
2121 	sc->cam_sc->startup_refcount = 0;
2122 	mpi3mr_startup_increment(cam_sc);
2123 
2124 	callout_init(&cam_sc->discovery_callout, 1 /*mpsafe*/);
2125 
2126 	/*
2127 	 * Register for async events so we can determine the EEDP
2128 	 * capabilities of devices.
2129 	 */
2130 	status = xpt_create_path(&cam_sc->path, /*periph*/NULL,
2131 	    cam_sim_path(sc->cam_sc->sim), CAM_TARGET_WILDCARD,
2132 	    CAM_LUN_WILDCARD);
2133 	if (status != CAM_REQ_CMP) {
2134 		mpi3mr_dprint(sc, MPI3MR_ERROR,
2135 		    "Error 0x%x creating sim path\n", status);
2136 		cam_sc->path = NULL;
2137 	}
2138 
2139 	if (status != CAM_REQ_CMP) {
2140 		/*
2141 		 * EEDP use is the exception, not the rule.
2142 		 * Warn the user, but do not fail to attach.
2143 		 */
2144 		mpi3mr_dprint(sc, MPI3MR_INFO, "EEDP capabilities disabled.\n");
2145 	}
2146 
2147 	mtx_unlock(&sc->mpi3mr_mtx);
2148 
2149 	error = mpi3mr_register_events(sc);
2150 
2151 out:
2152 	mpi3mr_dprint(sc, MPI3MR_XINFO, "%s Exiting CAM attach, error: 0x%x n", __func__, error);
2153 	return (error);
2154 }
2155 
2156 int
mpi3mr_cam_detach(struct mpi3mr_softc * sc)2157 mpi3mr_cam_detach(struct mpi3mr_softc *sc)
2158 {
2159 	struct mpi3mr_cam_softc *cam_sc;
2160 	struct mpi3mr_target *target;
2161 
2162 	mpi3mr_dprint(sc, MPI3MR_XINFO, "%s, Starting CAM detach\n", __func__);
2163 	if (sc->cam_sc == NULL)
2164 		return (0);
2165 
2166 	cam_sc = sc->cam_sc;
2167 
2168 	mpi3mr_freeup_events(sc);
2169 
2170 	/*
2171 	 * Drain and free the event handling taskqueue with the lock
2172 	 * unheld so that any parallel processing tasks drain properly
2173 	 * without deadlocking.
2174 	 */
2175 	if (cam_sc->ev_tq != NULL)
2176 		taskqueue_free(cam_sc->ev_tq);
2177 
2178 	mtx_lock(&sc->mpi3mr_mtx);
2179 
2180 	while (cam_sc->startup_refcount != 0)
2181 		mpi3mr_startup_decrement(cam_sc);
2182 
2183 	/* Deregister our async handler */
2184 	if (cam_sc->path != NULL) {
2185 		xpt_free_path(cam_sc->path);
2186 		cam_sc->path = NULL;
2187 	}
2188 
2189 	if (cam_sc->flags & MPI3MRSAS_IN_STARTUP)
2190 		xpt_release_simq(cam_sc->sim, 1);
2191 
2192 	if (cam_sc->sim != NULL) {
2193 		xpt_bus_deregister(cam_sim_path(cam_sc->sim));
2194 		cam_sim_free(cam_sc->sim, FALSE);
2195 	}
2196 
2197 	mtx_unlock(&sc->mpi3mr_mtx);
2198 
2199 	if (cam_sc->devq != NULL)
2200 		cam_simq_free(cam_sc->devq);
2201 
2202 get_target:
2203 	mtx_lock_spin(&sc->target_lock);
2204  	TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) {
2205  		TAILQ_REMOVE(&sc->cam_sc->tgt_list, target, tgt_next);
2206 		mtx_unlock_spin(&sc->target_lock);
2207 		goto out_tgt_free;
2208 	}
2209 	mtx_unlock_spin(&sc->target_lock);
2210 out_tgt_free:
2211 	if (target) {
2212 		free(target, M_MPI3MR);
2213 		target = NULL;
2214 		goto get_target;
2215  	}
2216 
2217 	free(cam_sc, M_MPI3MR);
2218 	sc->cam_sc = NULL;
2219 
2220 	mpi3mr_dprint(sc, MPI3MR_XINFO, "%s, Exiting CAM detach\n", __func__);
2221 	return (0);
2222 }
2223