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