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