1 /*
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2016-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/types.h>
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/module.h>
49 #include <sys/bus.h>
50 #include <sys/conf.h>
51 #include <sys/malloc.h>
52 #include <sys/sysctl.h>
53 #include <sys/uio.h>
54
55 #include <machine/bus.h>
56 #include <machine/resource.h>
57 #include <sys/rman.h>
58
59 #include <dev/pci/pcireg.h>
60 #include <dev/pci/pcivar.h>
61 #include <dev/pci/pci_private.h>
62
63 #include <cam/cam.h>
64 #include <cam/cam_ccb.h>
65 #include <cam/cam_debug.h>
66 #include <cam/cam_sim.h>
67 #include <cam/cam_xpt_sim.h>
68 #include <cam/cam_xpt_periph.h>
69 #include <cam/cam_periph.h>
70 #include <cam/scsi/scsi_all.h>
71 #include <cam/scsi/scsi_message.h>
72 #include <cam/scsi/smp_all.h>
73 #include <sys/queue.h>
74 #include <sys/kthread.h>
75 #include "mpi3mr.h"
76 #include "mpi3mr_cam.h"
77 #include "mpi3mr_app.h"
78
79 static void mpi3mr_repost_reply_buf(struct mpi3mr_softc *sc,
80 U64 reply_dma);
81 static int mpi3mr_complete_admin_cmd(struct mpi3mr_softc *sc);
82 static void mpi3mr_port_enable_complete(struct mpi3mr_softc *sc,
83 struct mpi3mr_drvr_cmd *drvrcmd);
84 static void mpi3mr_flush_io(struct mpi3mr_softc *sc);
85 static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type,
86 U16 reset_reason);
87 static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc *sc, U16 handle,
88 struct mpi3mr_drvr_cmd *cmdparam, U8 iou_rc);
89 static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc *sc,
90 struct mpi3mr_drvr_cmd *drv_cmd);
91 static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc *sc,
92 struct mpi3mr_drvr_cmd *drv_cmd);
93 static void mpi3mr_send_evt_ack(struct mpi3mr_softc *sc, U8 event,
94 struct mpi3mr_drvr_cmd *cmdparam, U32 event_ctx);
95 static void mpi3mr_print_fault_info(struct mpi3mr_softc *sc);
96 static inline void mpi3mr_set_diagsave(struct mpi3mr_softc *sc);
97 static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code);
98
99 void
mpi3mr_hexdump(void * buf,int sz,int format)100 mpi3mr_hexdump(void *buf, int sz, int format)
101 {
102 int i;
103 U32 *buf_loc = (U32 *)buf;
104
105 for (i = 0; i < (sz / sizeof(U32)); i++) {
106 if ((i % format) == 0) {
107 if (i != 0)
108 printf("\n");
109 printf("%08x: ", (i * 4));
110 }
111 printf("%08x ", buf_loc[i]);
112 }
113 printf("\n");
114 }
115
116 void
init_completion(struct completion * completion)117 init_completion(struct completion *completion)
118 {
119 completion->done = 0;
120 }
121
122 void
complete(struct completion * completion)123 complete(struct completion *completion)
124 {
125 completion->done = 1;
126 wakeup(complete);
127 }
128
wait_for_completion_timeout(struct completion * completion,U32 timeout)129 void wait_for_completion_timeout(struct completion *completion,
130 U32 timeout)
131 {
132 U32 count = timeout * 1000;
133
134 while ((completion->done == 0) && count) {
135 DELAY(1000);
136 count--;
137 }
138
139 if (completion->done == 0) {
140 printf("%s: Command is timedout\n", __func__);
141 completion->done = 1;
142 }
143 }
wait_for_completion_timeout_tm(struct completion * completion,U32 timeout,struct mpi3mr_softc * sc)144 void wait_for_completion_timeout_tm(struct completion *completion,
145 U32 timeout, struct mpi3mr_softc *sc)
146 {
147 U32 count = timeout * 1000;
148
149 while ((completion->done == 0) && count) {
150 msleep(&sc->tm_chan, &sc->mpi3mr_mtx, PRIBIO,
151 "TM command", 1 * hz);
152 count--;
153 }
154
155 if (completion->done == 0) {
156 printf("%s: Command is timedout\n", __func__);
157 completion->done = 1;
158 }
159 }
160
161
162 void
poll_for_command_completion(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * cmd,U16 wait)163 poll_for_command_completion(struct mpi3mr_softc *sc,
164 struct mpi3mr_drvr_cmd *cmd, U16 wait)
165 {
166 int wait_time = wait * 1000;
167 while (wait_time) {
168 mpi3mr_complete_admin_cmd(sc);
169 if (cmd->state & MPI3MR_CMD_COMPLETE)
170 break;
171 DELAY(1000);
172 wait_time--;
173 }
174 }
175
176 /**
177 * mpi3mr_trigger_snapdump - triggers firmware snapdump
178 * @sc: Adapter instance reference
179 * @reason_code: reason code for the fault.
180 *
181 * This routine will trigger the snapdump and wait for it to
182 * complete or timeout before it returns.
183 * This will be called during initilaization time faults/resets/timeouts
184 * before soft reset invocation.
185 *
186 * Return: None.
187 */
188 static void
mpi3mr_trigger_snapdump(struct mpi3mr_softc * sc,U16 reason_code)189 mpi3mr_trigger_snapdump(struct mpi3mr_softc *sc, U16 reason_code)
190 {
191 U32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
192
193 mpi3mr_dprint(sc, MPI3MR_INFO, "snapdump triggered: reason code: %s\n",
194 mpi3mr_reset_rc_name(reason_code));
195
196 mpi3mr_set_diagsave(sc);
197 mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT,
198 reason_code);
199
200 do {
201 host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET);
202 if (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS))
203 break;
204 DELAY(100 * 1000);
205 } while (--timeout);
206
207 return;
208 }
209
210 /**
211 * mpi3mr_check_rh_fault_ioc - check reset history and fault
212 * controller
213 * @sc: Adapter instance reference
214 * @reason_code, reason code for the fault.
215 *
216 * This routine will fault the controller with
217 * the given reason code if it is not already in the fault or
218 * not asynchronosuly reset. This will be used to handle
219 * initilaization time faults/resets/timeout as in those cases
220 * immediate soft reset invocation is not required.
221 *
222 * Return: None.
223 */
mpi3mr_check_rh_fault_ioc(struct mpi3mr_softc * sc,U16 reason_code)224 static void mpi3mr_check_rh_fault_ioc(struct mpi3mr_softc *sc, U16 reason_code)
225 {
226 U32 ioc_status;
227
228 if (sc->unrecoverable) {
229 mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is unrecoverable\n");
230 return;
231 }
232
233 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
234 if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) ||
235 (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) {
236 mpi3mr_print_fault_info(sc);
237 return;
238 }
239
240 mpi3mr_trigger_snapdump(sc, reason_code);
241
242 return;
243 }
244
mpi3mr_get_reply_virt_addr(struct mpi3mr_softc * sc,bus_addr_t phys_addr)245 static void * mpi3mr_get_reply_virt_addr(struct mpi3mr_softc *sc,
246 bus_addr_t phys_addr)
247 {
248 if (!phys_addr)
249 return NULL;
250 if ((phys_addr < sc->reply_buf_dma_min_address) ||
251 (phys_addr > sc->reply_buf_dma_max_address))
252 return NULL;
253
254 return sc->reply_buf + (phys_addr - sc->reply_buf_phys);
255 }
256
mpi3mr_get_sensebuf_virt_addr(struct mpi3mr_softc * sc,bus_addr_t phys_addr)257 static void * mpi3mr_get_sensebuf_virt_addr(struct mpi3mr_softc *sc,
258 bus_addr_t phys_addr)
259 {
260 if (!phys_addr)
261 return NULL;
262 return sc->sense_buf + (phys_addr - sc->sense_buf_phys);
263 }
264
mpi3mr_repost_reply_buf(struct mpi3mr_softc * sc,U64 reply_dma)265 static void mpi3mr_repost_reply_buf(struct mpi3mr_softc *sc,
266 U64 reply_dma)
267 {
268 U32 old_idx = 0;
269
270 mtx_lock_spin(&sc->reply_free_q_lock);
271 old_idx = sc->reply_free_q_host_index;
272 sc->reply_free_q_host_index = ((sc->reply_free_q_host_index ==
273 (sc->reply_free_q_sz - 1)) ? 0 :
274 (sc->reply_free_q_host_index + 1));
275 sc->reply_free_q[old_idx] = reply_dma;
276 mpi3mr_regwrite(sc, MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET,
277 sc->reply_free_q_host_index);
278 mtx_unlock_spin(&sc->reply_free_q_lock);
279 }
280
mpi3mr_repost_sense_buf(struct mpi3mr_softc * sc,U64 sense_buf_phys)281 static void mpi3mr_repost_sense_buf(struct mpi3mr_softc *sc,
282 U64 sense_buf_phys)
283 {
284 U32 old_idx = 0;
285
286 mtx_lock_spin(&sc->sense_buf_q_lock);
287 old_idx = sc->sense_buf_q_host_index;
288 sc->sense_buf_q_host_index = ((sc->sense_buf_q_host_index ==
289 (sc->sense_buf_q_sz - 1)) ? 0 :
290 (sc->sense_buf_q_host_index + 1));
291 sc->sense_buf_q[old_idx] = sense_buf_phys;
292 mpi3mr_regwrite(sc, MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET,
293 sc->sense_buf_q_host_index);
294 mtx_unlock_spin(&sc->sense_buf_q_lock);
295
296 }
297
mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_softc * sc,struct mpi3mr_throttle_group_info * tg,U8 divert_value)298 void mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_softc *sc,
299 struct mpi3mr_throttle_group_info *tg, U8 divert_value)
300 {
301 struct mpi3mr_target *target;
302
303 mtx_lock_spin(&sc->target_lock);
304 TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) {
305 if (target->throttle_group == tg)
306 target->io_divert = divert_value;
307 }
308 mtx_unlock_spin(&sc->target_lock);
309 }
310
311 /**
312 * mpi3mr_submit_admin_cmd - Submit request to admin queue
313 * @mrioc: Adapter reference
314 * @admin_req: MPI3 request
315 * @admin_req_sz: Request size
316 *
317 * Post the MPI3 request into admin request queue and
318 * inform the controller, if the queue is full return
319 * appropriate error.
320 *
321 * Return: 0 on success, non-zero on failure.
322 */
mpi3mr_submit_admin_cmd(struct mpi3mr_softc * sc,void * admin_req,U16 admin_req_sz)323 int mpi3mr_submit_admin_cmd(struct mpi3mr_softc *sc, void *admin_req,
324 U16 admin_req_sz)
325 {
326 U16 areq_pi = 0, areq_ci = 0, max_entries = 0;
327 int retval = 0;
328 U8 *areq_entry;
329
330 mtx_lock_spin(&sc->admin_req_lock);
331 areq_pi = sc->admin_req_pi;
332 areq_ci = sc->admin_req_ci;
333 max_entries = sc->num_admin_reqs;
334
335 if (sc->unrecoverable)
336 return -EFAULT;
337
338 if ((areq_ci == (areq_pi + 1)) || ((!areq_ci) &&
339 (areq_pi == (max_entries - 1)))) {
340 printf(IOCNAME "AdminReqQ full condition detected\n",
341 sc->name);
342 retval = -EAGAIN;
343 goto out;
344 }
345 areq_entry = (U8 *)sc->admin_req + (areq_pi *
346 MPI3MR_AREQ_FRAME_SZ);
347 memset(areq_entry, 0, MPI3MR_AREQ_FRAME_SZ);
348 memcpy(areq_entry, (U8 *)admin_req, admin_req_sz);
349
350 if (++areq_pi == max_entries)
351 areq_pi = 0;
352 sc->admin_req_pi = areq_pi;
353
354 mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET, sc->admin_req_pi);
355
356 out:
357 mtx_unlock_spin(&sc->admin_req_lock);
358 return retval;
359 }
360
361 /**
362 * mpi3mr_check_req_qfull - Check request queue is full or not
363 * @op_req_q: Operational reply queue info
364 *
365 * Return: true when queue full, false otherwise.
366 */
367 static inline bool
mpi3mr_check_req_qfull(struct mpi3mr_op_req_queue * op_req_q)368 mpi3mr_check_req_qfull(struct mpi3mr_op_req_queue *op_req_q)
369 {
370 U16 pi, ci, max_entries;
371 bool is_qfull = false;
372
373 pi = op_req_q->pi;
374 ci = op_req_q->ci;
375 max_entries = op_req_q->num_reqs;
376
377 if ((ci == (pi + 1)) || ((!ci) && (pi == (max_entries - 1))))
378 is_qfull = true;
379
380 return is_qfull;
381 }
382
383 /**
384 * mpi3mr_submit_io - Post IO command to firmware
385 * @sc: Adapter instance reference
386 * @op_req_q: Operational Request queue reference
387 * @req: MPT request data
388 *
389 * This function submits IO command to firmware.
390 *
391 * Return: Nothing
392 */
mpi3mr_submit_io(struct mpi3mr_softc * sc,struct mpi3mr_op_req_queue * op_req_q,U8 * req)393 int mpi3mr_submit_io(struct mpi3mr_softc *sc,
394 struct mpi3mr_op_req_queue *op_req_q, U8 *req)
395 {
396 U16 pi, max_entries;
397 int retval = 0;
398 U8 *req_entry;
399 U16 req_sz = sc->facts.op_req_sz;
400 struct mpi3mr_irq_context *irq_ctx;
401
402 mtx_lock_spin(&op_req_q->q_lock);
403
404 pi = op_req_q->pi;
405 max_entries = op_req_q->num_reqs;
406 if (mpi3mr_check_req_qfull(op_req_q)) {
407 irq_ctx = &sc->irq_ctx[op_req_q->reply_qid - 1];
408 mpi3mr_complete_io_cmd(sc, irq_ctx);
409
410 if (mpi3mr_check_req_qfull(op_req_q)) {
411 printf(IOCNAME "OpReqQ full condition detected\n",
412 sc->name);
413 retval = -EBUSY;
414 goto out;
415 }
416 }
417
418 req_entry = (U8 *)op_req_q->q_base + (pi * req_sz);
419 memset(req_entry, 0, req_sz);
420 memcpy(req_entry, req, MPI3MR_AREQ_FRAME_SZ);
421 if (++pi == max_entries)
422 pi = 0;
423 op_req_q->pi = pi;
424
425 mpi3mr_atomic_inc(&sc->op_reply_q[op_req_q->reply_qid - 1].pend_ios);
426
427 mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REQ_Q_N_PI_OFFSET(op_req_q->qid), op_req_q->pi);
428 if (sc->mpi3mr_debug & MPI3MR_TRACE) {
429 device_printf(sc->mpi3mr_dev, "IO submission: QID:%d PI:0x%x\n", op_req_q->qid, op_req_q->pi);
430 mpi3mr_hexdump(req_entry, MPI3MR_AREQ_FRAME_SZ, 8);
431 }
432
433 out:
434 mtx_unlock_spin(&op_req_q->q_lock);
435 return retval;
436 }
437
438 inline void
mpi3mr_add_sg_single(void * paddr,U8 flags,U32 length,bus_addr_t dma_addr)439 mpi3mr_add_sg_single(void *paddr, U8 flags, U32 length,
440 bus_addr_t dma_addr)
441 {
442 Mpi3SGESimple_t *sgel = paddr;
443
444 sgel->Flags = flags;
445 sgel->Length = (length);
446 sgel->Address = (U64)dma_addr;
447 }
448
mpi3mr_build_zero_len_sge(void * paddr)449 void mpi3mr_build_zero_len_sge(void *paddr)
450 {
451 U8 sgl_flags = (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE |
452 MPI3_SGE_FLAGS_DLAS_SYSTEM | MPI3_SGE_FLAGS_END_OF_LIST);
453
454 mpi3mr_add_sg_single(paddr, sgl_flags, 0, -1);
455
456 }
457
mpi3mr_enable_interrupts(struct mpi3mr_softc * sc)458 void mpi3mr_enable_interrupts(struct mpi3mr_softc *sc)
459 {
460 sc->intr_enabled = 1;
461 }
462
mpi3mr_disable_interrupts(struct mpi3mr_softc * sc)463 void mpi3mr_disable_interrupts(struct mpi3mr_softc *sc)
464 {
465 sc->intr_enabled = 0;
466 }
467
468 void
mpi3mr_memaddr_cb(void * arg,bus_dma_segment_t * segs,int nsegs,int error)469 mpi3mr_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
470 {
471 bus_addr_t *addr;
472
473 addr = arg;
474 *addr = segs[0].ds_addr;
475 }
476
mpi3mr_delete_op_reply_queue(struct mpi3mr_softc * sc,U16 qid)477 static int mpi3mr_delete_op_reply_queue(struct mpi3mr_softc *sc, U16 qid)
478 {
479 Mpi3DeleteReplyQueueRequest_t delq_req;
480 struct mpi3mr_op_reply_queue *op_reply_q;
481 int retval = 0;
482
483
484 op_reply_q = &sc->op_reply_q[qid - 1];
485
486 if (!op_reply_q->qid)
487 {
488 retval = -1;
489 printf(IOCNAME "Issue DelRepQ: called with invalid Reply QID\n",
490 sc->name);
491 goto out;
492 }
493
494 memset(&delq_req, 0, sizeof(delq_req));
495
496 mtx_lock(&sc->init_cmds.completion.lock);
497 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
498 retval = -1;
499 printf(IOCNAME "Issue DelRepQ: Init command is in use\n",
500 sc->name);
501 mtx_unlock(&sc->init_cmds.completion.lock);
502 goto out;
503 }
504
505 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
506 retval = -1;
507 printf(IOCNAME "Issue DelRepQ: Init command is in use\n",
508 sc->name);
509 goto out;
510 }
511 sc->init_cmds.state = MPI3MR_CMD_PENDING;
512 sc->init_cmds.is_waiting = 1;
513 sc->init_cmds.callback = NULL;
514 delq_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
515 delq_req.Function = MPI3_FUNCTION_DELETE_REPLY_QUEUE;
516 delq_req.QueueID = qid;
517
518 init_completion(&sc->init_cmds.completion);
519 retval = mpi3mr_submit_admin_cmd(sc, &delq_req, sizeof(delq_req));
520 if (retval) {
521 printf(IOCNAME "Issue DelRepQ: Admin Post failed\n",
522 sc->name);
523 goto out_unlock;
524 }
525 wait_for_completion_timeout(&sc->init_cmds.completion,
526 (MPI3MR_INTADMCMD_TIMEOUT));
527 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
528 printf(IOCNAME "Issue DelRepQ: command timed out\n",
529 sc->name);
530 mpi3mr_check_rh_fault_ioc(sc,
531 MPI3MR_RESET_FROM_DELREPQ_TIMEOUT);
532 sc->unrecoverable = 1;
533
534 retval = -1;
535 goto out_unlock;
536 }
537 if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
538 != MPI3_IOCSTATUS_SUCCESS ) {
539 printf(IOCNAME "Issue DelRepQ: Failed IOCStatus(0x%04x) "
540 " Loginfo(0x%08x) \n" , sc->name,
541 (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
542 sc->init_cmds.ioc_loginfo);
543 retval = -1;
544 goto out_unlock;
545 }
546 sc->irq_ctx[qid - 1].op_reply_q = NULL;
547
548 if (sc->op_reply_q[qid - 1].q_base_phys != 0)
549 bus_dmamap_unload(sc->op_reply_q[qid - 1].q_base_tag, sc->op_reply_q[qid - 1].q_base_dmamap);
550 if (sc->op_reply_q[qid - 1].q_base != NULL)
551 bus_dmamem_free(sc->op_reply_q[qid - 1].q_base_tag, sc->op_reply_q[qid - 1].q_base, sc->op_reply_q[qid - 1].q_base_dmamap);
552 if (sc->op_reply_q[qid - 1].q_base_tag != NULL)
553 bus_dma_tag_destroy(sc->op_reply_q[qid - 1].q_base_tag);
554
555 sc->op_reply_q[qid - 1].q_base = NULL;
556 sc->op_reply_q[qid - 1].qid = 0;
557 out_unlock:
558 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
559 mtx_unlock(&sc->init_cmds.completion.lock);
560 out:
561 return retval;
562 }
563
564 /**
565 * mpi3mr_create_op_reply_queue - create operational reply queue
566 * @sc: Adapter instance reference
567 * @qid: operational reply queue id
568 *
569 * Create operatinal reply queue by issuing MPI request
570 * through admin queue.
571 *
572 * Return: 0 on success, non-zero on failure.
573 */
mpi3mr_create_op_reply_queue(struct mpi3mr_softc * sc,U16 qid)574 static int mpi3mr_create_op_reply_queue(struct mpi3mr_softc *sc, U16 qid)
575 {
576 Mpi3CreateReplyQueueRequest_t create_req;
577 struct mpi3mr_op_reply_queue *op_reply_q;
578 int retval = 0;
579 char q_lock_name[32];
580
581 op_reply_q = &sc->op_reply_q[qid - 1];
582
583 if (op_reply_q->qid)
584 {
585 retval = -1;
586 printf(IOCNAME "CreateRepQ: called for duplicate qid %d\n",
587 sc->name, op_reply_q->qid);
588 return retval;
589 }
590
591 op_reply_q->ci = 0;
592 if (pci_get_revid(sc->mpi3mr_dev) == SAS4116_CHIP_REV_A0)
593 op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD_A0;
594 else
595 op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD;
596
597 op_reply_q->qsz = op_reply_q->num_replies * sc->op_reply_sz;
598 op_reply_q->ephase = 1;
599
600 if (!op_reply_q->q_base) {
601 snprintf(q_lock_name, 32, "Reply Queue Lock[%d]", qid);
602 mtx_init(&op_reply_q->q_lock, q_lock_name, NULL, MTX_SPIN);
603
604 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
605 4, 0, /* algnmnt, boundary */
606 sc->dma_loaddr, /* lowaddr */
607 BUS_SPACE_MAXADDR, /* highaddr */
608 NULL, NULL, /* filter, filterarg */
609 op_reply_q->qsz, /* maxsize */
610 1, /* nsegments */
611 op_reply_q->qsz, /* maxsegsize */
612 0, /* flags */
613 NULL, NULL, /* lockfunc, lockarg */
614 &op_reply_q->q_base_tag)) {
615 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Operational reply DMA tag\n");
616 return (ENOMEM);
617 }
618
619 if (bus_dmamem_alloc(op_reply_q->q_base_tag, (void **)&op_reply_q->q_base,
620 BUS_DMA_NOWAIT, &op_reply_q->q_base_dmamap)) {
621 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
622 return (ENOMEM);
623 }
624 bzero(op_reply_q->q_base, op_reply_q->qsz);
625 bus_dmamap_load(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap, op_reply_q->q_base, op_reply_q->qsz,
626 mpi3mr_memaddr_cb, &op_reply_q->q_base_phys, BUS_DMA_NOWAIT);
627 mpi3mr_dprint(sc, MPI3MR_XINFO, "Operational Reply queue ID: %d phys addr= %#016jx virt_addr: %pa size= %d\n",
628 qid, (uintmax_t)op_reply_q->q_base_phys, op_reply_q->q_base, op_reply_q->qsz);
629
630 if (!op_reply_q->q_base)
631 {
632 retval = -1;
633 printf(IOCNAME "CreateRepQ: memory alloc failed for qid %d\n",
634 sc->name, qid);
635 goto out;
636 }
637 }
638
639 memset(&create_req, 0, sizeof(create_req));
640
641 mtx_lock(&sc->init_cmds.completion.lock);
642 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
643 retval = -1;
644 printf(IOCNAME "CreateRepQ: Init command is in use\n",
645 sc->name);
646 mtx_unlock(&sc->init_cmds.completion.lock);
647 goto out;
648 }
649
650 sc->init_cmds.state = MPI3MR_CMD_PENDING;
651 sc->init_cmds.is_waiting = 1;
652 sc->init_cmds.callback = NULL;
653 create_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
654 create_req.Function = MPI3_FUNCTION_CREATE_REPLY_QUEUE;
655 create_req.QueueID = qid;
656 create_req.Flags = MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE;
657 create_req.MSIxIndex = sc->irq_ctx[qid - 1].msix_index;
658 create_req.BaseAddress = (U64)op_reply_q->q_base_phys;
659 create_req.Size = op_reply_q->num_replies;
660
661 init_completion(&sc->init_cmds.completion);
662 retval = mpi3mr_submit_admin_cmd(sc, &create_req,
663 sizeof(create_req));
664 if (retval) {
665 printf(IOCNAME "CreateRepQ: Admin Post failed\n",
666 sc->name);
667 goto out_unlock;
668 }
669
670 wait_for_completion_timeout(&sc->init_cmds.completion,
671 MPI3MR_INTADMCMD_TIMEOUT);
672 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
673 printf(IOCNAME "CreateRepQ: command timed out\n",
674 sc->name);
675 mpi3mr_check_rh_fault_ioc(sc,
676 MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT);
677 sc->unrecoverable = 1;
678 retval = -1;
679 goto out_unlock;
680 }
681
682 if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
683 != MPI3_IOCSTATUS_SUCCESS ) {
684 printf(IOCNAME "CreateRepQ: Failed IOCStatus(0x%04x) "
685 " Loginfo(0x%08x) \n" , sc->name,
686 (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
687 sc->init_cmds.ioc_loginfo);
688 retval = -1;
689 goto out_unlock;
690 }
691 op_reply_q->qid = qid;
692 sc->irq_ctx[qid - 1].op_reply_q = op_reply_q;
693
694 out_unlock:
695 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
696 mtx_unlock(&sc->init_cmds.completion.lock);
697 out:
698 if (retval) {
699 if (op_reply_q->q_base_phys != 0)
700 bus_dmamap_unload(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap);
701 if (op_reply_q->q_base != NULL)
702 bus_dmamem_free(op_reply_q->q_base_tag, op_reply_q->q_base, op_reply_q->q_base_dmamap);
703 if (op_reply_q->q_base_tag != NULL)
704 bus_dma_tag_destroy(op_reply_q->q_base_tag);
705 op_reply_q->q_base = NULL;
706 op_reply_q->qid = 0;
707 }
708
709 return retval;
710 }
711
712 /**
713 * mpi3mr_create_op_req_queue - create operational request queue
714 * @sc: Adapter instance reference
715 * @req_qid: operational request queue id
716 * @reply_qid: Reply queue ID
717 *
718 * Create operatinal request queue by issuing MPI request
719 * through admin queue.
720 *
721 * Return: 0 on success, non-zero on failure.
722 */
mpi3mr_create_op_req_queue(struct mpi3mr_softc * sc,U16 req_qid,U8 reply_qid)723 static int mpi3mr_create_op_req_queue(struct mpi3mr_softc *sc, U16 req_qid, U8 reply_qid)
724 {
725 Mpi3CreateRequestQueueRequest_t create_req;
726 struct mpi3mr_op_req_queue *op_req_q;
727 int retval = 0;
728 char q_lock_name[32];
729
730 op_req_q = &sc->op_req_q[req_qid - 1];
731
732 if (op_req_q->qid)
733 {
734 retval = -1;
735 printf(IOCNAME "CreateReqQ: called for duplicate qid %d\n",
736 sc->name, op_req_q->qid);
737 return retval;
738 }
739
740 op_req_q->ci = 0;
741 op_req_q->pi = 0;
742 op_req_q->num_reqs = MPI3MR_OP_REQ_Q_QD;
743 op_req_q->qsz = op_req_q->num_reqs * sc->facts.op_req_sz;
744 op_req_q->reply_qid = reply_qid;
745
746 if (!op_req_q->q_base) {
747 snprintf(q_lock_name, 32, "Request Queue Lock[%d]", req_qid);
748 mtx_init(&op_req_q->q_lock, q_lock_name, NULL, MTX_SPIN);
749
750 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
751 4, 0, /* algnmnt, boundary */
752 sc->dma_loaddr, /* lowaddr */
753 BUS_SPACE_MAXADDR, /* highaddr */
754 NULL, NULL, /* filter, filterarg */
755 op_req_q->qsz, /* maxsize */
756 1, /* nsegments */
757 op_req_q->qsz, /* maxsegsize */
758 0, /* flags */
759 NULL, NULL, /* lockfunc, lockarg */
760 &op_req_q->q_base_tag)) {
761 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
762 return (ENOMEM);
763 }
764
765 if (bus_dmamem_alloc(op_req_q->q_base_tag, (void **)&op_req_q->q_base,
766 BUS_DMA_NOWAIT, &op_req_q->q_base_dmamap)) {
767 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
768 return (ENOMEM);
769 }
770
771 bzero(op_req_q->q_base, op_req_q->qsz);
772
773 bus_dmamap_load(op_req_q->q_base_tag, op_req_q->q_base_dmamap, op_req_q->q_base, op_req_q->qsz,
774 mpi3mr_memaddr_cb, &op_req_q->q_base_phys, BUS_DMA_NOWAIT);
775
776 mpi3mr_dprint(sc, MPI3MR_XINFO, "Operational Request QID: %d phys addr= %#016jx virt addr= %pa size= %d associated Reply QID: %d\n",
777 req_qid, (uintmax_t)op_req_q->q_base_phys, op_req_q->q_base, op_req_q->qsz, reply_qid);
778
779 if (!op_req_q->q_base) {
780 retval = -1;
781 printf(IOCNAME "CreateReqQ: memory alloc failed for qid %d\n",
782 sc->name, req_qid);
783 goto out;
784 }
785 }
786
787 memset(&create_req, 0, sizeof(create_req));
788
789 mtx_lock(&sc->init_cmds.completion.lock);
790 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
791 retval = -1;
792 printf(IOCNAME "CreateReqQ: Init command is in use\n",
793 sc->name);
794 mtx_unlock(&sc->init_cmds.completion.lock);
795 goto out;
796 }
797
798 sc->init_cmds.state = MPI3MR_CMD_PENDING;
799 sc->init_cmds.is_waiting = 1;
800 sc->init_cmds.callback = NULL;
801 create_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
802 create_req.Function = MPI3_FUNCTION_CREATE_REQUEST_QUEUE;
803 create_req.QueueID = req_qid;
804 create_req.Flags = 0;
805 create_req.ReplyQueueID = reply_qid;
806 create_req.BaseAddress = (U64)op_req_q->q_base_phys;
807 create_req.Size = op_req_q->num_reqs;
808
809 init_completion(&sc->init_cmds.completion);
810 retval = mpi3mr_submit_admin_cmd(sc, &create_req,
811 sizeof(create_req));
812 if (retval) {
813 printf(IOCNAME "CreateReqQ: Admin Post failed\n",
814 sc->name);
815 goto out_unlock;
816 }
817
818 wait_for_completion_timeout(&sc->init_cmds.completion,
819 (MPI3MR_INTADMCMD_TIMEOUT));
820
821 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
822 printf(IOCNAME "CreateReqQ: command timed out\n",
823 sc->name);
824 mpi3mr_check_rh_fault_ioc(sc,
825 MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT);
826 sc->unrecoverable = 1;
827 retval = -1;
828 goto out_unlock;
829 }
830
831 if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
832 != MPI3_IOCSTATUS_SUCCESS ) {
833 printf(IOCNAME "CreateReqQ: Failed IOCStatus(0x%04x) "
834 " Loginfo(0x%08x) \n" , sc->name,
835 (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
836 sc->init_cmds.ioc_loginfo);
837 retval = -1;
838 goto out_unlock;
839 }
840 op_req_q->qid = req_qid;
841
842 out_unlock:
843 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
844 mtx_unlock(&sc->init_cmds.completion.lock);
845 out:
846 if (retval) {
847 if (op_req_q->q_base_phys != 0)
848 bus_dmamap_unload(op_req_q->q_base_tag, op_req_q->q_base_dmamap);
849 if (op_req_q->q_base != NULL)
850 bus_dmamem_free(op_req_q->q_base_tag, op_req_q->q_base, op_req_q->q_base_dmamap);
851 if (op_req_q->q_base_tag != NULL)
852 bus_dma_tag_destroy(op_req_q->q_base_tag);
853 op_req_q->q_base = NULL;
854 op_req_q->qid = 0;
855 }
856 return retval;
857 }
858
859 /**
860 * mpi3mr_create_op_queues - create operational queues
861 * @sc: Adapter instance reference
862 *
863 * Create operatinal queues(request queues and reply queues).
864 * Return: 0 on success, non-zero on failure.
865 */
mpi3mr_create_op_queues(struct mpi3mr_softc * sc)866 static int mpi3mr_create_op_queues(struct mpi3mr_softc *sc)
867 {
868 int retval = 0;
869 U16 num_queues = 0, i = 0, qid;
870
871 num_queues = min(sc->facts.max_op_reply_q,
872 sc->facts.max_op_req_q);
873 num_queues = min(num_queues, sc->msix_count);
874
875 /*
876 * During reset set the num_queues to the number of queues
877 * that was set before the reset.
878 */
879 if (sc->num_queues)
880 num_queues = sc->num_queues;
881
882 mpi3mr_dprint(sc, MPI3MR_XINFO, "Trying to create %d Operational Q pairs\n",
883 num_queues);
884
885 if (!sc->op_req_q) {
886 sc->op_req_q = malloc(sizeof(struct mpi3mr_op_req_queue) *
887 num_queues, M_MPI3MR, M_NOWAIT | M_ZERO);
888
889 if (!sc->op_req_q) {
890 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to alloc memory for Request queue info\n");
891 retval = -1;
892 goto out_failed;
893 }
894 }
895
896 if (!sc->op_reply_q) {
897 sc->op_reply_q = malloc(sizeof(struct mpi3mr_op_reply_queue) * num_queues,
898 M_MPI3MR, M_NOWAIT | M_ZERO);
899
900 if (!sc->op_reply_q) {
901 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to alloc memory for Reply queue info\n");
902 retval = -1;
903 goto out_failed;
904 }
905 }
906
907 sc->num_hosttag_op_req_q = (sc->max_host_ios + 1) / num_queues;
908
909 /*Operational Request and reply queue ID starts with 1*/
910 for (i = 0; i < num_queues; i++) {
911 qid = i + 1;
912 if (mpi3mr_create_op_reply_queue(sc, qid)) {
913 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create Reply queue %d\n",
914 qid);
915 break;
916 }
917 if (mpi3mr_create_op_req_queue(sc, qid,
918 sc->op_reply_q[qid - 1].qid)) {
919 mpi3mr_delete_op_reply_queue(sc, qid);
920 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create Request queue %d\n",
921 qid);
922 break;
923 }
924
925 }
926
927 /* Not even one queue is created successfully*/
928 if (i == 0) {
929 retval = -1;
930 goto out_failed;
931 }
932
933 if (!sc->num_queues) {
934 sc->num_queues = i;
935 } else {
936 if (num_queues != i) {
937 mpi3mr_dprint(sc, MPI3MR_ERROR, "Number of queues (%d) post reset are not same as"
938 "queues allocated (%d) during driver init\n", i, num_queues);
939 goto out_failed;
940 }
941 }
942
943 mpi3mr_dprint(sc, MPI3MR_INFO, "Successfully created %d Operational Queue pairs\n",
944 sc->num_queues);
945 mpi3mr_dprint(sc, MPI3MR_INFO, "Request Queue QD: %d Reply queue QD: %d\n",
946 sc->op_req_q[0].num_reqs, sc->op_reply_q[0].num_replies);
947
948 return retval;
949 out_failed:
950 if (sc->op_req_q) {
951 free(sc->op_req_q, M_MPI3MR);
952 sc->op_req_q = NULL;
953 }
954 if (sc->op_reply_q) {
955 free(sc->op_reply_q, M_MPI3MR);
956 sc->op_reply_q = NULL;
957 }
958 return retval;
959 }
960
961 /**
962 * mpi3mr_setup_admin_qpair - Setup admin queue pairs
963 * @sc: Adapter instance reference
964 *
965 * Allocation and setup admin queues(request queues and reply queues).
966 * Return: 0 on success, non-zero on failure.
967 */
mpi3mr_setup_admin_qpair(struct mpi3mr_softc * sc)968 static int mpi3mr_setup_admin_qpair(struct mpi3mr_softc *sc)
969 {
970 int retval = 0;
971 U32 num_adm_entries = 0;
972
973 sc->admin_req_q_sz = MPI3MR_AREQQ_SIZE;
974 sc->num_admin_reqs = sc->admin_req_q_sz / MPI3MR_AREQ_FRAME_SZ;
975 sc->admin_req_ci = sc->admin_req_pi = 0;
976
977 sc->admin_reply_q_sz = MPI3MR_AREPQ_SIZE;
978 sc->num_admin_replies = sc->admin_reply_q_sz/ MPI3MR_AREP_FRAME_SZ;
979 sc->admin_reply_ci = 0;
980 sc->admin_reply_ephase = 1;
981
982 if (!sc->admin_req) {
983 /*
984 * We need to create the tag for the admin queue to get the
985 * iofacts to see how many bits the controller decodes. Solve
986 * this chicken and egg problem by only doing lower 4GB DMA.
987 */
988 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
989 4, 0, /* algnmnt, boundary */
990 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
991 BUS_SPACE_MAXADDR, /* highaddr */
992 NULL, NULL, /* filter, filterarg */
993 sc->admin_req_q_sz, /* maxsize */
994 1, /* nsegments */
995 sc->admin_req_q_sz, /* maxsegsize */
996 0, /* flags */
997 NULL, NULL, /* lockfunc, lockarg */
998 &sc->admin_req_tag)) {
999 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
1000 return (ENOMEM);
1001 }
1002
1003 if (bus_dmamem_alloc(sc->admin_req_tag, (void **)&sc->admin_req,
1004 BUS_DMA_NOWAIT, &sc->admin_req_dmamap)) {
1005 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
1006 return (ENOMEM);
1007 }
1008 bzero(sc->admin_req, sc->admin_req_q_sz);
1009 bus_dmamap_load(sc->admin_req_tag, sc->admin_req_dmamap, sc->admin_req, sc->admin_req_q_sz,
1010 mpi3mr_memaddr_cb, &sc->admin_req_phys, BUS_DMA_NOWAIT);
1011 mpi3mr_dprint(sc, MPI3MR_XINFO, "Admin Req queue phys addr= %#016jx size= %d\n",
1012 (uintmax_t)sc->admin_req_phys, sc->admin_req_q_sz);
1013
1014 if (!sc->admin_req)
1015 {
1016 retval = -1;
1017 printf(IOCNAME "Memory alloc for AdminReqQ: failed\n",
1018 sc->name);
1019 goto out_failed;
1020 }
1021 }
1022
1023 if (!sc->admin_reply) {
1024 mtx_init(&sc->admin_reply_lock, "Admin Reply Queue Lock", NULL, MTX_SPIN);
1025
1026 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
1027 4, 0, /* algnmnt, boundary */
1028 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
1029 BUS_SPACE_MAXADDR, /* highaddr */
1030 NULL, NULL, /* filter, filterarg */
1031 sc->admin_reply_q_sz, /* maxsize */
1032 1, /* nsegments */
1033 sc->admin_reply_q_sz, /* maxsegsize */
1034 0, /* flags */
1035 NULL, NULL, /* lockfunc, lockarg */
1036 &sc->admin_reply_tag)) {
1037 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate reply DMA tag\n");
1038 return (ENOMEM);
1039 }
1040
1041 if (bus_dmamem_alloc(sc->admin_reply_tag, (void **)&sc->admin_reply,
1042 BUS_DMA_NOWAIT, &sc->admin_reply_dmamap)) {
1043 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
1044 return (ENOMEM);
1045 }
1046 bzero(sc->admin_reply, sc->admin_reply_q_sz);
1047 bus_dmamap_load(sc->admin_reply_tag, sc->admin_reply_dmamap, sc->admin_reply, sc->admin_reply_q_sz,
1048 mpi3mr_memaddr_cb, &sc->admin_reply_phys, BUS_DMA_NOWAIT);
1049 mpi3mr_dprint(sc, MPI3MR_XINFO, "Admin Reply queue phys addr= %#016jx size= %d\n",
1050 (uintmax_t)sc->admin_reply_phys, sc->admin_req_q_sz);
1051
1052
1053 if (!sc->admin_reply)
1054 {
1055 retval = -1;
1056 printf(IOCNAME "Memory alloc for AdminRepQ: failed\n",
1057 sc->name);
1058 goto out_failed;
1059 }
1060 }
1061
1062 num_adm_entries = (sc->num_admin_replies << 16) |
1063 (sc->num_admin_reqs);
1064 mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_OFFSET, num_adm_entries);
1065 mpi3mr_regwrite64(sc, MPI3_SYSIF_ADMIN_REQ_Q_ADDR_LOW_OFFSET, sc->admin_req_phys);
1066 mpi3mr_regwrite64(sc, MPI3_SYSIF_ADMIN_REPLY_Q_ADDR_LOW_OFFSET, sc->admin_reply_phys);
1067 mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET, sc->admin_req_pi);
1068 mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, sc->admin_reply_ci);
1069
1070 return retval;
1071
1072 out_failed:
1073 /* Free Admin reply*/
1074 if (sc->admin_reply_phys)
1075 bus_dmamap_unload(sc->admin_reply_tag, sc->admin_reply_dmamap);
1076
1077 if (sc->admin_reply != NULL)
1078 bus_dmamem_free(sc->admin_reply_tag, sc->admin_reply,
1079 sc->admin_reply_dmamap);
1080
1081 if (sc->admin_reply_tag != NULL)
1082 bus_dma_tag_destroy(sc->admin_reply_tag);
1083
1084 /* Free Admin request*/
1085 if (sc->admin_req_phys)
1086 bus_dmamap_unload(sc->admin_req_tag, sc->admin_req_dmamap);
1087
1088 if (sc->admin_req != NULL)
1089 bus_dmamem_free(sc->admin_req_tag, sc->admin_req,
1090 sc->admin_req_dmamap);
1091
1092 if (sc->admin_req_tag != NULL)
1093 bus_dma_tag_destroy(sc->admin_req_tag);
1094
1095 return retval;
1096 }
1097
1098 /**
1099 * mpi3mr_print_fault_info - Display fault information
1100 * @sc: Adapter instance reference
1101 *
1102 * Display the controller fault information if there is a
1103 * controller fault.
1104 *
1105 * Return: Nothing.
1106 */
mpi3mr_print_fault_info(struct mpi3mr_softc * sc)1107 static void mpi3mr_print_fault_info(struct mpi3mr_softc *sc)
1108 {
1109 U32 ioc_status, code, code1, code2, code3;
1110
1111 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
1112
1113 if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) {
1114 code = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) &
1115 MPI3_SYSIF_FAULT_CODE_MASK;
1116 code1 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO0_OFFSET);
1117 code2 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO1_OFFSET);
1118 code3 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO2_OFFSET);
1119 printf(IOCNAME "fault codes 0x%04x:0x%04x:0x%04x:0x%04x\n",
1120 sc->name, code, code1, code2, code3);
1121 }
1122 }
1123
mpi3mr_get_iocstate(struct mpi3mr_softc * sc)1124 enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_softc *sc)
1125 {
1126 U32 ioc_status, ioc_control;
1127 U8 ready, enabled;
1128
1129 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
1130 ioc_control = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
1131
1132 if(sc->unrecoverable)
1133 return MRIOC_STATE_UNRECOVERABLE;
1134 if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)
1135 return MRIOC_STATE_FAULT;
1136
1137 ready = (ioc_status & MPI3_SYSIF_IOC_STATUS_READY);
1138 enabled = (ioc_control & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC);
1139
1140 if (ready && enabled)
1141 return MRIOC_STATE_READY;
1142 if ((!ready) && (!enabled))
1143 return MRIOC_STATE_RESET;
1144 if ((!ready) && (enabled))
1145 return MRIOC_STATE_BECOMING_READY;
1146
1147 return MRIOC_STATE_RESET_REQUESTED;
1148 }
1149
mpi3mr_clear_reset_history(struct mpi3mr_softc * sc)1150 static inline void mpi3mr_clear_reset_history(struct mpi3mr_softc *sc)
1151 {
1152 U32 ioc_status;
1153
1154 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
1155 if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)
1156 mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_STATUS_OFFSET, ioc_status);
1157
1158 }
1159
1160 /**
1161 * mpi3mr_mur_ioc - Message unit Reset handler
1162 * @sc: Adapter instance reference
1163 * @reset_reason: Reset reason code
1164 *
1165 * Issue Message unit Reset to the controller and wait for it to
1166 * be complete.
1167 *
1168 * Return: 0 on success, -1 on failure.
1169 */
mpi3mr_mur_ioc(struct mpi3mr_softc * sc,U16 reset_reason)1170 static int mpi3mr_mur_ioc(struct mpi3mr_softc *sc, U16 reset_reason)
1171 {
1172 U32 ioc_config, timeout, ioc_status, scratch_pad0;
1173 int retval = -1;
1174
1175 mpi3mr_dprint(sc, MPI3MR_INFO, "Issuing Message Unit Reset(MUR)\n");
1176 if (sc->unrecoverable) {
1177 mpi3mr_dprint(sc, MPI3MR_ERROR, "IOC is unrecoverable MUR not issued\n");
1178 return retval;
1179 }
1180 mpi3mr_clear_reset_history(sc);
1181
1182 scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_FREEBSD <<
1183 MPI3MR_RESET_REASON_OSTYPE_SHIFT) |
1184 (sc->facts.ioc_num <<
1185 MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason);
1186 mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, scratch_pad0);
1187 ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
1188 ioc_config &= ~MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC;
1189 mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
1190
1191 timeout = MPI3MR_MUR_TIMEOUT * 10;
1192 do {
1193 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
1194 if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)) {
1195 mpi3mr_clear_reset_history(sc);
1196 ioc_config =
1197 mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
1198 if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) ||
1199 (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) ||
1200 (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) {
1201 retval = 0;
1202 break;
1203 }
1204 }
1205 DELAY(100 * 1000);
1206 } while (--timeout);
1207
1208 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
1209 ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
1210
1211 mpi3mr_dprint(sc, MPI3MR_INFO, "IOC Status/Config after %s MUR is (0x%x)/(0x%x)\n",
1212 !retval ? "successful":"failed", ioc_status, ioc_config);
1213 return retval;
1214 }
1215
1216 /**
1217 * mpi3mr_bring_ioc_ready - Bring controller to ready state
1218 * @sc: Adapter instance reference
1219 *
1220 * Set Enable IOC bit in IOC configuration register and wait for
1221 * the controller to become ready.
1222 *
1223 * Return: 0 on success, appropriate error on failure.
1224 */
mpi3mr_bring_ioc_ready(struct mpi3mr_softc * sc,U64 * start_time)1225 static int mpi3mr_bring_ioc_ready(struct mpi3mr_softc *sc,
1226 U64 *start_time)
1227 {
1228 enum mpi3mr_iocstate current_state;
1229 U32 ioc_status;
1230 int retval;
1231
1232 U32 ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
1233 ioc_config |= MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC;
1234 mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
1235
1236 if (*start_time == 0)
1237 *start_time = ticks;
1238
1239 do {
1240 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
1241 if (ioc_status & (MPI3_SYSIF_IOC_STATUS_FAULT | MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)) {
1242 if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) {
1243 mpi3mr_print_fault_info(sc);
1244 retval = mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, MPI3MR_RESET_FROM_BRINGUP);
1245 if (retval) {
1246 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Failed to soft reset the IOC, error 0x%d\n", __func__, retval);
1247 return -1;
1248 }
1249 }
1250 mpi3mr_clear_reset_history(sc);
1251 return EAGAIN;
1252 }
1253
1254 current_state = mpi3mr_get_iocstate(sc);
1255 if (current_state == MRIOC_STATE_READY)
1256 return 0;
1257
1258 DELAY(100 * 1000);
1259
1260 } while (((ticks - *start_time) / hz) < sc->ready_timeout);
1261
1262 return -1;
1263 }
1264
1265 static const struct {
1266 enum mpi3mr_iocstate value;
1267 char *name;
1268 } mrioc_states[] = {
1269 { MRIOC_STATE_READY, "ready" },
1270 { MRIOC_STATE_FAULT, "fault" },
1271 { MRIOC_STATE_RESET, "reset" },
1272 { MRIOC_STATE_BECOMING_READY, "becoming ready" },
1273 { MRIOC_STATE_RESET_REQUESTED, "reset requested" },
1274 { MRIOC_STATE_COUNT, "Count" },
1275 };
1276
mpi3mr_iocstate_name(enum mpi3mr_iocstate mrioc_state)1277 static const char *mpi3mr_iocstate_name(enum mpi3mr_iocstate mrioc_state)
1278 {
1279 int i;
1280 char *name = NULL;
1281
1282 for (i = 0; i < MRIOC_STATE_COUNT; i++) {
1283 if (mrioc_states[i].value == mrioc_state){
1284 name = mrioc_states[i].name;
1285 break;
1286 }
1287 }
1288 return name;
1289 }
1290
1291 /* Reset reason to name mapper structure*/
1292 static const struct {
1293 enum mpi3mr_reset_reason value;
1294 char *name;
1295 } mpi3mr_reset_reason_codes[] = {
1296 { MPI3MR_RESET_FROM_BRINGUP, "timeout in bringup" },
1297 { MPI3MR_RESET_FROM_FAULT_WATCH, "fault" },
1298 { MPI3MR_RESET_FROM_IOCTL, "application" },
1299 { MPI3MR_RESET_FROM_EH_HOS, "error handling" },
1300 { MPI3MR_RESET_FROM_TM_TIMEOUT, "TM timeout" },
1301 { MPI3MR_RESET_FROM_IOCTL_TIMEOUT, "IOCTL timeout" },
1302 { MPI3MR_RESET_FROM_SCSIIO_TIMEOUT, "SCSIIO timeout" },
1303 { MPI3MR_RESET_FROM_MUR_FAILURE, "MUR failure" },
1304 { MPI3MR_RESET_FROM_CTLR_CLEANUP, "timeout in controller cleanup" },
1305 { MPI3MR_RESET_FROM_CIACTIV_FAULT, "component image activation fault" },
1306 { MPI3MR_RESET_FROM_PE_TIMEOUT, "port enable timeout" },
1307 { MPI3MR_RESET_FROM_TSU_TIMEOUT, "time stamp update timeout" },
1308 { MPI3MR_RESET_FROM_DELREQQ_TIMEOUT, "delete request queue timeout" },
1309 { MPI3MR_RESET_FROM_DELREPQ_TIMEOUT, "delete reply queue timeout" },
1310 {
1311 MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT,
1312 "create request queue timeout"
1313 },
1314 {
1315 MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT,
1316 "create reply queue timeout"
1317 },
1318 { MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT, "IOC facts timeout" },
1319 { MPI3MR_RESET_FROM_IOCINIT_TIMEOUT, "IOC init timeout" },
1320 { MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT, "event notify timeout" },
1321 { MPI3MR_RESET_FROM_EVTACK_TIMEOUT, "event acknowledgment timeout" },
1322 {
1323 MPI3MR_RESET_FROM_CIACTVRST_TIMER,
1324 "component image activation timeout"
1325 },
1326 {
1327 MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT,
1328 "get package version timeout"
1329 },
1330 {
1331 MPI3MR_RESET_FROM_PELABORT_TIMEOUT,
1332 "persistent event log abort timeout"
1333 },
1334 { MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" },
1335 { MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" },
1336 {
1337 MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT,
1338 "diagnostic buffer post timeout"
1339 },
1340 { MPI3MR_RESET_FROM_FIRMWARE, "firmware asynchronus reset" },
1341 { MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT, "configuration request timeout" },
1342 { MPI3MR_RESET_REASON_COUNT, "Reset reason count" },
1343 };
1344
1345 /**
1346 * mpi3mr_reset_rc_name - get reset reason code name
1347 * @reason_code: reset reason code value
1348 *
1349 * Map reset reason to an NULL terminated ASCII string
1350 *
1351 * Return: Name corresponding to reset reason value or NULL.
1352 */
mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code)1353 static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code)
1354 {
1355 int i;
1356 char *name = NULL;
1357
1358 for (i = 0; i < MPI3MR_RESET_REASON_COUNT; i++) {
1359 if (mpi3mr_reset_reason_codes[i].value == reason_code) {
1360 name = mpi3mr_reset_reason_codes[i].name;
1361 break;
1362 }
1363 }
1364 return name;
1365 }
1366
1367 #define MAX_RESET_TYPE 3
1368 /* Reset type to name mapper structure*/
1369 static const struct {
1370 U16 reset_type;
1371 char *name;
1372 } mpi3mr_reset_types[] = {
1373 { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, "soft" },
1374 { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, "diag fault" },
1375 { MAX_RESET_TYPE, "count"}
1376 };
1377
1378 /**
1379 * mpi3mr_reset_type_name - get reset type name
1380 * @reset_type: reset type value
1381 *
1382 * Map reset type to an NULL terminated ASCII string
1383 *
1384 * Return: Name corresponding to reset type value or NULL.
1385 */
mpi3mr_reset_type_name(U16 reset_type)1386 static const char *mpi3mr_reset_type_name(U16 reset_type)
1387 {
1388 int i;
1389 char *name = NULL;
1390
1391 for (i = 0; i < MAX_RESET_TYPE; i++) {
1392 if (mpi3mr_reset_types[i].reset_type == reset_type) {
1393 name = mpi3mr_reset_types[i].name;
1394 break;
1395 }
1396 }
1397 return name;
1398 }
1399
1400 /**
1401 * mpi3mr_soft_reset_success - Check softreset is success or not
1402 * @ioc_status: IOC status register value
1403 * @ioc_config: IOC config register value
1404 *
1405 * Check whether the soft reset is successful or not based on
1406 * IOC status and IOC config register values.
1407 *
1408 * Return: True when the soft reset is success, false otherwise.
1409 */
1410 static inline bool
mpi3mr_soft_reset_success(U32 ioc_status,U32 ioc_config)1411 mpi3mr_soft_reset_success(U32 ioc_status, U32 ioc_config)
1412 {
1413 if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) ||
1414 (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) ||
1415 (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC)))
1416 return true;
1417 return false;
1418 }
1419
1420 /**
1421 * mpi3mr_diagfault_success - Check diag fault is success or not
1422 * @sc: Adapter reference
1423 * @ioc_status: IOC status register value
1424 *
1425 * Check whether the controller hit diag reset fault code.
1426 *
1427 * Return: True when there is diag fault, false otherwise.
1428 */
mpi3mr_diagfault_success(struct mpi3mr_softc * sc,U32 ioc_status)1429 static inline bool mpi3mr_diagfault_success(struct mpi3mr_softc *sc,
1430 U32 ioc_status)
1431 {
1432 if (!(ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT))
1433 return false;
1434 mpi3mr_print_fault_info(sc);
1435 return true;
1436 }
1437
1438 /**
1439 * mpi3mr_issue_iocfacts - Send IOC Facts
1440 * @sc: Adapter instance reference
1441 * @facts_data: Cached IOC facts data
1442 *
1443 * Issue IOC Facts MPI request through admin queue and wait for
1444 * the completion of it or time out.
1445 *
1446 * Return: 0 on success, non-zero on failures.
1447 */
mpi3mr_issue_iocfacts(struct mpi3mr_softc * sc,Mpi3IOCFactsData_t * facts_data)1448 static int mpi3mr_issue_iocfacts(struct mpi3mr_softc *sc,
1449 Mpi3IOCFactsData_t *facts_data)
1450 {
1451 Mpi3IOCFactsRequest_t iocfacts_req;
1452 bus_dma_tag_t data_tag = NULL;
1453 bus_dmamap_t data_map = NULL;
1454 bus_addr_t data_phys = 0;
1455 void *data = NULL;
1456 U32 data_len = sizeof(*facts_data);
1457 int retval = 0;
1458
1459 U8 sgl_flags = (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE |
1460 MPI3_SGE_FLAGS_DLAS_SYSTEM |
1461 MPI3_SGE_FLAGS_END_OF_LIST);
1462
1463
1464 /*
1465 * We can't use sc->dma_loaddr here. We set those only after we get the
1466 * iocfacts. So allocate in the lower 4GB. The amount of data is tiny
1467 * and we don't do this that often, so any bouncing we might have to do
1468 * isn't a cause for concern.
1469 */
1470 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
1471 4, 0, /* algnmnt, boundary */
1472 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
1473 BUS_SPACE_MAXADDR, /* highaddr */
1474 NULL, NULL, /* filter, filterarg */
1475 data_len, /* maxsize */
1476 1, /* nsegments */
1477 data_len, /* maxsegsize */
1478 0, /* flags */
1479 NULL, NULL, /* lockfunc, lockarg */
1480 &data_tag)) {
1481 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
1482 return (ENOMEM);
1483 }
1484
1485 if (bus_dmamem_alloc(data_tag, (void **)&data,
1486 BUS_DMA_NOWAIT, &data_map)) {
1487 mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d Data DMA mem alloc failed\n",
1488 __func__, __LINE__);
1489 return (ENOMEM);
1490 }
1491
1492 bzero(data, data_len);
1493 bus_dmamap_load(data_tag, data_map, data, data_len,
1494 mpi3mr_memaddr_cb, &data_phys, BUS_DMA_NOWAIT);
1495 mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d IOCfacts data phys addr= %#016jx size= %d\n",
1496 __func__, __LINE__, (uintmax_t)data_phys, data_len);
1497
1498 if (!data)
1499 {
1500 retval = -1;
1501 printf(IOCNAME "Memory alloc for IOCFactsData: failed\n",
1502 sc->name);
1503 goto out;
1504 }
1505
1506 mtx_lock(&sc->init_cmds.completion.lock);
1507 memset(&iocfacts_req, 0, sizeof(iocfacts_req));
1508
1509 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
1510 retval = -1;
1511 printf(IOCNAME "Issue IOCFacts: Init command is in use\n",
1512 sc->name);
1513 mtx_unlock(&sc->init_cmds.completion.lock);
1514 goto out;
1515 }
1516
1517 sc->init_cmds.state = MPI3MR_CMD_PENDING;
1518 sc->init_cmds.is_waiting = 1;
1519 sc->init_cmds.callback = NULL;
1520 iocfacts_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS);
1521 iocfacts_req.Function = MPI3_FUNCTION_IOC_FACTS;
1522
1523 mpi3mr_add_sg_single(&iocfacts_req.SGL, sgl_flags, data_len,
1524 data_phys);
1525
1526 init_completion(&sc->init_cmds.completion);
1527
1528 retval = mpi3mr_submit_admin_cmd(sc, &iocfacts_req,
1529 sizeof(iocfacts_req));
1530
1531 if (retval) {
1532 printf(IOCNAME "Issue IOCFacts: Admin Post failed\n",
1533 sc->name);
1534 goto out_unlock;
1535 }
1536
1537 wait_for_completion_timeout(&sc->init_cmds.completion,
1538 (MPI3MR_INTADMCMD_TIMEOUT));
1539 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
1540 printf(IOCNAME "Issue IOCFacts: command timed out\n",
1541 sc->name);
1542 mpi3mr_check_rh_fault_ioc(sc,
1543 MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT);
1544 sc->unrecoverable = 1;
1545 retval = -1;
1546 goto out_unlock;
1547 }
1548
1549 if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
1550 != MPI3_IOCSTATUS_SUCCESS ) {
1551 printf(IOCNAME "Issue IOCFacts: Failed IOCStatus(0x%04x) "
1552 " Loginfo(0x%08x) \n" , sc->name,
1553 (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
1554 sc->init_cmds.ioc_loginfo);
1555 retval = -1;
1556 goto out_unlock;
1557 }
1558
1559 memcpy(facts_data, (U8 *)data, data_len);
1560 out_unlock:
1561 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
1562 mtx_unlock(&sc->init_cmds.completion.lock);
1563
1564 out:
1565 if (data_phys != 0)
1566 bus_dmamap_unload(data_tag, data_map);
1567 if (data != NULL)
1568 bus_dmamem_free(data_tag, data, data_map);
1569 if (data_tag != NULL)
1570 bus_dma_tag_destroy(data_tag);
1571 return retval;
1572 }
1573
1574 /**
1575 * mpi3mr_process_factsdata - Process IOC facts data
1576 * @sc: Adapter instance reference
1577 * @facts_data: Cached IOC facts data
1578 *
1579 * Convert IOC facts data into cpu endianness and cache it in
1580 * the driver .
1581 *
1582 * Return: Nothing.
1583 */
mpi3mr_process_factsdata(struct mpi3mr_softc * sc,Mpi3IOCFactsData_t * facts_data)1584 static int mpi3mr_process_factsdata(struct mpi3mr_softc *sc,
1585 Mpi3IOCFactsData_t *facts_data)
1586 {
1587 int retval = 0;
1588 U32 ioc_config, req_sz, facts_flags;
1589 struct mpi3mr_compimg_ver *fwver;
1590
1591 if (le16toh(facts_data->IOCFactsDataLength) !=
1592 (sizeof(*facts_data) / 4)) {
1593 mpi3mr_dprint(sc, MPI3MR_INFO, "IOCFacts data length mismatch "
1594 " driver_sz(%ld) firmware_sz(%d) \n",
1595 sizeof(*facts_data),
1596 facts_data->IOCFactsDataLength);
1597 }
1598
1599 ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
1600 req_sz = 1 << ((ioc_config & MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ) >>
1601 MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ_SHIFT);
1602
1603 if (facts_data->IOCRequestFrameSize != (req_sz/4)) {
1604 mpi3mr_dprint(sc, MPI3MR_INFO, "IOCFacts data reqFrameSize mismatch "
1605 " hw_size(%d) firmware_sz(%d) \n" , req_sz/4,
1606 facts_data->IOCRequestFrameSize);
1607 }
1608
1609 memset(&sc->facts, 0, sizeof(sc->facts));
1610
1611 facts_flags = le32toh(facts_data->Flags);
1612 sc->facts.op_req_sz = req_sz;
1613 sc->op_reply_sz = 1 << ((ioc_config &
1614 MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ) >>
1615 MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ_SHIFT);
1616
1617 sc->facts.ioc_num = facts_data->IOCNumber;
1618 sc->facts.who_init = facts_data->WhoInit;
1619 sc->facts.max_msix_vectors = facts_data->MaxMSIxVectors;
1620 sc->facts.personality = (facts_flags &
1621 MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK);
1622 sc->facts.dma_mask = (facts_flags &
1623 MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >>
1624 MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT;
1625 sc->facts.protocol_flags = facts_data->ProtocolFlags;
1626 sc->facts.mpi_version = (facts_data->MPIVersion.Word);
1627 sc->facts.max_reqs = (facts_data->MaxOutstandingRequests);
1628 sc->facts.product_id = (facts_data->ProductID);
1629 sc->facts.reply_sz = (facts_data->ReplyFrameSize) * 4;
1630 sc->facts.exceptions = (facts_data->IOCExceptions);
1631 sc->facts.max_perids = (facts_data->MaxPersistentID);
1632 sc->facts.max_vds = (facts_data->MaxVDs);
1633 sc->facts.max_hpds = (facts_data->MaxHostPDs);
1634 sc->facts.max_advhpds = (facts_data->MaxAdvHostPDs);
1635 sc->facts.max_raidpds = (facts_data->MaxRAIDPDs);
1636 sc->facts.max_nvme = (facts_data->MaxNVMe);
1637 sc->facts.max_pcieswitches =
1638 (facts_data->MaxPCIeSwitches);
1639 sc->facts.max_sasexpanders =
1640 (facts_data->MaxSASExpanders);
1641 sc->facts.max_data_length = facts_data->MaxDataLength;
1642 sc->facts.max_sasinitiators =
1643 (facts_data->MaxSASInitiators);
1644 sc->facts.max_enclosures = (facts_data->MaxEnclosures);
1645 sc->facts.min_devhandle = (facts_data->MinDevHandle);
1646 sc->facts.max_devhandle = (facts_data->MaxDevHandle);
1647 sc->facts.max_op_req_q =
1648 (facts_data->MaxOperationalRequestQueues);
1649 sc->facts.max_op_reply_q =
1650 (facts_data->MaxOperationalReplyQueues);
1651 sc->facts.ioc_capabilities =
1652 (facts_data->IOCCapabilities);
1653 sc->facts.fw_ver.build_num =
1654 (facts_data->FWVersion.BuildNum);
1655 sc->facts.fw_ver.cust_id =
1656 (facts_data->FWVersion.CustomerID);
1657 sc->facts.fw_ver.ph_minor = facts_data->FWVersion.PhaseMinor;
1658 sc->facts.fw_ver.ph_major = facts_data->FWVersion.PhaseMajor;
1659 sc->facts.fw_ver.gen_minor = facts_data->FWVersion.GenMinor;
1660 sc->facts.fw_ver.gen_major = facts_data->FWVersion.GenMajor;
1661 sc->max_msix_vectors = min(sc->max_msix_vectors,
1662 sc->facts.max_msix_vectors);
1663 sc->facts.sge_mod_mask = facts_data->SGEModifierMask;
1664 sc->facts.sge_mod_value = facts_data->SGEModifierValue;
1665 sc->facts.sge_mod_shift = facts_data->SGEModifierShift;
1666 sc->facts.shutdown_timeout =
1667 (facts_data->ShutdownTimeout);
1668 sc->facts.max_dev_per_tg = facts_data->MaxDevicesPerThrottleGroup;
1669 sc->facts.io_throttle_data_length =
1670 facts_data->IOThrottleDataLength;
1671 sc->facts.max_io_throttle_group =
1672 facts_data->MaxIOThrottleGroup;
1673 sc->facts.io_throttle_low = facts_data->IOThrottleLow;
1674 sc->facts.io_throttle_high = facts_data->IOThrottleHigh;
1675
1676 if (sc->facts.max_data_length == MPI3_IOCFACTS_MAX_DATA_LENGTH_NOT_REPORTED)
1677 sc->facts.max_data_length = MPI3MR_DEFAULT_MAX_IO_SIZE;
1678 else
1679 sc->facts.max_data_length *= MPI3MR_PAGE_SIZE_4K;
1680 /*Store in 512b block count*/
1681 if (sc->facts.io_throttle_data_length)
1682 sc->io_throttle_data_length =
1683 (sc->facts.io_throttle_data_length * 2 * 4);
1684 else
1685 /* set the length to 1MB + 1K to disable throttle*/
1686 sc->io_throttle_data_length = MPI3MR_MAX_SECTORS + 2;
1687
1688 sc->io_throttle_high = (sc->facts.io_throttle_high * 2 * 1024);
1689 sc->io_throttle_low = (sc->facts.io_throttle_low * 2 * 1024);
1690
1691 fwver = &sc->facts.fw_ver;
1692 snprintf(sc->fw_version, sizeof(sc->fw_version),
1693 "%d.%d.%d.%d.%05d-%05d",
1694 fwver->gen_major, fwver->gen_minor, fwver->ph_major,
1695 fwver->ph_minor, fwver->cust_id, fwver->build_num);
1696
1697 mpi3mr_dprint(sc, MPI3MR_INFO, "ioc_num(%d), maxopQ(%d), maxopRepQ(%d), maxdh(%d),"
1698 "maxreqs(%d), mindh(%d) maxPDs(%d) maxvectors(%d) maxperids(%d)\n",
1699 sc->facts.ioc_num, sc->facts.max_op_req_q,
1700 sc->facts.max_op_reply_q, sc->facts.max_devhandle,
1701 sc->facts.max_reqs, sc->facts.min_devhandle,
1702 sc->facts.max_pds, sc->facts.max_msix_vectors,
1703 sc->facts.max_perids);
1704 mpi3mr_dprint(sc, MPI3MR_INFO, "SGEModMask 0x%x SGEModVal 0x%x SGEModShift 0x%x\n",
1705 sc->facts.sge_mod_mask, sc->facts.sge_mod_value,
1706 sc->facts.sge_mod_shift);
1707 mpi3mr_dprint(sc, MPI3MR_INFO,
1708 "max_dev_per_throttle_group(%d), max_throttle_groups(%d), io_throttle_data_len(%dKiB), io_throttle_high(%dMiB), io_throttle_low(%dMiB)\n",
1709 sc->facts.max_dev_per_tg, sc->facts.max_io_throttle_group,
1710 sc->facts.io_throttle_data_length * 4,
1711 sc->facts.io_throttle_high, sc->facts.io_throttle_low);
1712
1713 sc->max_host_ios = sc->facts.max_reqs -
1714 (MPI3MR_INTERNALCMDS_RESVD + 1);
1715
1716 /*
1717 * Set the DMA mask for the card. dma_mask is the number of bits that
1718 * can have bits set in them. Translate this into bus_dma loaddr args.
1719 * Add sanity for more bits than address space or other overflow
1720 * situations.
1721 */
1722 if (sc->facts.dma_mask == 0 ||
1723 (sc->facts.dma_mask >= sizeof(bus_addr_t) * 8))
1724 sc->dma_loaddr = BUS_SPACE_MAXADDR;
1725 else
1726 sc->dma_loaddr = ~((1ull << sc->facts.dma_mask) - 1);
1727 mpi3mr_dprint(sc, MPI3MR_INFO,
1728 "dma_mask bits: %d loaddr 0x%jx\n",
1729 sc->facts.dma_mask, sc->dma_loaddr);
1730
1731 return retval;
1732 }
1733
mpi3mr_setup_reply_free_queues(struct mpi3mr_softc * sc)1734 static inline void mpi3mr_setup_reply_free_queues(struct mpi3mr_softc *sc)
1735 {
1736 int i;
1737 bus_addr_t phys_addr;
1738
1739 /* initialize Reply buffer Queue */
1740 for (i = 0, phys_addr = sc->reply_buf_phys;
1741 i < sc->num_reply_bufs; i++, phys_addr += sc->reply_sz)
1742 sc->reply_free_q[i] = phys_addr;
1743 sc->reply_free_q[i] = (0);
1744
1745 /* initialize Sense Buffer Queue */
1746 for (i = 0, phys_addr = sc->sense_buf_phys;
1747 i < sc->num_sense_bufs; i++, phys_addr += MPI3MR_SENSEBUF_SZ)
1748 sc->sense_buf_q[i] = phys_addr;
1749 sc->sense_buf_q[i] = (0);
1750
1751 }
1752
mpi3mr_reply_dma_alloc(struct mpi3mr_softc * sc)1753 static int mpi3mr_reply_dma_alloc(struct mpi3mr_softc *sc)
1754 {
1755 U32 sz;
1756
1757 sc->num_reply_bufs = sc->facts.max_reqs + MPI3MR_NUM_EVTREPLIES;
1758 sc->reply_free_q_sz = sc->num_reply_bufs + 1;
1759 sc->num_sense_bufs = sc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR;
1760 sc->sense_buf_q_sz = sc->num_sense_bufs + 1;
1761
1762 sz = sc->num_reply_bufs * sc->reply_sz;
1763
1764 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
1765 16, 0, /* algnmnt, boundary */
1766 sc->dma_loaddr, /* lowaddr */
1767 BUS_SPACE_MAXADDR, /* highaddr */
1768 NULL, NULL, /* filter, filterarg */
1769 sz, /* maxsize */
1770 1, /* nsegments */
1771 sz, /* maxsegsize */
1772 0, /* flags */
1773 NULL, NULL, /* lockfunc, lockarg */
1774 &sc->reply_buf_tag)) {
1775 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
1776 return (ENOMEM);
1777 }
1778
1779 if (bus_dmamem_alloc(sc->reply_buf_tag, (void **)&sc->reply_buf,
1780 BUS_DMA_NOWAIT, &sc->reply_buf_dmamap)) {
1781 mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n",
1782 __func__, __LINE__);
1783 return (ENOMEM);
1784 }
1785
1786 bzero(sc->reply_buf, sz);
1787 bus_dmamap_load(sc->reply_buf_tag, sc->reply_buf_dmamap, sc->reply_buf, sz,
1788 mpi3mr_memaddr_cb, &sc->reply_buf_phys, BUS_DMA_NOWAIT);
1789
1790 sc->reply_buf_dma_min_address = sc->reply_buf_phys;
1791 sc->reply_buf_dma_max_address = sc->reply_buf_phys + sz;
1792 mpi3mr_dprint(sc, MPI3MR_XINFO, "reply buf (0x%p): depth(%d), frame_size(%d), "
1793 "pool_size(%d kB), reply_buf_dma(0x%llx)\n",
1794 sc->reply_buf, sc->num_reply_bufs, sc->reply_sz,
1795 (sz / 1024), (unsigned long long)sc->reply_buf_phys);
1796
1797 /* reply free queue, 8 byte align */
1798 sz = sc->reply_free_q_sz * 8;
1799
1800 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
1801 8, 0, /* algnmnt, boundary */
1802 sc->dma_loaddr, /* lowaddr */
1803 BUS_SPACE_MAXADDR, /* highaddr */
1804 NULL, NULL, /* filter, filterarg */
1805 sz, /* maxsize */
1806 1, /* nsegments */
1807 sz, /* maxsegsize */
1808 0, /* flags */
1809 NULL, NULL, /* lockfunc, lockarg */
1810 &sc->reply_free_q_tag)) {
1811 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate reply free queue DMA tag\n");
1812 return (ENOMEM);
1813 }
1814
1815 if (bus_dmamem_alloc(sc->reply_free_q_tag, (void **)&sc->reply_free_q,
1816 BUS_DMA_NOWAIT, &sc->reply_free_q_dmamap)) {
1817 mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n",
1818 __func__, __LINE__);
1819 return (ENOMEM);
1820 }
1821
1822 bzero(sc->reply_free_q, sz);
1823 bus_dmamap_load(sc->reply_free_q_tag, sc->reply_free_q_dmamap, sc->reply_free_q, sz,
1824 mpi3mr_memaddr_cb, &sc->reply_free_q_phys, BUS_DMA_NOWAIT);
1825
1826 mpi3mr_dprint(sc, MPI3MR_XINFO, "reply_free_q (0x%p): depth(%d), frame_size(%d), "
1827 "pool_size(%d kB), reply_free_q_dma(0x%llx)\n",
1828 sc->reply_free_q, sc->reply_free_q_sz, 8, (sz / 1024),
1829 (unsigned long long)sc->reply_free_q_phys);
1830
1831 /* sense buffer pool, 4 byte align */
1832 sz = sc->num_sense_bufs * MPI3MR_SENSEBUF_SZ;
1833
1834 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
1835 4, 0, /* algnmnt, boundary */
1836 sc->dma_loaddr, /* lowaddr */
1837 BUS_SPACE_MAXADDR, /* highaddr */
1838 NULL, NULL, /* filter, filterarg */
1839 sz, /* maxsize */
1840 1, /* nsegments */
1841 sz, /* maxsegsize */
1842 0, /* flags */
1843 NULL, NULL, /* lockfunc, lockarg */
1844 &sc->sense_buf_tag)) {
1845 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Sense buffer DMA tag\n");
1846 return (ENOMEM);
1847 }
1848
1849 if (bus_dmamem_alloc(sc->sense_buf_tag, (void **)&sc->sense_buf,
1850 BUS_DMA_NOWAIT, &sc->sense_buf_dmamap)) {
1851 mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n",
1852 __func__, __LINE__);
1853 return (ENOMEM);
1854 }
1855
1856 bzero(sc->sense_buf, sz);
1857 bus_dmamap_load(sc->sense_buf_tag, sc->sense_buf_dmamap, sc->sense_buf, sz,
1858 mpi3mr_memaddr_cb, &sc->sense_buf_phys, BUS_DMA_NOWAIT);
1859
1860 mpi3mr_dprint(sc, MPI3MR_XINFO, "sense_buf (0x%p): depth(%d), frame_size(%d), "
1861 "pool_size(%d kB), sense_dma(0x%llx)\n",
1862 sc->sense_buf, sc->num_sense_bufs, MPI3MR_SENSEBUF_SZ,
1863 (sz / 1024), (unsigned long long)sc->sense_buf_phys);
1864
1865 /* sense buffer queue, 8 byte align */
1866 sz = sc->sense_buf_q_sz * 8;
1867
1868 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
1869 8, 0, /* algnmnt, boundary */
1870 sc->dma_loaddr, /* lowaddr */
1871 BUS_SPACE_MAXADDR, /* highaddr */
1872 NULL, NULL, /* filter, filterarg */
1873 sz, /* maxsize */
1874 1, /* nsegments */
1875 sz, /* maxsegsize */
1876 0, /* flags */
1877 NULL, NULL, /* lockfunc, lockarg */
1878 &sc->sense_buf_q_tag)) {
1879 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Sense buffer Queue DMA tag\n");
1880 return (ENOMEM);
1881 }
1882
1883 if (bus_dmamem_alloc(sc->sense_buf_q_tag, (void **)&sc->sense_buf_q,
1884 BUS_DMA_NOWAIT, &sc->sense_buf_q_dmamap)) {
1885 mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n",
1886 __func__, __LINE__);
1887 return (ENOMEM);
1888 }
1889
1890 bzero(sc->sense_buf_q, sz);
1891 bus_dmamap_load(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap, sc->sense_buf_q, sz,
1892 mpi3mr_memaddr_cb, &sc->sense_buf_q_phys, BUS_DMA_NOWAIT);
1893
1894 mpi3mr_dprint(sc, MPI3MR_XINFO, "sense_buf_q (0x%p): depth(%d), frame_size(%d), "
1895 "pool_size(%d kB), sense_dma(0x%llx)\n",
1896 sc->sense_buf_q, sc->sense_buf_q_sz, 8, (sz / 1024),
1897 (unsigned long long)sc->sense_buf_q_phys);
1898
1899 return 0;
1900 }
1901
mpi3mr_reply_alloc(struct mpi3mr_softc * sc)1902 static int mpi3mr_reply_alloc(struct mpi3mr_softc *sc)
1903 {
1904 int retval = 0;
1905 U32 i;
1906
1907 if (sc->init_cmds.reply)
1908 goto post_reply_sbuf;
1909
1910 sc->init_cmds.reply = malloc(sc->reply_sz,
1911 M_MPI3MR, M_NOWAIT | M_ZERO);
1912
1913 if (!sc->init_cmds.reply) {
1914 printf(IOCNAME "Cannot allocate memory for init_cmds.reply\n",
1915 sc->name);
1916 goto out_failed;
1917 }
1918
1919 sc->cfg_cmds.reply = malloc(sc->reply_sz,
1920 M_MPI3MR, M_NOWAIT | M_ZERO);
1921
1922 if (!sc->cfg_cmds.reply) {
1923 printf(IOCNAME "Cannot allocate memory for cfg_cmds.reply\n",
1924 sc->name);
1925 goto out_failed;
1926 }
1927
1928 sc->ioctl_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
1929 if (!sc->ioctl_cmds.reply) {
1930 printf(IOCNAME "Cannot allocate memory for ioctl_cmds.reply\n",
1931 sc->name);
1932 goto out_failed;
1933 }
1934
1935 sc->host_tm_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
1936 if (!sc->host_tm_cmds.reply) {
1937 printf(IOCNAME "Cannot allocate memory for host_tm.reply\n",
1938 sc->name);
1939 goto out_failed;
1940 }
1941 for (i=0; i<MPI3MR_NUM_DEVRMCMD; i++) {
1942 sc->dev_rmhs_cmds[i].reply = malloc(sc->reply_sz,
1943 M_MPI3MR, M_NOWAIT | M_ZERO);
1944 if (!sc->dev_rmhs_cmds[i].reply) {
1945 printf(IOCNAME "Cannot allocate memory for"
1946 " dev_rmhs_cmd[%d].reply\n",
1947 sc->name, i);
1948 goto out_failed;
1949 }
1950 }
1951
1952 for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) {
1953 sc->evtack_cmds[i].reply = malloc(sc->reply_sz,
1954 M_MPI3MR, M_NOWAIT | M_ZERO);
1955 if (!sc->evtack_cmds[i].reply)
1956 goto out_failed;
1957 }
1958
1959 sc->dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8);
1960
1961 sc->removepend_bitmap = malloc(sc->dev_handle_bitmap_sz,
1962 M_MPI3MR, M_NOWAIT | M_ZERO);
1963 if (!sc->removepend_bitmap) {
1964 printf(IOCNAME "Cannot alloc memory for remove pend bitmap\n",
1965 sc->name);
1966 goto out_failed;
1967 }
1968
1969 sc->devrem_bitmap_sz = MPI3MR_DIV_ROUND_UP(MPI3MR_NUM_DEVRMCMD, 8);
1970 sc->devrem_bitmap = malloc(sc->devrem_bitmap_sz,
1971 M_MPI3MR, M_NOWAIT | M_ZERO);
1972 if (!sc->devrem_bitmap) {
1973 printf(IOCNAME "Cannot alloc memory for dev remove bitmap\n",
1974 sc->name);
1975 goto out_failed;
1976 }
1977
1978 sc->evtack_cmds_bitmap_sz = MPI3MR_DIV_ROUND_UP(MPI3MR_NUM_EVTACKCMD, 8);
1979
1980 sc->evtack_cmds_bitmap = malloc(sc->evtack_cmds_bitmap_sz,
1981 M_MPI3MR, M_NOWAIT | M_ZERO);
1982 if (!sc->evtack_cmds_bitmap)
1983 goto out_failed;
1984
1985 if (mpi3mr_reply_dma_alloc(sc)) {
1986 printf(IOCNAME "func:%s line:%d DMA memory allocation failed\n",
1987 sc->name, __func__, __LINE__);
1988 goto out_failed;
1989 }
1990
1991 post_reply_sbuf:
1992 mpi3mr_setup_reply_free_queues(sc);
1993 return retval;
1994 out_failed:
1995 mpi3mr_cleanup_interrupts(sc);
1996 mpi3mr_free_mem(sc);
1997 retval = -1;
1998 return retval;
1999 }
2000
2001 static void
mpi3mr_print_fw_pkg_ver(struct mpi3mr_softc * sc)2002 mpi3mr_print_fw_pkg_ver(struct mpi3mr_softc *sc)
2003 {
2004 int retval = 0;
2005 void *fw_pkg_ver = NULL;
2006 bus_dma_tag_t fw_pkg_ver_tag;
2007 bus_dmamap_t fw_pkg_ver_map;
2008 bus_addr_t fw_pkg_ver_dma;
2009 Mpi3CIUploadRequest_t ci_upload;
2010 Mpi3ComponentImageHeader_t *ci_header;
2011 U32 fw_pkg_ver_len = sizeof(*ci_header);
2012 U8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2013
2014 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
2015 4, 0, /* algnmnt, boundary */
2016 sc->dma_loaddr, /* lowaddr */
2017 BUS_SPACE_MAXADDR, /* highaddr */
2018 NULL, NULL, /* filter, filterarg */
2019 fw_pkg_ver_len, /* maxsize */
2020 1, /* nsegments */
2021 fw_pkg_ver_len, /* maxsegsize */
2022 0, /* flags */
2023 NULL, NULL, /* lockfunc, lockarg */
2024 &fw_pkg_ver_tag)) {
2025 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate fw package version request DMA tag\n");
2026 return;
2027 }
2028
2029 if (bus_dmamem_alloc(fw_pkg_ver_tag, (void **)&fw_pkg_ver, BUS_DMA_NOWAIT, &fw_pkg_ver_map)) {
2030 mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d fw package version DMA mem alloc failed\n",
2031 __func__, __LINE__);
2032 return;
2033 }
2034
2035 bzero(fw_pkg_ver, fw_pkg_ver_len);
2036
2037 bus_dmamap_load(fw_pkg_ver_tag, fw_pkg_ver_map, fw_pkg_ver, fw_pkg_ver_len,
2038 mpi3mr_memaddr_cb, &fw_pkg_ver_dma, BUS_DMA_NOWAIT);
2039
2040 mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d fw package version phys addr= %#016jx size= %d\n",
2041 __func__, __LINE__, (uintmax_t)fw_pkg_ver_dma, fw_pkg_ver_len);
2042
2043 if (!fw_pkg_ver) {
2044 mpi3mr_dprint(sc, MPI3MR_ERROR, "Memory alloc for fw package version failed\n");
2045 goto out;
2046 }
2047
2048 memset(&ci_upload, 0, sizeof(ci_upload));
2049 mtx_lock(&sc->init_cmds.completion.lock);
2050 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
2051 mpi3mr_dprint(sc, MPI3MR_INFO,"Issue CI Header Upload: command is in use\n");
2052 mtx_unlock(&sc->init_cmds.completion.lock);
2053 goto out;
2054 }
2055 sc->init_cmds.state = MPI3MR_CMD_PENDING;
2056 sc->init_cmds.is_waiting = 1;
2057 sc->init_cmds.callback = NULL;
2058 ci_upload.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS);
2059 ci_upload.Function = MPI3_FUNCTION_CI_UPLOAD;
2060 ci_upload.MsgFlags = MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_PRIMARY;
2061 ci_upload.ImageOffset = MPI3_IMAGE_HEADER_SIGNATURE0_OFFSET;
2062 ci_upload.SegmentSize = MPI3_IMAGE_HEADER_SIZE;
2063
2064 mpi3mr_add_sg_single(&ci_upload.SGL, sgl_flags, fw_pkg_ver_len,
2065 fw_pkg_ver_dma);
2066
2067 init_completion(&sc->init_cmds.completion);
2068 if ((retval = mpi3mr_submit_admin_cmd(sc, &ci_upload, sizeof(ci_upload)))) {
2069 mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: Admin Post failed\n");
2070 goto out_unlock;
2071 }
2072 wait_for_completion_timeout(&sc->init_cmds.completion,
2073 (MPI3MR_INTADMCMD_TIMEOUT));
2074 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
2075 mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: command timed out\n");
2076 sc->init_cmds.is_waiting = 0;
2077 if (!(sc->init_cmds.state & MPI3MR_CMD_RESET))
2078 mpi3mr_check_rh_fault_ioc(sc,
2079 MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT);
2080 goto out_unlock;
2081 }
2082 if ((GET_IOC_STATUS(sc->init_cmds.ioc_status)) != MPI3_IOCSTATUS_SUCCESS) {
2083 mpi3mr_dprint(sc, MPI3MR_ERROR,
2084 "Issue CI Header Upload: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n",
2085 GET_IOC_STATUS(sc->init_cmds.ioc_status), sc->init_cmds.ioc_loginfo);
2086 goto out_unlock;
2087 }
2088
2089 ci_header = (Mpi3ComponentImageHeader_t *) fw_pkg_ver;
2090 mpi3mr_dprint(sc, MPI3MR_XINFO,
2091 "Issue CI Header Upload:EnvVariableOffset(0x%x) \
2092 HeaderSize(0x%x) Signature1(0x%x)\n",
2093 ci_header->EnvironmentVariableOffset,
2094 ci_header->HeaderSize,
2095 ci_header->Signature1);
2096 mpi3mr_dprint(sc, MPI3MR_INFO, "FW Package Version: %02d.%02d.%02d.%02d\n",
2097 ci_header->ComponentImageVersion.GenMajor,
2098 ci_header->ComponentImageVersion.GenMinor,
2099 ci_header->ComponentImageVersion.PhaseMajor,
2100 ci_header->ComponentImageVersion.PhaseMinor);
2101 out_unlock:
2102 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
2103 mtx_unlock(&sc->init_cmds.completion.lock);
2104
2105 out:
2106 if (fw_pkg_ver_dma != 0)
2107 bus_dmamap_unload(fw_pkg_ver_tag, fw_pkg_ver_map);
2108 if (fw_pkg_ver)
2109 bus_dmamem_free(fw_pkg_ver_tag, fw_pkg_ver, fw_pkg_ver_map);
2110 if (fw_pkg_ver_tag)
2111 bus_dma_tag_destroy(fw_pkg_ver_tag);
2112
2113 }
2114
2115 /**
2116 * mpi3mr_issue_iocinit - Send IOC Init
2117 * @sc: Adapter instance reference
2118 *
2119 * Issue IOC Init MPI request through admin queue and wait for
2120 * the completion of it or time out.
2121 *
2122 * Return: 0 on success, non-zero on failures.
2123 */
mpi3mr_issue_iocinit(struct mpi3mr_softc * sc)2124 static int mpi3mr_issue_iocinit(struct mpi3mr_softc *sc)
2125 {
2126 Mpi3IOCInitRequest_t iocinit_req;
2127 Mpi3DriverInfoLayout_t *drvr_info = NULL;
2128 bus_dma_tag_t drvr_info_tag;
2129 bus_dmamap_t drvr_info_map;
2130 bus_addr_t drvr_info_phys;
2131 U32 drvr_info_len = sizeof(*drvr_info);
2132 int retval = 0;
2133 struct timeval now;
2134 uint64_t time_in_msec;
2135
2136 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
2137 4, 0, /* algnmnt, boundary */
2138 sc->dma_loaddr, /* lowaddr */
2139 BUS_SPACE_MAXADDR, /* highaddr */
2140 NULL, NULL, /* filter, filterarg */
2141 drvr_info_len, /* maxsize */
2142 1, /* nsegments */
2143 drvr_info_len, /* maxsegsize */
2144 0, /* flags */
2145 NULL, NULL, /* lockfunc, lockarg */
2146 &drvr_info_tag)) {
2147 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
2148 return (ENOMEM);
2149 }
2150
2151 if (bus_dmamem_alloc(drvr_info_tag, (void **)&drvr_info,
2152 BUS_DMA_NOWAIT, &drvr_info_map)) {
2153 mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d Data DMA mem alloc failed\n",
2154 __func__, __LINE__);
2155 return (ENOMEM);
2156 }
2157
2158 bzero(drvr_info, drvr_info_len);
2159 bus_dmamap_load(drvr_info_tag, drvr_info_map, drvr_info, drvr_info_len,
2160 mpi3mr_memaddr_cb, &drvr_info_phys, BUS_DMA_NOWAIT);
2161 mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d IOCfacts drvr_info phys addr= %#016jx size= %d\n",
2162 __func__, __LINE__, (uintmax_t)drvr_info_phys, drvr_info_len);
2163
2164 if (!drvr_info)
2165 {
2166 retval = -1;
2167 printf(IOCNAME "Memory alloc for Driver Info failed\n",
2168 sc->name);
2169 goto out;
2170 }
2171 drvr_info->InformationLength = (drvr_info_len);
2172 strcpy(drvr_info->DriverSignature, "Broadcom");
2173 strcpy(drvr_info->OsName, "FreeBSD");
2174 strcpy(drvr_info->OsVersion, fmt_os_ver);
2175 strcpy(drvr_info->DriverName, MPI3MR_DRIVER_NAME);
2176 strcpy(drvr_info->DriverVersion, MPI3MR_DRIVER_VERSION);
2177 strcpy(drvr_info->DriverReleaseDate, MPI3MR_DRIVER_RELDATE);
2178 drvr_info->DriverCapabilities = MPI3_IOCINIT_DRIVERCAP_OSEXPOSURE_NO_SPECIAL;
2179 memcpy((U8 *)&sc->driver_info, (U8 *)drvr_info, sizeof(sc->driver_info));
2180
2181 memset(&iocinit_req, 0, sizeof(iocinit_req));
2182 mtx_lock(&sc->init_cmds.completion.lock);
2183 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
2184 retval = -1;
2185 printf(IOCNAME "Issue IOCInit: Init command is in use\n",
2186 sc->name);
2187 mtx_unlock(&sc->init_cmds.completion.lock);
2188 goto out;
2189 }
2190 sc->init_cmds.state = MPI3MR_CMD_PENDING;
2191 sc->init_cmds.is_waiting = 1;
2192 sc->init_cmds.callback = NULL;
2193 iocinit_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
2194 iocinit_req.Function = MPI3_FUNCTION_IOC_INIT;
2195 iocinit_req.MPIVersion.Struct.Dev = MPI3_VERSION_DEV;
2196 iocinit_req.MPIVersion.Struct.Unit = MPI3_VERSION_UNIT;
2197 iocinit_req.MPIVersion.Struct.Major = MPI3_VERSION_MAJOR;
2198 iocinit_req.MPIVersion.Struct.Minor = MPI3_VERSION_MINOR;
2199 iocinit_req.WhoInit = MPI3_WHOINIT_HOST_DRIVER;
2200 iocinit_req.ReplyFreeQueueDepth = sc->reply_free_q_sz;
2201 iocinit_req.ReplyFreeQueueAddress =
2202 sc->reply_free_q_phys;
2203 iocinit_req.SenseBufferLength = MPI3MR_SENSEBUF_SZ;
2204 iocinit_req.SenseBufferFreeQueueDepth =
2205 sc->sense_buf_q_sz;
2206 iocinit_req.SenseBufferFreeQueueAddress =
2207 sc->sense_buf_q_phys;
2208 iocinit_req.DriverInformationAddress = drvr_info_phys;
2209
2210 getmicrotime(&now);
2211 time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000);
2212 iocinit_req.TimeStamp = htole64(time_in_msec);
2213
2214 iocinit_req.MsgFlags |= MPI3_IOCINIT_MSGFLAGS_WRITESAMEDIVERT_SUPPORTED;
2215
2216 init_completion(&sc->init_cmds.completion);
2217 retval = mpi3mr_submit_admin_cmd(sc, &iocinit_req,
2218 sizeof(iocinit_req));
2219
2220 if (retval) {
2221 printf(IOCNAME "Issue IOCInit: Admin Post failed\n",
2222 sc->name);
2223 goto out_unlock;
2224 }
2225
2226 wait_for_completion_timeout(&sc->init_cmds.completion,
2227 (MPI3MR_INTADMCMD_TIMEOUT));
2228 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
2229 printf(IOCNAME "Issue IOCInit: command timed out\n",
2230 sc->name);
2231 mpi3mr_check_rh_fault_ioc(sc,
2232 MPI3MR_RESET_FROM_IOCINIT_TIMEOUT);
2233 sc->unrecoverable = 1;
2234 retval = -1;
2235 goto out_unlock;
2236 }
2237
2238 if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
2239 != MPI3_IOCSTATUS_SUCCESS ) {
2240 printf(IOCNAME "Issue IOCInit: Failed IOCStatus(0x%04x) "
2241 " Loginfo(0x%08x) \n" , sc->name,
2242 (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
2243 sc->init_cmds.ioc_loginfo);
2244 retval = -1;
2245 goto out_unlock;
2246 }
2247
2248 out_unlock:
2249 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
2250 mtx_unlock(&sc->init_cmds.completion.lock);
2251
2252 out:
2253 if (drvr_info_phys != 0)
2254 bus_dmamap_unload(drvr_info_tag, drvr_info_map);
2255 if (drvr_info != NULL)
2256 bus_dmamem_free(drvr_info_tag, drvr_info, drvr_info_map);
2257 if (drvr_info_tag != NULL)
2258 bus_dma_tag_destroy(drvr_info_tag);
2259 return retval;
2260 }
2261
2262 static void
mpi3mr_display_ioc_info(struct mpi3mr_softc * sc)2263 mpi3mr_display_ioc_info(struct mpi3mr_softc *sc)
2264 {
2265 int i = 0;
2266 char personality[16];
2267
2268 switch (sc->facts.personality) {
2269 case MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA:
2270 strcpy(personality, "Enhanced HBA");
2271 break;
2272 case MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR:
2273 strcpy(personality, "RAID");
2274 break;
2275 default:
2276 strcpy(personality, "Unknown");
2277 break;
2278 }
2279
2280 mpi3mr_dprint(sc, MPI3MR_INFO, "Current Personality: %s\n", personality);
2281
2282 mpi3mr_dprint(sc, MPI3MR_INFO, "%s\n", sc->fw_version);
2283
2284 mpi3mr_dprint(sc, MPI3MR_INFO, "Protocol=(");
2285
2286 if (sc->facts.protocol_flags &
2287 MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
2288 printf("Initiator");
2289 i++;
2290 }
2291
2292 if (sc->facts.protocol_flags &
2293 MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET) {
2294 printf("%sTarget", i ? "," : "");
2295 i++;
2296 }
2297
2298 if (sc->facts.protocol_flags &
2299 MPI3_IOCFACTS_PROTOCOL_NVME) {
2300 printf("%sNVMe attachment", i ? "," : "");
2301 i++;
2302 }
2303 i = 0;
2304 printf("), ");
2305 printf("Capabilities=(");
2306
2307 if (sc->facts.ioc_capabilities &
2308 MPI3_IOCFACTS_CAPABILITY_RAID_SUPPORTED) {
2309 printf("RAID");
2310 i++;
2311 }
2312
2313 printf(")\n");
2314 }
2315
2316 /**
2317 * mpi3mr_unmask_events - Unmask events in event mask bitmap
2318 * @sc: Adapter instance reference
2319 * @event: MPI event ID
2320 *
2321 * Un mask the specific event by resetting the event_mask
2322 * bitmap.
2323 *
2324 * Return: None.
2325 */
mpi3mr_unmask_events(struct mpi3mr_softc * sc,U16 event)2326 static void mpi3mr_unmask_events(struct mpi3mr_softc *sc, U16 event)
2327 {
2328 U32 desired_event;
2329
2330 if (event >= 128)
2331 return;
2332
2333 desired_event = (1 << (event % 32));
2334
2335 if (event < 32)
2336 sc->event_masks[0] &= ~desired_event;
2337 else if (event < 64)
2338 sc->event_masks[1] &= ~desired_event;
2339 else if (event < 96)
2340 sc->event_masks[2] &= ~desired_event;
2341 else if (event < 128)
2342 sc->event_masks[3] &= ~desired_event;
2343 }
2344
mpi3mr_set_events_mask(struct mpi3mr_softc * sc)2345 static void mpi3mr_set_events_mask(struct mpi3mr_softc *sc)
2346 {
2347 int i;
2348 for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
2349 sc->event_masks[i] = -1;
2350
2351 mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_ADDED);
2352 mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_INFO_CHANGED);
2353 mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_STATUS_CHANGE);
2354
2355 mpi3mr_unmask_events(sc, MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE);
2356
2357 mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
2358 mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DISCOVERY);
2359 mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR);
2360 mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_BROADCAST_PRIMITIVE);
2361
2362 mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST);
2363 mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_ENUMERATION);
2364
2365 mpi3mr_unmask_events(sc, MPI3_EVENT_PREPARE_FOR_RESET);
2366 mpi3mr_unmask_events(sc, MPI3_EVENT_CABLE_MGMT);
2367 mpi3mr_unmask_events(sc, MPI3_EVENT_ENERGY_PACK_CHANGE);
2368 }
2369
2370 /**
2371 * mpi3mr_issue_event_notification - Send event notification
2372 * @sc: Adapter instance reference
2373 *
2374 * Issue event notification MPI request through admin queue and
2375 * wait for the completion of it or time out.
2376 *
2377 * Return: 0 on success, non-zero on failures.
2378 */
mpi3mr_issue_event_notification(struct mpi3mr_softc * sc)2379 int mpi3mr_issue_event_notification(struct mpi3mr_softc *sc)
2380 {
2381 Mpi3EventNotificationRequest_t evtnotify_req;
2382 int retval = 0;
2383 U8 i;
2384
2385 memset(&evtnotify_req, 0, sizeof(evtnotify_req));
2386 mtx_lock(&sc->init_cmds.completion.lock);
2387 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
2388 retval = -1;
2389 printf(IOCNAME "Issue EvtNotify: Init command is in use\n",
2390 sc->name);
2391 mtx_unlock(&sc->init_cmds.completion.lock);
2392 goto out;
2393 }
2394 sc->init_cmds.state = MPI3MR_CMD_PENDING;
2395 sc->init_cmds.is_waiting = 1;
2396 sc->init_cmds.callback = NULL;
2397 evtnotify_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS);
2398 evtnotify_req.Function = MPI3_FUNCTION_EVENT_NOTIFICATION;
2399 for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
2400 evtnotify_req.EventMasks[i] =
2401 (sc->event_masks[i]);
2402 init_completion(&sc->init_cmds.completion);
2403 retval = mpi3mr_submit_admin_cmd(sc, &evtnotify_req,
2404 sizeof(evtnotify_req));
2405 if (retval) {
2406 printf(IOCNAME "Issue EvtNotify: Admin Post failed\n",
2407 sc->name);
2408 goto out_unlock;
2409 }
2410
2411 poll_for_command_completion(sc,
2412 &sc->init_cmds,
2413 (MPI3MR_INTADMCMD_TIMEOUT));
2414 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
2415 printf(IOCNAME "Issue EvtNotify: command timed out\n",
2416 sc->name);
2417 mpi3mr_check_rh_fault_ioc(sc,
2418 MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT);
2419 retval = -1;
2420 goto out_unlock;
2421 }
2422
2423 if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
2424 != MPI3_IOCSTATUS_SUCCESS ) {
2425 printf(IOCNAME "Issue EvtNotify: Failed IOCStatus(0x%04x) "
2426 " Loginfo(0x%08x) \n" , sc->name,
2427 (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
2428 sc->init_cmds.ioc_loginfo);
2429 retval = -1;
2430 goto out_unlock;
2431 }
2432
2433 out_unlock:
2434 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
2435 mtx_unlock(&sc->init_cmds.completion.lock);
2436
2437 out:
2438 return retval;
2439 }
2440
2441 int
mpi3mr_register_events(struct mpi3mr_softc * sc)2442 mpi3mr_register_events(struct mpi3mr_softc *sc)
2443 {
2444 int error;
2445
2446 mpi3mr_set_events_mask(sc);
2447
2448 error = mpi3mr_issue_event_notification(sc);
2449
2450 if (error) {
2451 printf(IOCNAME "Failed to issue event notification %d\n",
2452 sc->name, error);
2453 }
2454
2455 return error;
2456 }
2457
2458 /**
2459 * mpi3mr_process_event_ack - Process event acknowledgment
2460 * @sc: Adapter instance reference
2461 * @event: MPI3 event ID
2462 * @event_ctx: Event context
2463 *
2464 * Send event acknowledgement through admin queue and wait for
2465 * it to complete.
2466 *
2467 * Return: 0 on success, non-zero on failures.
2468 */
mpi3mr_process_event_ack(struct mpi3mr_softc * sc,U8 event,U32 event_ctx)2469 int mpi3mr_process_event_ack(struct mpi3mr_softc *sc, U8 event,
2470 U32 event_ctx)
2471 {
2472 Mpi3EventAckRequest_t evtack_req;
2473 int retval = 0;
2474
2475 memset(&evtack_req, 0, sizeof(evtack_req));
2476 mtx_lock(&sc->init_cmds.completion.lock);
2477 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
2478 retval = -1;
2479 printf(IOCNAME "Issue EvtAck: Init command is in use\n",
2480 sc->name);
2481 mtx_unlock(&sc->init_cmds.completion.lock);
2482 goto out;
2483 }
2484 sc->init_cmds.state = MPI3MR_CMD_PENDING;
2485 sc->init_cmds.is_waiting = 1;
2486 sc->init_cmds.callback = NULL;
2487 evtack_req.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS);
2488 evtack_req.Function = MPI3_FUNCTION_EVENT_ACK;
2489 evtack_req.Event = event;
2490 evtack_req.EventContext = htole32(event_ctx);
2491
2492 init_completion(&sc->init_cmds.completion);
2493 retval = mpi3mr_submit_admin_cmd(sc, &evtack_req,
2494 sizeof(evtack_req));
2495 if (retval) {
2496 printf(IOCNAME "Issue EvtAck: Admin Post failed\n",
2497 sc->name);
2498 goto out_unlock;
2499 }
2500
2501 wait_for_completion_timeout(&sc->init_cmds.completion,
2502 (MPI3MR_INTADMCMD_TIMEOUT));
2503 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
2504 printf(IOCNAME "Issue EvtAck: command timed out\n",
2505 sc->name);
2506 retval = -1;
2507 goto out_unlock;
2508 }
2509
2510 if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
2511 != MPI3_IOCSTATUS_SUCCESS ) {
2512 printf(IOCNAME "Issue EvtAck: Failed IOCStatus(0x%04x) "
2513 " Loginfo(0x%08x) \n" , sc->name,
2514 (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
2515 sc->init_cmds.ioc_loginfo);
2516 retval = -1;
2517 goto out_unlock;
2518 }
2519
2520 out_unlock:
2521 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
2522 mtx_unlock(&sc->init_cmds.completion.lock);
2523
2524 out:
2525 return retval;
2526 }
2527
2528
mpi3mr_alloc_chain_bufs(struct mpi3mr_softc * sc)2529 static int mpi3mr_alloc_chain_bufs(struct mpi3mr_softc *sc)
2530 {
2531 int retval = 0;
2532 U32 sz, i;
2533 U16 num_chains;
2534
2535 num_chains = sc->max_host_ios;
2536
2537 sc->chain_buf_count = num_chains;
2538 sz = sizeof(struct mpi3mr_chain) * num_chains;
2539
2540 sc->chain_sgl_list = malloc(sz, M_MPI3MR, M_NOWAIT | M_ZERO);
2541
2542 if (!sc->chain_sgl_list) {
2543 printf(IOCNAME "Cannot allocate memory for chain SGL list\n",
2544 sc->name);
2545 retval = -1;
2546 goto out_failed;
2547 }
2548
2549 if (sc->max_sgl_entries > sc->facts.max_data_length / PAGE_SIZE)
2550 sc->max_sgl_entries = sc->facts.max_data_length / PAGE_SIZE;
2551 sz = sc->max_sgl_entries * sizeof(Mpi3SGESimple_t);
2552
2553 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
2554 4096, 0, /* algnmnt, boundary */
2555 sc->dma_loaddr, /* lowaddr */
2556 BUS_SPACE_MAXADDR, /* highaddr */
2557 NULL, NULL, /* filter, filterarg */
2558 sz, /* maxsize */
2559 1, /* nsegments */
2560 sz, /* maxsegsize */
2561 0, /* flags */
2562 NULL, NULL, /* lockfunc, lockarg */
2563 &sc->chain_sgl_list_tag)) {
2564 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Chain buffer DMA tag\n");
2565 return (ENOMEM);
2566 }
2567
2568 for (i = 0; i < num_chains; i++) {
2569 if (bus_dmamem_alloc(sc->chain_sgl_list_tag, (void **)&sc->chain_sgl_list[i].buf,
2570 BUS_DMA_NOWAIT, &sc->chain_sgl_list[i].buf_dmamap)) {
2571 mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n",
2572 __func__, __LINE__);
2573 return (ENOMEM);
2574 }
2575
2576 bzero(sc->chain_sgl_list[i].buf, sz);
2577 bus_dmamap_load(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap, sc->chain_sgl_list[i].buf, sz,
2578 mpi3mr_memaddr_cb, &sc->chain_sgl_list[i].buf_phys, BUS_DMA_NOWAIT);
2579 mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d phys addr= %#016jx size= %d\n",
2580 __func__, __LINE__, (uintmax_t)sc->chain_sgl_list[i].buf_phys, sz);
2581 }
2582
2583 sc->chain_bitmap_sz = MPI3MR_DIV_ROUND_UP(num_chains, 8);
2584
2585 sc->chain_bitmap = malloc(sc->chain_bitmap_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
2586 if (!sc->chain_bitmap) {
2587 mpi3mr_dprint(sc, MPI3MR_INFO, "Cannot alloc memory for chain bitmap\n");
2588 retval = -1;
2589 goto out_failed;
2590 }
2591 return retval;
2592
2593 out_failed:
2594 for (i = 0; i < num_chains; i++) {
2595 if (sc->chain_sgl_list[i].buf_phys != 0)
2596 bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap);
2597 if (sc->chain_sgl_list[i].buf != NULL)
2598 bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf, sc->chain_sgl_list[i].buf_dmamap);
2599 }
2600 if (sc->chain_sgl_list_tag != NULL)
2601 bus_dma_tag_destroy(sc->chain_sgl_list_tag);
2602 return retval;
2603 }
2604
mpi3mr_pel_alloc(struct mpi3mr_softc * sc)2605 static int mpi3mr_pel_alloc(struct mpi3mr_softc *sc)
2606 {
2607 int retval = 0;
2608
2609 if (!sc->pel_cmds.reply) {
2610 sc->pel_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
2611 if (!sc->pel_cmds.reply) {
2612 printf(IOCNAME "Cannot allocate memory for pel_cmds.reply\n",
2613 sc->name);
2614 goto out_failed;
2615 }
2616 }
2617
2618 if (!sc->pel_abort_cmd.reply) {
2619 sc->pel_abort_cmd.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
2620 if (!sc->pel_abort_cmd.reply) {
2621 printf(IOCNAME "Cannot allocate memory for pel_abort_cmd.reply\n",
2622 sc->name);
2623 goto out_failed;
2624 }
2625 }
2626
2627 if (!sc->pel_seq_number) {
2628 sc->pel_seq_number_sz = sizeof(Mpi3PELSeq_t);
2629 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
2630 4, 0, /* alignment, boundary */
2631 sc->dma_loaddr, /* lowaddr */
2632 BUS_SPACE_MAXADDR, /* highaddr */
2633 NULL, NULL, /* filter, filterarg */
2634 sc->pel_seq_number_sz, /* maxsize */
2635 1, /* nsegments */
2636 sc->pel_seq_number_sz, /* maxsegsize */
2637 0, /* flags */
2638 NULL, NULL, /* lockfunc, lockarg */
2639 &sc->pel_seq_num_dmatag)) {
2640 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot create PEL seq number dma memory tag\n");
2641 retval = -ENOMEM;
2642 goto out_failed;
2643 }
2644
2645 if (bus_dmamem_alloc(sc->pel_seq_num_dmatag, (void **)&sc->pel_seq_number,
2646 BUS_DMA_NOWAIT, &sc->pel_seq_num_dmamap)) {
2647 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate PEL seq number kernel buffer dma memory\n");
2648 retval = -ENOMEM;
2649 goto out_failed;
2650 }
2651
2652 bzero(sc->pel_seq_number, sc->pel_seq_number_sz);
2653
2654 bus_dmamap_load(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap, sc->pel_seq_number,
2655 sc->pel_seq_number_sz, mpi3mr_memaddr_cb, &sc->pel_seq_number_dma, BUS_DMA_NOWAIT);
2656
2657 if (!sc->pel_seq_number) {
2658 printf(IOCNAME "%s:%d Cannot load PEL seq number dma memory for size: %d\n", sc->name,
2659 __func__, __LINE__, sc->pel_seq_number_sz);
2660 retval = -ENOMEM;
2661 goto out_failed;
2662 }
2663 }
2664
2665 out_failed:
2666 return retval;
2667 }
2668
2669 /**
2670 * mpi3mr_validate_fw_update - validate IOCFacts post adapter reset
2671 * @sc: Adapter instance reference
2672 *
2673 * Return zero if the new IOCFacts is compatible with previous values
2674 * else return appropriate error
2675 */
2676 static int
mpi3mr_validate_fw_update(struct mpi3mr_softc * sc)2677 mpi3mr_validate_fw_update(struct mpi3mr_softc *sc)
2678 {
2679 U16 dev_handle_bitmap_sz;
2680 U8 *removepend_bitmap;
2681
2682 if (sc->facts.reply_sz > sc->reply_sz) {
2683 mpi3mr_dprint(sc, MPI3MR_ERROR,
2684 "Cannot increase reply size from %d to %d\n",
2685 sc->reply_sz, sc->reply_sz);
2686 return -EPERM;
2687 }
2688
2689 if (sc->num_io_throttle_group != sc->facts.max_io_throttle_group) {
2690 mpi3mr_dprint(sc, MPI3MR_ERROR,
2691 "max io throttle group doesn't match old(%d), new(%d)\n",
2692 sc->num_io_throttle_group,
2693 sc->facts.max_io_throttle_group);
2694 return -EPERM;
2695 }
2696
2697 if (sc->facts.max_op_reply_q < sc->num_queues) {
2698 mpi3mr_dprint(sc, MPI3MR_ERROR,
2699 "Cannot reduce number of operational reply queues from %d to %d\n",
2700 sc->num_queues,
2701 sc->facts.max_op_reply_q);
2702 return -EPERM;
2703 }
2704
2705 if (sc->facts.max_op_req_q < sc->num_queues) {
2706 mpi3mr_dprint(sc, MPI3MR_ERROR,
2707 "Cannot reduce number of operational request queues from %d to %d\n",
2708 sc->num_queues, sc->facts.max_op_req_q);
2709 return -EPERM;
2710 }
2711
2712 dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8);
2713
2714 if (dev_handle_bitmap_sz > sc->dev_handle_bitmap_sz) {
2715 removepend_bitmap = realloc(sc->removepend_bitmap,
2716 dev_handle_bitmap_sz, M_MPI3MR, M_NOWAIT);
2717
2718 if (!removepend_bitmap) {
2719 mpi3mr_dprint(sc, MPI3MR_ERROR,
2720 "failed to increase removepend_bitmap sz from: %d to %d\n",
2721 sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
2722 return -ENOMEM;
2723 }
2724
2725 memset(removepend_bitmap + sc->dev_handle_bitmap_sz, 0,
2726 dev_handle_bitmap_sz - sc->dev_handle_bitmap_sz);
2727 sc->removepend_bitmap = removepend_bitmap;
2728 mpi3mr_dprint(sc, MPI3MR_INFO,
2729 "increased dev_handle_bitmap_sz from %d to %d\n",
2730 sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
2731 sc->dev_handle_bitmap_sz = dev_handle_bitmap_sz;
2732 }
2733
2734 return 0;
2735 }
2736
2737 /*
2738 * mpi3mr_initialize_ioc - Controller initialization
2739 * @dev: pointer to device struct
2740 *
2741 * This function allocates the controller wide resources and brings
2742 * the controller to operational state
2743 *
2744 * Return: 0 on success and proper error codes on failure
2745 */
mpi3mr_initialize_ioc(struct mpi3mr_softc * sc,U8 init_type)2746 int mpi3mr_initialize_ioc(struct mpi3mr_softc *sc, U8 init_type)
2747 {
2748 int retval = 0;
2749 enum mpi3mr_iocstate ioc_state;
2750 U64 ioc_info, start_ticks = 0;
2751 U32 ioc_status, ioc_control, i, timeout;
2752 Mpi3IOCFactsData_t facts_data;
2753 char str[32];
2754 U32 size;
2755 U8 retry = 0;
2756
2757 sc->cpu_count = mp_ncpus;
2758
2759 retry_init:
2760 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
2761 ioc_control = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
2762 ioc_info = mpi3mr_regread64(sc, MPI3_SYSIF_IOC_INFO_LOW_OFFSET);
2763
2764 mpi3mr_dprint(sc, MPI3MR_INFO, "SOD ioc_status: 0x%x ioc_control: 0x%x "
2765 "ioc_info: 0x%lx\n", ioc_status, ioc_control, ioc_info);
2766
2767 /*The timeout value is in 2sec unit, changing it to seconds*/
2768 sc->ready_timeout =
2769 ((ioc_info & MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK) >>
2770 MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_SHIFT) * 2;
2771
2772 ioc_state = mpi3mr_get_iocstate(sc);
2773 mpi3mr_dprint(sc, MPI3MR_INFO, "IOC state: %s IOC ready timeout: %d\n",
2774 mpi3mr_iocstate_name(ioc_state), sc->ready_timeout);
2775
2776 timeout = sc->ready_timeout * 10;
2777 do {
2778 ioc_state = mpi3mr_get_iocstate(sc);
2779
2780 if (ioc_state != MRIOC_STATE_BECOMING_READY &&
2781 ioc_state != MRIOC_STATE_RESET_REQUESTED)
2782 break;
2783
2784 DELAY(1000 * 100);
2785 } while (--timeout);
2786
2787 if (ioc_state == MRIOC_STATE_READY) {
2788 retval = mpi3mr_mur_ioc(sc, MPI3MR_RESET_FROM_BRINGUP);
2789 if (retval) {
2790 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to MU reset IOC, error 0x%x\n",
2791 retval);
2792 }
2793 ioc_state = mpi3mr_get_iocstate(sc);
2794 }
2795
2796 if (ioc_state != MRIOC_STATE_RESET) {
2797 if (ioc_state == MRIOC_STATE_FAULT) {
2798 mpi3mr_print_fault_info(sc);
2799
2800 U32 fault = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) &
2801 MPI3_SYSIF_FAULT_CODE_MASK;
2802 if (fault == MPI3_SYSIF_FAULT_CODE_INSUFFICIENT_PCI_SLOT_POWER)
2803 mpi3mr_dprint(sc, MPI3MR_INFO,
2804 "controller faulted due to insufficient power, try by connecting it in a different slot\n");
2805 goto err;
2806
2807 U32 host_diagnostic;
2808 timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10;
2809 do {
2810 host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET);
2811 if (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS))
2812 break;
2813 DELAY(100 * 1000);
2814 } while (--timeout);
2815 }
2816 mpi3mr_dprint(sc, MPI3MR_ERROR, "issuing soft reset to bring to reset state\n");
2817 retval = mpi3mr_issue_reset(sc,
2818 MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
2819 MPI3MR_RESET_FROM_BRINGUP);
2820 if (retval) {
2821 mpi3mr_dprint(sc, MPI3MR_ERROR,
2822 "%s :Failed to soft reset IOC, error 0x%d\n",
2823 __func__, retval);
2824 goto err_retry;
2825 }
2826 }
2827
2828 ioc_state = mpi3mr_get_iocstate(sc);
2829
2830 if (ioc_state != MRIOC_STATE_RESET) {
2831 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot bring IOC to reset state\n");
2832 goto err_retry;
2833 }
2834
2835 retval = mpi3mr_setup_admin_qpair(sc);
2836 if (retval) {
2837 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup Admin queues, error 0x%x\n",
2838 retval);
2839 if (retval == ENOMEM)
2840 goto err;
2841 goto err_retry;
2842 }
2843
2844 retval = mpi3mr_bring_ioc_ready(sc, &start_ticks);
2845 if (retval) {
2846 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to bring IOC ready, error 0x%x\n", retval);
2847 if (retval == EAGAIN)
2848 goto err_retry;
2849 goto err;
2850 }
2851
2852
2853 if (init_type == MPI3MR_INIT_TYPE_INIT) {
2854 retval = mpi3mr_alloc_interrupts(sc, 1);
2855 if (retval) {
2856 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, error 0x%x\n",
2857 retval);
2858 goto err;
2859 }
2860
2861 retval = mpi3mr_setup_irqs(sc);
2862 if (retval) {
2863 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup ISR, error 0x%x\n",
2864 retval);
2865 goto err;
2866 }
2867 }
2868
2869 mpi3mr_enable_interrupts(sc);
2870
2871 if (init_type == MPI3MR_INIT_TYPE_INIT) {
2872 mtx_init(&sc->mpi3mr_mtx, "SIM lock", NULL, MTX_DEF);
2873 mtx_init(&sc->io_lock, "IO lock", NULL, MTX_DEF);
2874 mtx_init(&sc->admin_req_lock, "Admin Request Queue lock", NULL, MTX_SPIN);
2875 mtx_init(&sc->reply_free_q_lock, "Reply free Queue lock", NULL, MTX_SPIN);
2876 mtx_init(&sc->sense_buf_q_lock, "Sense buffer Queue lock", NULL, MTX_SPIN);
2877 mtx_init(&sc->chain_buf_lock, "Chain buffer lock", NULL, MTX_SPIN);
2878 mtx_init(&sc->cmd_pool_lock, "Command pool lock", NULL, MTX_DEF);
2879 mtx_init(&sc->fwevt_lock, "Firmware Event lock", NULL, MTX_DEF);
2880 mtx_init(&sc->target_lock, "Target lock", NULL, MTX_SPIN);
2881 mtx_init(&sc->reset_mutex, "Reset lock", NULL, MTX_DEF);
2882
2883 mtx_init(&sc->init_cmds.completion.lock, "Init commands lock", NULL, MTX_DEF);
2884 sc->init_cmds.reply = NULL;
2885 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
2886 sc->init_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
2887 sc->init_cmds.host_tag = MPI3MR_HOSTTAG_INITCMDS;
2888
2889 mtx_init(&sc->cfg_cmds.completion.lock, "CFG commands lock", NULL, MTX_DEF);
2890 sc->cfg_cmds.reply = NULL;
2891 sc->cfg_cmds.state = MPI3MR_CMD_NOTUSED;
2892 sc->cfg_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
2893 sc->cfg_cmds.host_tag = MPI3MR_HOSTTAG_CFGCMDS;
2894
2895 mtx_init(&sc->ioctl_cmds.completion.lock, "IOCTL commands lock", NULL, MTX_DEF);
2896 sc->ioctl_cmds.reply = NULL;
2897 sc->ioctl_cmds.state = MPI3MR_CMD_NOTUSED;
2898 sc->ioctl_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
2899 sc->ioctl_cmds.host_tag = MPI3MR_HOSTTAG_IOCTLCMDS;
2900
2901 mtx_init(&sc->pel_abort_cmd.completion.lock, "PEL Abort command lock", NULL, MTX_DEF);
2902 sc->pel_abort_cmd.reply = NULL;
2903 sc->pel_abort_cmd.state = MPI3MR_CMD_NOTUSED;
2904 sc->pel_abort_cmd.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
2905 sc->pel_abort_cmd.host_tag = MPI3MR_HOSTTAG_PELABORT;
2906
2907 mtx_init(&sc->host_tm_cmds.completion.lock, "TM commands lock", NULL, MTX_DEF);
2908 sc->host_tm_cmds.reply = NULL;
2909 sc->host_tm_cmds.state = MPI3MR_CMD_NOTUSED;
2910 sc->host_tm_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
2911 sc->host_tm_cmds.host_tag = MPI3MR_HOSTTAG_TMS;
2912
2913 TAILQ_INIT(&sc->cmd_list_head);
2914 TAILQ_INIT(&sc->event_list);
2915 TAILQ_INIT(&sc->delayed_rmhs_list);
2916 TAILQ_INIT(&sc->delayed_evtack_cmds_list);
2917
2918 for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
2919 snprintf(str, 32, "Dev REMHS commands lock[%d]", i);
2920 mtx_init(&sc->dev_rmhs_cmds[i].completion.lock, str, NULL, MTX_DEF);
2921 sc->dev_rmhs_cmds[i].reply = NULL;
2922 sc->dev_rmhs_cmds[i].state = MPI3MR_CMD_NOTUSED;
2923 sc->dev_rmhs_cmds[i].dev_handle = MPI3MR_INVALID_DEV_HANDLE;
2924 sc->dev_rmhs_cmds[i].host_tag = MPI3MR_HOSTTAG_DEVRMCMD_MIN
2925 + i;
2926 }
2927 }
2928
2929 retval = mpi3mr_issue_iocfacts(sc, &facts_data);
2930 if (retval) {
2931 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Facts, error: 0x%x\n",
2932 retval);
2933 if (retval == ENOMEM)
2934 goto err;
2935 goto err_retry;
2936 }
2937
2938 retval = mpi3mr_process_factsdata(sc, &facts_data);
2939 if (retval) {
2940 mpi3mr_dprint(sc, MPI3MR_ERROR, "IOC Facts data processing failed, error: 0x%x\n",
2941 retval);
2942 goto err_retry;
2943 }
2944
2945 sc->num_io_throttle_group = sc->facts.max_io_throttle_group;
2946 mpi3mr_atomic_set(&sc->pend_large_data_sz, 0);
2947
2948 if (init_type == MPI3MR_INIT_TYPE_RESET) {
2949 retval = mpi3mr_validate_fw_update(sc);
2950 if (retval) {
2951 if (retval == ENOMEM)
2952 goto err;
2953 goto err_retry;
2954 }
2955 } else {
2956 sc->reply_sz = sc->facts.reply_sz;
2957 }
2958
2959 mpi3mr_display_ioc_info(sc);
2960
2961 retval = mpi3mr_reply_alloc(sc);
2962 if (retval) {
2963 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated reply and sense buffers, error: 0x%x\n",
2964 retval);
2965 goto err;
2966 }
2967
2968 if (init_type == MPI3MR_INIT_TYPE_INIT) {
2969 retval = mpi3mr_alloc_chain_bufs(sc);
2970 if (retval) {
2971 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated chain buffers, error: 0x%x\n",
2972 retval);
2973 goto err;
2974 }
2975 }
2976
2977 retval = mpi3mr_issue_iocinit(sc);
2978 if (retval) {
2979 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Init, error: 0x%x\n",
2980 retval);
2981 if (retval == ENOMEM)
2982 goto err;
2983 goto err_retry;
2984 }
2985
2986 mpi3mr_print_fw_pkg_ver(sc);
2987
2988 sc->reply_free_q_host_index = sc->num_reply_bufs;
2989 mpi3mr_regwrite(sc, MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET,
2990 sc->reply_free_q_host_index);
2991
2992 sc->sense_buf_q_host_index = sc->num_sense_bufs;
2993
2994 mpi3mr_regwrite(sc, MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET,
2995 sc->sense_buf_q_host_index);
2996
2997 if (init_type == MPI3MR_INIT_TYPE_INIT) {
2998 retval = mpi3mr_alloc_interrupts(sc, 0);
2999 if (retval) {
3000 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, error: 0x%x\n",
3001 retval);
3002 goto err;
3003 }
3004
3005 retval = mpi3mr_setup_irqs(sc);
3006 if (retval) {
3007 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup ISR, error: 0x%x\n", retval);
3008 goto err;
3009 }
3010
3011 mpi3mr_enable_interrupts(sc);
3012
3013 } else
3014 mpi3mr_enable_interrupts(sc);
3015
3016 retval = mpi3mr_create_op_queues(sc);
3017 if (retval) {
3018 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create operational queues, error: %d\n",
3019 retval);
3020 if (retval == ENOMEM)
3021 goto err;
3022 goto err_retry;
3023 }
3024
3025 if (!sc->throttle_groups && sc->num_io_throttle_group) {
3026 size = sizeof(struct mpi3mr_throttle_group_info);
3027 sc->throttle_groups = (struct mpi3mr_throttle_group_info *)
3028 malloc(sc->num_io_throttle_group *
3029 size, M_MPI3MR, M_NOWAIT | M_ZERO);
3030 if (!sc->throttle_groups) {
3031 mpi3mr_dprint(sc, MPI3MR_ERROR, "throttle groups memory allocation failed\n");
3032 goto err;
3033 }
3034 }
3035
3036 if (init_type == MPI3MR_INIT_TYPE_RESET) {
3037 mpi3mr_dprint(sc, MPI3MR_XINFO, "Re-register events\n");
3038 retval = mpi3mr_register_events(sc);
3039 if (retval) {
3040 mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to re-register events, error: 0x%x\n",
3041 retval);
3042 goto err_retry;
3043 }
3044
3045 mpi3mr_dprint(sc, MPI3MR_INFO, "Issuing Port Enable\n");
3046 retval = mpi3mr_issue_port_enable(sc, 0);
3047 if (retval) {
3048 mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to issue port enable, error: 0x%x\n",
3049 retval);
3050 goto err_retry;
3051 }
3052 }
3053 retval = mpi3mr_pel_alloc(sc);
3054 if (retval) {
3055 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate memory for PEL, error: 0x%x\n",
3056 retval);
3057 goto err;
3058 }
3059
3060 if (mpi3mr_cfg_get_driver_pg1(sc) != 0)
3061 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to get the cfg driver page1\n");
3062
3063 return retval;
3064
3065 err_retry:
3066 if ((retry++ < 2) && (((ticks - start_ticks) / hz) < (sc->ready_timeout - 60))) {
3067 mpi3mr_dprint(sc, MPI3MR_ERROR, "Retrying controller initialization,"
3068 "retry_count: %d\n", retry);
3069 goto retry_init;
3070 }
3071 err:
3072 retval = -1;
3073 return retval;
3074 }
3075
mpi3mr_port_enable_complete(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * drvrcmd)3076 static void mpi3mr_port_enable_complete(struct mpi3mr_softc *sc,
3077 struct mpi3mr_drvr_cmd *drvrcmd)
3078 {
3079 drvrcmd->state = MPI3MR_CMD_NOTUSED;
3080 drvrcmd->callback = NULL;
3081 printf(IOCNAME "Completing Port Enable Request\n", sc->name);
3082 sc->mpi3mr_flags |= MPI3MR_FLAGS_PORT_ENABLE_DONE;
3083 mpi3mr_startup_decrement(sc->cam_sc);
3084 }
3085
mpi3mr_issue_port_enable(struct mpi3mr_softc * sc,U8 async)3086 int mpi3mr_issue_port_enable(struct mpi3mr_softc *sc, U8 async)
3087 {
3088 Mpi3PortEnableRequest_t pe_req;
3089 int retval = 0;
3090
3091 memset(&pe_req, 0, sizeof(pe_req));
3092 mtx_lock(&sc->init_cmds.completion.lock);
3093 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
3094 retval = -1;
3095 printf(IOCNAME "Issue PortEnable: Init command is in use\n", sc->name);
3096 mtx_unlock(&sc->init_cmds.completion.lock);
3097 goto out;
3098 }
3099
3100 sc->init_cmds.state = MPI3MR_CMD_PENDING;
3101
3102 if (async) {
3103 sc->init_cmds.is_waiting = 0;
3104 sc->init_cmds.callback = mpi3mr_port_enable_complete;
3105 } else {
3106 sc->init_cmds.is_waiting = 1;
3107 sc->init_cmds.callback = NULL;
3108 init_completion(&sc->init_cmds.completion);
3109 }
3110 pe_req.HostTag = MPI3MR_HOSTTAG_INITCMDS;
3111 pe_req.Function = MPI3_FUNCTION_PORT_ENABLE;
3112
3113 printf(IOCNAME "Sending Port Enable Request\n", sc->name);
3114 retval = mpi3mr_submit_admin_cmd(sc, &pe_req, sizeof(pe_req));
3115 if (retval) {
3116 printf(IOCNAME "Issue PortEnable: Admin Post failed\n",
3117 sc->name);
3118 goto out_unlock;
3119 }
3120
3121 if (!async) {
3122 wait_for_completion_timeout(&sc->init_cmds.completion,
3123 MPI3MR_PORTENABLE_TIMEOUT);
3124 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
3125 printf(IOCNAME "Issue PortEnable: command timed out\n",
3126 sc->name);
3127 retval = -1;
3128 mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_PE_TIMEOUT);
3129 goto out_unlock;
3130 }
3131 mpi3mr_port_enable_complete(sc, &sc->init_cmds);
3132 }
3133 out_unlock:
3134 mtx_unlock(&sc->init_cmds.completion.lock);
3135
3136 out:
3137 return retval;
3138 }
3139
mpi3mr_timestamp_sync(struct mpi3mr_softc * sc)3140 static int mpi3mr_timestamp_sync(struct mpi3mr_softc *sc)
3141 {
3142 int retval = 0;
3143 struct timeval current_time;
3144 int64_t time_in_msec;
3145 Mpi3IoUnitControlRequest_t iou_ctrl = {0};
3146
3147 mtx_lock(&sc->init_cmds.completion.lock);
3148 if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
3149 mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue timestamp sync: command is in use\n");
3150 mtx_unlock(&sc->init_cmds.completion.lock);
3151 return -1;
3152 }
3153
3154 sc->init_cmds.state = MPI3MR_CMD_PENDING;
3155 sc->init_cmds.is_waiting = 1;
3156 sc->init_cmds.callback = NULL;
3157 iou_ctrl.HostTag = htole64(MPI3MR_HOSTTAG_INITCMDS);
3158 iou_ctrl.Function = MPI3_FUNCTION_IO_UNIT_CONTROL;
3159 iou_ctrl.Operation = MPI3_CTRL_OP_UPDATE_TIMESTAMP;
3160 getmicrotime(¤t_time);
3161 time_in_msec = (int64_t)current_time.tv_sec * 1000 + current_time.tv_usec/1000;
3162 iou_ctrl.Param64[0] = htole64(time_in_msec);
3163
3164 init_completion(&sc->init_cmds.completion);
3165
3166 retval = mpi3mr_submit_admin_cmd(sc, &iou_ctrl, sizeof(iou_ctrl));
3167 if (retval) {
3168 mpi3mr_dprint(sc, MPI3MR_ERROR, "timestamp sync: Admin Post failed\n");
3169 goto out_unlock;
3170 }
3171
3172 wait_for_completion_timeout(&sc->init_cmds.completion,
3173 (MPI3MR_INTADMCMD_TIMEOUT));
3174
3175 if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
3176 mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue timestamp sync: command timed out\n");
3177 sc->init_cmds.is_waiting = 0;
3178
3179 if (!(sc->init_cmds.state & MPI3MR_CMD_RESET))
3180 mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_TSU_TIMEOUT);
3181
3182 retval = -1;
3183 goto out_unlock;
3184 }
3185
3186 if (((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS) &&
3187 (sc->init_cmds.ioc_status != MPI3_IOCSTATUS_SUPERVISOR_ONLY)) {
3188 mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue timestamp sync: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n",
3189 (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), sc->init_cmds.ioc_loginfo);
3190 retval = -1;
3191 }
3192
3193 out_unlock:
3194 sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
3195 mtx_unlock(&sc->init_cmds.completion.lock);
3196
3197 return retval;
3198 }
3199
3200 void
mpi3mr_timestamp_thread(void * arg)3201 mpi3mr_timestamp_thread(void *arg)
3202 {
3203 struct mpi3mr_softc *sc = (struct mpi3mr_softc *)arg;
3204 U64 elapsed_time = 0;
3205
3206 sc->timestamp_thread_active = 1;
3207 mtx_lock(&sc->reset_mutex);
3208 while (1) {
3209
3210 if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ||
3211 (sc->unrecoverable == 1)) {
3212 mpi3mr_dprint(sc, MPI3MR_INFO,
3213 "Exit due to %s from %s\n",
3214 sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ? "Shutdown" :
3215 "Hardware critical error", __func__);
3216 break;
3217 }
3218 mtx_unlock(&sc->reset_mutex);
3219
3220 while (sc->reset_in_progress) {
3221 if (elapsed_time)
3222 elapsed_time = 0;
3223 if (sc->unrecoverable)
3224 break;
3225 pause("mpi3mr_timestamp_thread", hz / 5);
3226 }
3227
3228 if (elapsed_time++ >= sc->ts_update_interval * 60) {
3229 mpi3mr_timestamp_sync(sc);
3230 elapsed_time = 0;
3231 }
3232
3233 /*
3234 * Sleep for 1 second if we're not exiting, then loop to top
3235 * to poll exit status and hardware health.
3236 */
3237 mtx_lock(&sc->reset_mutex);
3238 if (((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) == 0) &&
3239 (!sc->unrecoverable) && (!sc->reset_in_progress)) {
3240 msleep(&sc->timestamp_chan, &sc->reset_mutex, PRIBIO,
3241 "mpi3mr_timestamp", 1 * hz);
3242 }
3243 }
3244 mtx_unlock(&sc->reset_mutex);
3245 sc->timestamp_thread_active = 0;
3246 kproc_exit(0);
3247 }
3248
3249 void
mpi3mr_watchdog_thread(void * arg)3250 mpi3mr_watchdog_thread(void *arg)
3251 {
3252 struct mpi3mr_softc *sc;
3253 enum mpi3mr_iocstate ioc_state;
3254 U32 fault, host_diagnostic, ioc_status;
3255
3256 sc = (struct mpi3mr_softc *)arg;
3257
3258 mpi3mr_dprint(sc, MPI3MR_XINFO, "%s\n", __func__);
3259
3260 sc->watchdog_thread_active = 1;
3261 mtx_lock(&sc->reset_mutex);
3262 for (;;) {
3263 if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ||
3264 (sc->unrecoverable == 1)) {
3265 mpi3mr_dprint(sc, MPI3MR_INFO,
3266 "Exit due to %s from %s\n",
3267 sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ? "Shutdown" :
3268 "Hardware critical error", __func__);
3269 break;
3270 }
3271 mtx_unlock(&sc->reset_mutex);
3272
3273 if ((sc->prepare_for_reset) &&
3274 ((sc->prepare_for_reset_timeout_counter++) >=
3275 MPI3MR_PREPARE_FOR_RESET_TIMEOUT)) {
3276 mpi3mr_soft_reset_handler(sc,
3277 MPI3MR_RESET_FROM_CIACTVRST_TIMER, 1);
3278 goto sleep;
3279 }
3280
3281 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
3282
3283 if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) {
3284 mpi3mr_soft_reset_handler(sc, MPI3MR_RESET_FROM_FIRMWARE, 0);
3285 goto sleep;
3286 }
3287
3288 ioc_state = mpi3mr_get_iocstate(sc);
3289 if (ioc_state == MRIOC_STATE_FAULT) {
3290 fault = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) &
3291 MPI3_SYSIF_FAULT_CODE_MASK;
3292
3293 host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET);
3294 if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) {
3295 if (!sc->diagsave_timeout) {
3296 mpi3mr_print_fault_info(sc);
3297 mpi3mr_dprint(sc, MPI3MR_INFO,
3298 "diag save in progress\n");
3299 }
3300 if ((sc->diagsave_timeout++) <= MPI3_SYSIF_DIAG_SAVE_TIMEOUT)
3301 goto sleep;
3302 }
3303 mpi3mr_print_fault_info(sc);
3304 sc->diagsave_timeout = 0;
3305
3306 if ((fault == MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED) ||
3307 (fault == MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED)) {
3308 mpi3mr_dprint(sc, MPI3MR_INFO,
3309 "Controller requires system power cycle or complete reset is needed,"
3310 "fault code: 0x%x. marking controller as unrecoverable\n", fault);
3311 sc->unrecoverable = 1;
3312 break;
3313 }
3314
3315 if (fault == MPI3_SYSIF_FAULT_CODE_INSUFFICIENT_PCI_SLOT_POWER) {
3316 mpi3mr_dprint(sc, MPI3MR_INFO,
3317 "controller faulted due to insufficient power, marking controller as unrecoverable\n");
3318 sc->unrecoverable = 1;
3319 break;
3320 }
3321
3322 if ((fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET)
3323 || (fault == MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS)
3324 || (sc->reset_in_progress))
3325 break;
3326 if (fault == MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET)
3327 mpi3mr_soft_reset_handler(sc,
3328 MPI3MR_RESET_FROM_CIACTIV_FAULT, 0);
3329 else
3330 mpi3mr_soft_reset_handler(sc,
3331 MPI3MR_RESET_FROM_FAULT_WATCH, 0);
3332
3333 }
3334
3335 if (sc->reset.type == MPI3MR_TRIGGER_SOFT_RESET) {
3336 mpi3mr_print_fault_info(sc);
3337 mpi3mr_soft_reset_handler(sc, sc->reset.reason, 1);
3338 }
3339 sleep:
3340 mtx_lock(&sc->reset_mutex);
3341 /*
3342 * Sleep for 1 second if we're not exiting, then loop to top
3343 * to poll exit status and hardware health.
3344 */
3345 if ((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) == 0 &&
3346 !sc->unrecoverable) {
3347 msleep(&sc->watchdog_chan, &sc->reset_mutex, PRIBIO,
3348 "mpi3mr_watchdog", 1 * hz);
3349 }
3350 }
3351 mtx_unlock(&sc->reset_mutex);
3352 sc->watchdog_thread_active = 0;
3353 mpi3mr_kproc_exit(0);
3354 }
3355
mpi3mr_display_event_data(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_rep)3356 static void mpi3mr_display_event_data(struct mpi3mr_softc *sc,
3357 Mpi3EventNotificationReply_t *event_rep)
3358 {
3359 char *desc = NULL;
3360 U16 event;
3361
3362 event = event_rep->Event;
3363
3364 switch (event) {
3365 case MPI3_EVENT_LOG_DATA:
3366 desc = "Log Data";
3367 break;
3368 case MPI3_EVENT_CHANGE:
3369 desc = "Event Change";
3370 break;
3371 case MPI3_EVENT_GPIO_INTERRUPT:
3372 desc = "GPIO Interrupt";
3373 break;
3374 case MPI3_EVENT_CABLE_MGMT:
3375 desc = "Cable Management";
3376 break;
3377 case MPI3_EVENT_ENERGY_PACK_CHANGE:
3378 desc = "Energy Pack Change";
3379 break;
3380 case MPI3_EVENT_DEVICE_ADDED:
3381 {
3382 Mpi3DevicePage0_t *event_data =
3383 (Mpi3DevicePage0_t *)event_rep->EventData;
3384 mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Added: Dev=0x%04x Form=0x%x Perst id: 0x%x\n",
3385 event_data->DevHandle, event_data->DeviceForm, event_data->PersistentID);
3386 return;
3387 }
3388 case MPI3_EVENT_DEVICE_INFO_CHANGED:
3389 {
3390 Mpi3DevicePage0_t *event_data =
3391 (Mpi3DevicePage0_t *)event_rep->EventData;
3392 mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Info Changed: Dev=0x%04x Form=0x%x\n",
3393 event_data->DevHandle, event_data->DeviceForm);
3394 return;
3395 }
3396 case MPI3_EVENT_DEVICE_STATUS_CHANGE:
3397 {
3398 Mpi3EventDataDeviceStatusChange_t *event_data =
3399 (Mpi3EventDataDeviceStatusChange_t *)event_rep->EventData;
3400 mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Status Change: Dev=0x%04x RC=0x%x\n",
3401 event_data->DevHandle, event_data->ReasonCode);
3402 return;
3403 }
3404 case MPI3_EVENT_SAS_DISCOVERY:
3405 {
3406 Mpi3EventDataSasDiscovery_t *event_data =
3407 (Mpi3EventDataSasDiscovery_t *)event_rep->EventData;
3408 mpi3mr_dprint(sc, MPI3MR_EVENT, "SAS Discovery: (%s)",
3409 (event_data->ReasonCode == MPI3_EVENT_SAS_DISC_RC_STARTED) ?
3410 "start" : "stop");
3411 if (event_data->DiscoveryStatus &&
3412 (sc->mpi3mr_debug & MPI3MR_EVENT)) {
3413 printf("discovery_status(0x%08x)",
3414 event_data->DiscoveryStatus);
3415
3416 }
3417
3418 if (sc->mpi3mr_debug & MPI3MR_EVENT)
3419 printf("\n");
3420 return;
3421 }
3422 case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE:
3423 desc = "SAS Broadcast Primitive";
3424 break;
3425 case MPI3_EVENT_SAS_NOTIFY_PRIMITIVE:
3426 desc = "SAS Notify Primitive";
3427 break;
3428 case MPI3_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
3429 desc = "SAS Init Device Status Change";
3430 break;
3431 case MPI3_EVENT_SAS_INIT_TABLE_OVERFLOW:
3432 desc = "SAS Init Table Overflow";
3433 break;
3434 case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
3435 desc = "SAS Topology Change List";
3436 break;
3437 case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
3438 desc = "Enclosure Device Status Change";
3439 break;
3440 case MPI3_EVENT_HARD_RESET_RECEIVED:
3441 desc = "Hard Reset Received";
3442 break;
3443 case MPI3_EVENT_SAS_PHY_COUNTER:
3444 desc = "SAS PHY Counter";
3445 break;
3446 case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
3447 desc = "SAS Device Discovery Error";
3448 break;
3449 case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
3450 desc = "PCIE Topology Change List";
3451 break;
3452 case MPI3_EVENT_PCIE_ENUMERATION:
3453 {
3454 Mpi3EventDataPcieEnumeration_t *event_data =
3455 (Mpi3EventDataPcieEnumeration_t *)event_rep->EventData;
3456 mpi3mr_dprint(sc, MPI3MR_EVENT, "PCIE Enumeration: (%s)",
3457 (event_data->ReasonCode ==
3458 MPI3_EVENT_PCIE_ENUM_RC_STARTED) ? "start" :
3459 "stop");
3460 if (event_data->EnumerationStatus)
3461 mpi3mr_dprint(sc, MPI3MR_EVENT, "enumeration_status(0x%08x)",
3462 event_data->EnumerationStatus);
3463 if (sc->mpi3mr_debug & MPI3MR_EVENT)
3464 printf("\n");
3465 return;
3466 }
3467 case MPI3_EVENT_PREPARE_FOR_RESET:
3468 desc = "Prepare For Reset";
3469 break;
3470 }
3471
3472 if (!desc)
3473 return;
3474
3475 mpi3mr_dprint(sc, MPI3MR_EVENT, "%s\n", desc);
3476 }
3477
3478 struct mpi3mr_target *
mpi3mr_find_target_by_per_id(struct mpi3mr_cam_softc * cam_sc,uint16_t per_id)3479 mpi3mr_find_target_by_per_id(struct mpi3mr_cam_softc *cam_sc,
3480 uint16_t per_id)
3481 {
3482 struct mpi3mr_target *target = NULL;
3483
3484 mtx_lock_spin(&cam_sc->sc->target_lock);
3485 TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) {
3486 if (target->per_id == per_id)
3487 break;
3488 }
3489
3490 mtx_unlock_spin(&cam_sc->sc->target_lock);
3491 return target;
3492 }
3493
3494 struct mpi3mr_target *
mpi3mr_find_target_by_dev_handle(struct mpi3mr_cam_softc * cam_sc,uint16_t handle)3495 mpi3mr_find_target_by_dev_handle(struct mpi3mr_cam_softc *cam_sc,
3496 uint16_t handle)
3497 {
3498 struct mpi3mr_target *target = NULL;
3499
3500 mtx_lock_spin(&cam_sc->sc->target_lock);
3501 TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) {
3502 if (target->dev_handle == handle)
3503 break;
3504
3505 }
3506 mtx_unlock_spin(&cam_sc->sc->target_lock);
3507 return target;
3508 }
3509
mpi3mr_update_device(struct mpi3mr_softc * sc,struct mpi3mr_target * tgtdev,Mpi3DevicePage0_t * dev_pg0,bool is_added)3510 void mpi3mr_update_device(struct mpi3mr_softc *sc,
3511 struct mpi3mr_target *tgtdev, Mpi3DevicePage0_t *dev_pg0,
3512 bool is_added)
3513 {
3514 U16 flags = 0;
3515
3516 tgtdev->per_id = (dev_pg0->PersistentID);
3517 tgtdev->dev_handle = (dev_pg0->DevHandle);
3518 tgtdev->dev_type = dev_pg0->DeviceForm;
3519 tgtdev->encl_handle = (dev_pg0->EnclosureHandle);
3520 tgtdev->parent_handle = (dev_pg0->ParentDevHandle);
3521 tgtdev->slot = (dev_pg0->Slot);
3522 tgtdev->qdepth = (dev_pg0->QueueDepth);
3523 tgtdev->wwid = (dev_pg0->WWID);
3524
3525 flags = (dev_pg0->Flags);
3526 tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN);
3527 if (is_added == true)
3528 tgtdev->io_throttle_enabled =
3529 (flags & MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED) ? 1 : 0;
3530
3531 switch (dev_pg0->AccessStatus) {
3532 case MPI3_DEVICE0_ASTATUS_NO_ERRORS:
3533 case MPI3_DEVICE0_ASTATUS_PREPARE:
3534 case MPI3_DEVICE0_ASTATUS_NEEDS_INITIALIZATION:
3535 case MPI3_DEVICE0_ASTATUS_DEVICE_MISSING_DELAY:
3536 break;
3537 default:
3538 tgtdev->is_hidden = 1;
3539 break;
3540 }
3541
3542 switch (flags & MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_MASK) {
3543 case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_256_LB:
3544 tgtdev->ws_len = 256;
3545 break;
3546 case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_2048_LB:
3547 tgtdev->ws_len = 2048;
3548 break;
3549 case MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_NO_LIMIT:
3550 default:
3551 tgtdev->ws_len = 0;
3552 break;
3553 }
3554
3555 switch (tgtdev->dev_type) {
3556 case MPI3_DEVICE_DEVFORM_SAS_SATA:
3557 {
3558 Mpi3Device0SasSataFormat_t *sasinf =
3559 &dev_pg0->DeviceSpecific.SasSataFormat;
3560 U16 dev_info = (sasinf->DeviceInfo);
3561 tgtdev->dev_spec.sassata_inf.dev_info = dev_info;
3562 tgtdev->dev_spec.sassata_inf.sas_address =
3563 (sasinf->SASAddress);
3564 if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) !=
3565 MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE)
3566 tgtdev->is_hidden = 1;
3567 else if (!(dev_info & (MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET |
3568 MPI3_SAS_DEVICE_INFO_SSP_TARGET)))
3569 tgtdev->is_hidden = 1;
3570 break;
3571 }
3572 case MPI3_DEVICE_DEVFORM_PCIE:
3573 {
3574 Mpi3Device0PcieFormat_t *pcieinf =
3575 &dev_pg0->DeviceSpecific.PcieFormat;
3576 U16 dev_info = (pcieinf->DeviceInfo);
3577
3578 tgtdev->q_depth = dev_pg0->QueueDepth;
3579 tgtdev->dev_spec.pcie_inf.dev_info = dev_info;
3580 tgtdev->dev_spec.pcie_inf.capb =
3581 (pcieinf->Capabilities);
3582 tgtdev->dev_spec.pcie_inf.mdts = MPI3MR_DEFAULT_MDTS;
3583 if (dev_pg0->AccessStatus == MPI3_DEVICE0_ASTATUS_NO_ERRORS) {
3584 tgtdev->dev_spec.pcie_inf.mdts =
3585 (pcieinf->MaximumDataTransferSize);
3586 tgtdev->dev_spec.pcie_inf.pgsz = pcieinf->PageSize;
3587 tgtdev->dev_spec.pcie_inf.reset_to =
3588 pcieinf->ControllerResetTO;
3589 tgtdev->dev_spec.pcie_inf.abort_to =
3590 pcieinf->NVMeAbortTO;
3591 }
3592 if (tgtdev->dev_spec.pcie_inf.mdts > (1024 * 1024))
3593 tgtdev->dev_spec.pcie_inf.mdts = (1024 * 1024);
3594
3595 if (((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) !=
3596 MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE) &&
3597 ((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) !=
3598 MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE))
3599 tgtdev->is_hidden = 1;
3600
3601 break;
3602 }
3603 case MPI3_DEVICE_DEVFORM_VD:
3604 {
3605 Mpi3Device0VdFormat_t *vdinf =
3606 &dev_pg0->DeviceSpecific.VdFormat;
3607 struct mpi3mr_throttle_group_info *tg = NULL;
3608
3609 tgtdev->dev_spec.vol_inf.state = vdinf->VdState;
3610 if (vdinf->VdState == MPI3_DEVICE0_VD_STATE_OFFLINE)
3611 tgtdev->is_hidden = 1;
3612 tgtdev->dev_spec.vol_inf.tg_id = vdinf->IOThrottleGroup;
3613 tgtdev->dev_spec.vol_inf.tg_high =
3614 vdinf->IOThrottleGroupHigh * 2048;
3615 tgtdev->dev_spec.vol_inf.tg_low =
3616 vdinf->IOThrottleGroupLow * 2048;
3617 if (vdinf->IOThrottleGroup < sc->num_io_throttle_group) {
3618 tg = sc->throttle_groups + vdinf->IOThrottleGroup;
3619 tg->id = vdinf->IOThrottleGroup;
3620 tg->high = tgtdev->dev_spec.vol_inf.tg_high;
3621 tg->low = tgtdev->dev_spec.vol_inf.tg_low;
3622 if (is_added == true)
3623 tg->fw_qd = tgtdev->q_depth;
3624 tg->modified_qd = tgtdev->q_depth;
3625 }
3626 tgtdev->dev_spec.vol_inf.tg = tg;
3627 tgtdev->throttle_group = tg;
3628 break;
3629 }
3630 default:
3631 goto out;
3632 }
3633
3634 out:
3635 return;
3636 }
3637
mpi3mr_create_device(struct mpi3mr_softc * sc,Mpi3DevicePage0_t * dev_pg0)3638 int mpi3mr_create_device(struct mpi3mr_softc *sc,
3639 Mpi3DevicePage0_t *dev_pg0)
3640 {
3641 int retval = 0;
3642 struct mpi3mr_target *target = NULL;
3643 U16 per_id = 0;
3644
3645 per_id = dev_pg0->PersistentID;
3646
3647 mtx_lock_spin(&sc->target_lock);
3648 TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) {
3649 if (target->per_id == per_id) {
3650 target->state = MPI3MR_DEV_CREATED;
3651 break;
3652 }
3653 }
3654 mtx_unlock_spin(&sc->target_lock);
3655
3656 if (target) {
3657 mpi3mr_update_device(sc, target, dev_pg0, true);
3658 } else {
3659 target = malloc(sizeof(*target), M_MPI3MR,
3660 M_NOWAIT | M_ZERO);
3661
3662 if (target == NULL) {
3663 retval = -1;
3664 goto out;
3665 }
3666
3667 target->exposed_to_os = 0;
3668 mpi3mr_update_device(sc, target, dev_pg0, true);
3669 mtx_lock_spin(&sc->target_lock);
3670 TAILQ_INSERT_TAIL(&sc->cam_sc->tgt_list, target, tgt_next);
3671 target->state = MPI3MR_DEV_CREATED;
3672 mtx_unlock_spin(&sc->target_lock);
3673 }
3674 out:
3675 return retval;
3676 }
3677
3678 /**
3679 * mpi3mr_dev_rmhs_complete_iou - Device removal IOUC completion
3680 * @sc: Adapter instance reference
3681 * @drv_cmd: Internal command tracker
3682 *
3683 * Issues a target reset TM to the firmware from the device
3684 * removal TM pend list or retry the removal handshake sequence
3685 * based on the IOU control request IOC status.
3686 *
3687 * Return: Nothing
3688 */
mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * drv_cmd)3689 static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc *sc,
3690 struct mpi3mr_drvr_cmd *drv_cmd)
3691 {
3692 U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
3693 struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL;
3694 struct mpi3mr_target *tgtdev = NULL;
3695
3696 mpi3mr_dprint(sc, MPI3MR_EVENT,
3697 "%s :dev_rmhs_iouctrl_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x)\n",
3698 __func__, drv_cmd->dev_handle, drv_cmd->ioc_status,
3699 drv_cmd->ioc_loginfo);
3700 if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) {
3701 if (drv_cmd->retry_count < MPI3MR_DEVRMHS_RETRYCOUNT) {
3702 drv_cmd->retry_count++;
3703 mpi3mr_dprint(sc, MPI3MR_EVENT,
3704 "%s :dev_rmhs_iouctrl_complete: handle(0x%04x)retrying handshake retry=%d\n",
3705 __func__, drv_cmd->dev_handle,
3706 drv_cmd->retry_count);
3707 mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle,
3708 drv_cmd, drv_cmd->iou_rc);
3709 return;
3710 }
3711 mpi3mr_dprint(sc, MPI3MR_ERROR,
3712 "%s :dev removal handshake failed after all retries: handle(0x%04x)\n",
3713 __func__, drv_cmd->dev_handle);
3714 } else {
3715 mtx_lock_spin(&sc->target_lock);
3716 TAILQ_FOREACH(tgtdev, &sc->cam_sc->tgt_list, tgt_next) {
3717 if (tgtdev->dev_handle == drv_cmd->dev_handle)
3718 tgtdev->state = MPI3MR_DEV_REMOVE_HS_COMPLETED;
3719 }
3720 mtx_unlock_spin(&sc->target_lock);
3721
3722 mpi3mr_dprint(sc, MPI3MR_INFO,
3723 "%s :dev removal handshake completed successfully: handle(0x%04x)\n",
3724 __func__, drv_cmd->dev_handle);
3725 mpi3mr_clear_bit(drv_cmd->dev_handle, sc->removepend_bitmap);
3726 }
3727
3728 if (!TAILQ_EMPTY(&sc->delayed_rmhs_list)) {
3729 delayed_dev_rmhs = TAILQ_FIRST(&sc->delayed_rmhs_list);
3730 drv_cmd->dev_handle = delayed_dev_rmhs->handle;
3731 drv_cmd->retry_count = 0;
3732 drv_cmd->iou_rc = delayed_dev_rmhs->iou_rc;
3733 mpi3mr_dprint(sc, MPI3MR_EVENT,
3734 "%s :dev_rmhs_iouctrl_complete: processing delayed TM: handle(0x%04x)\n",
3735 __func__, drv_cmd->dev_handle);
3736 mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle, drv_cmd,
3737 drv_cmd->iou_rc);
3738 TAILQ_REMOVE(&sc->delayed_rmhs_list, delayed_dev_rmhs, list);
3739 free(delayed_dev_rmhs, M_MPI3MR);
3740 return;
3741 }
3742 drv_cmd->state = MPI3MR_CMD_NOTUSED;
3743 drv_cmd->callback = NULL;
3744 drv_cmd->retry_count = 0;
3745 drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
3746 mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap);
3747 }
3748
3749 /**
3750 * mpi3mr_dev_rmhs_complete_tm - Device removal TM completion
3751 * @sc: Adapter instance reference
3752 * @drv_cmd: Internal command tracker
3753 *
3754 * Issues a target reset TM to the firmware from the device
3755 * removal TM pend list or issue IO Unit control request as
3756 * part of device removal or hidden acknowledgment handshake.
3757 *
3758 * Return: Nothing
3759 */
mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * drv_cmd)3760 static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc *sc,
3761 struct mpi3mr_drvr_cmd *drv_cmd)
3762 {
3763 Mpi3IoUnitControlRequest_t iou_ctrl;
3764 U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
3765 Mpi3SCSITaskMgmtReply_t *tm_reply = NULL;
3766 int retval;
3767
3768 if (drv_cmd->state & MPI3MR_CMD_REPLYVALID)
3769 tm_reply = (Mpi3SCSITaskMgmtReply_t *)drv_cmd->reply;
3770
3771 if (tm_reply)
3772 printf(IOCNAME
3773 "dev_rmhs_tr_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x), term_count(%d)\n",
3774 sc->name, drv_cmd->dev_handle, drv_cmd->ioc_status,
3775 drv_cmd->ioc_loginfo,
3776 le32toh(tm_reply->TerminationCount));
3777
3778 printf(IOCNAME "Issuing IOU CTL: handle(0x%04x) dev_rmhs idx(%d)\n",
3779 sc->name, drv_cmd->dev_handle, cmd_idx);
3780
3781 memset(&iou_ctrl, 0, sizeof(iou_ctrl));
3782
3783 drv_cmd->state = MPI3MR_CMD_PENDING;
3784 drv_cmd->is_waiting = 0;
3785 drv_cmd->callback = mpi3mr_dev_rmhs_complete_iou;
3786 iou_ctrl.Operation = drv_cmd->iou_rc;
3787 iou_ctrl.Param16[0] = htole16(drv_cmd->dev_handle);
3788 iou_ctrl.HostTag = htole16(drv_cmd->host_tag);
3789 iou_ctrl.Function = MPI3_FUNCTION_IO_UNIT_CONTROL;
3790
3791 retval = mpi3mr_submit_admin_cmd(sc, &iou_ctrl, sizeof(iou_ctrl));
3792 if (retval) {
3793 printf(IOCNAME "Issue DevRmHsTMIOUCTL: Admin post failed\n",
3794 sc->name);
3795 goto out_failed;
3796 }
3797
3798 return;
3799 out_failed:
3800 drv_cmd->state = MPI3MR_CMD_NOTUSED;
3801 drv_cmd->callback = NULL;
3802 drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
3803 drv_cmd->retry_count = 0;
3804 mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap);
3805 }
3806
3807 /**
3808 * mpi3mr_dev_rmhs_send_tm - Issue TM for device removal
3809 * @sc: Adapter instance reference
3810 * @handle: Device handle
3811 * @cmdparam: Internal command tracker
3812 * @iou_rc: IO Unit reason code
3813 *
3814 * Issues a target reset TM to the firmware or add it to a pend
3815 * list as part of device removal or hidden acknowledgment
3816 * handshake.
3817 *
3818 * Return: Nothing
3819 */
mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc * sc,U16 handle,struct mpi3mr_drvr_cmd * cmdparam,U8 iou_rc)3820 static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc *sc, U16 handle,
3821 struct mpi3mr_drvr_cmd *cmdparam, U8 iou_rc)
3822 {
3823 Mpi3SCSITaskMgmtRequest_t tm_req;
3824 int retval = 0;
3825 U16 cmd_idx = MPI3MR_NUM_DEVRMCMD;
3826 U8 retrycount = 5;
3827 struct mpi3mr_drvr_cmd *drv_cmd = cmdparam;
3828 struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL;
3829
3830 if (drv_cmd)
3831 goto issue_cmd;
3832 do {
3833 cmd_idx = mpi3mr_find_first_zero_bit(sc->devrem_bitmap,
3834 MPI3MR_NUM_DEVRMCMD);
3835 if (cmd_idx < MPI3MR_NUM_DEVRMCMD) {
3836 if (!mpi3mr_test_and_set_bit(cmd_idx, sc->devrem_bitmap))
3837 break;
3838 cmd_idx = MPI3MR_NUM_DEVRMCMD;
3839 }
3840 } while (retrycount--);
3841
3842 if (cmd_idx >= MPI3MR_NUM_DEVRMCMD) {
3843 delayed_dev_rmhs = malloc(sizeof(*delayed_dev_rmhs),M_MPI3MR,
3844 M_ZERO|M_NOWAIT);
3845
3846 if (!delayed_dev_rmhs)
3847 return;
3848 delayed_dev_rmhs->handle = handle;
3849 delayed_dev_rmhs->iou_rc = iou_rc;
3850 TAILQ_INSERT_TAIL(&(sc->delayed_rmhs_list), delayed_dev_rmhs, list);
3851 mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :DevRmHs: tr:handle(0x%04x) is postponed\n",
3852 __func__, handle);
3853
3854
3855 return;
3856 }
3857 drv_cmd = &sc->dev_rmhs_cmds[cmd_idx];
3858
3859 issue_cmd:
3860 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
3861 mpi3mr_dprint(sc, MPI3MR_EVENT,
3862 "%s :Issuing TR TM: for devhandle 0x%04x with dev_rmhs %d\n",
3863 __func__, handle, cmd_idx);
3864
3865 memset(&tm_req, 0, sizeof(tm_req));
3866 if (drv_cmd->state & MPI3MR_CMD_PENDING) {
3867 mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Issue TM: Command is in use\n", __func__);
3868 goto out;
3869 }
3870 drv_cmd->state = MPI3MR_CMD_PENDING;
3871 drv_cmd->is_waiting = 0;
3872 drv_cmd->callback = mpi3mr_dev_rmhs_complete_tm;
3873 drv_cmd->dev_handle = handle;
3874 drv_cmd->iou_rc = iou_rc;
3875 tm_req.DevHandle = htole16(handle);
3876 tm_req.TaskType = MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3877 tm_req.HostTag = htole16(drv_cmd->host_tag);
3878 tm_req.TaskHostTag = htole16(MPI3MR_HOSTTAG_INVALID);
3879 tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT;
3880
3881 mpi3mr_set_bit(handle, sc->removepend_bitmap);
3882 retval = mpi3mr_submit_admin_cmd(sc, &tm_req, sizeof(tm_req));
3883 if (retval) {
3884 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :Issue DevRmHsTM: Admin Post failed\n",
3885 __func__);
3886 goto out_failed;
3887 }
3888 out:
3889 return;
3890 out_failed:
3891 drv_cmd->state = MPI3MR_CMD_NOTUSED;
3892 drv_cmd->callback = NULL;
3893 drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
3894 drv_cmd->retry_count = 0;
3895 mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap);
3896 }
3897
3898 /**
3899 * mpi3mr_complete_evt_ack - Event ack request completion
3900 * @sc: Adapter instance reference
3901 * @drv_cmd: Internal command tracker
3902 *
3903 * This is the completion handler for non blocking event
3904 * acknowledgment sent to the firmware and this will issue any
3905 * pending event acknowledgment request.
3906 *
3907 * Return: Nothing
3908 */
mpi3mr_complete_evt_ack(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * drv_cmd)3909 static void mpi3mr_complete_evt_ack(struct mpi3mr_softc *sc,
3910 struct mpi3mr_drvr_cmd *drv_cmd)
3911 {
3912 U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN;
3913 struct delayed_evtack_node *delayed_evtack = NULL;
3914
3915 if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) {
3916 mpi3mr_dprint(sc, MPI3MR_EVENT,
3917 "%s: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", __func__,
3918 (drv_cmd->ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
3919 drv_cmd->ioc_loginfo);
3920 }
3921
3922 if (!TAILQ_EMPTY(&sc->delayed_evtack_cmds_list)) {
3923 delayed_evtack = TAILQ_FIRST(&sc->delayed_evtack_cmds_list);
3924 mpi3mr_dprint(sc, MPI3MR_EVENT,
3925 "%s: processing delayed event ack for event %d\n",
3926 __func__, delayed_evtack->event);
3927 mpi3mr_send_evt_ack(sc, delayed_evtack->event, drv_cmd,
3928 delayed_evtack->event_ctx);
3929 TAILQ_REMOVE(&sc->delayed_evtack_cmds_list, delayed_evtack, list);
3930 free(delayed_evtack, M_MPI3MR);
3931 return;
3932 }
3933 drv_cmd->state = MPI3MR_CMD_NOTUSED;
3934 drv_cmd->callback = NULL;
3935 mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap);
3936 }
3937
3938 /**
3939 * mpi3mr_send_evt_ack - Issue event acknwoledgment request
3940 * @sc: Adapter instance reference
3941 * @event: MPI3 event id
3942 * @cmdparam: Internal command tracker
3943 * @event_ctx: Event context
3944 *
3945 * Issues event acknowledgment request to the firmware if there
3946 * is a free command to send the event ack else it to a pend
3947 * list so that it will be processed on a completion of a prior
3948 * event acknowledgment .
3949 *
3950 * Return: Nothing
3951 */
mpi3mr_send_evt_ack(struct mpi3mr_softc * sc,U8 event,struct mpi3mr_drvr_cmd * cmdparam,U32 event_ctx)3952 static void mpi3mr_send_evt_ack(struct mpi3mr_softc *sc, U8 event,
3953 struct mpi3mr_drvr_cmd *cmdparam, U32 event_ctx)
3954 {
3955 Mpi3EventAckRequest_t evtack_req;
3956 int retval = 0;
3957 U8 retrycount = 5;
3958 U16 cmd_idx = MPI3MR_NUM_EVTACKCMD;
3959 struct mpi3mr_drvr_cmd *drv_cmd = cmdparam;
3960 struct delayed_evtack_node *delayed_evtack = NULL;
3961
3962 if (drv_cmd)
3963 goto issue_cmd;
3964 do {
3965 cmd_idx = mpi3mr_find_first_zero_bit(sc->evtack_cmds_bitmap,
3966 MPI3MR_NUM_EVTACKCMD);
3967 if (cmd_idx < MPI3MR_NUM_EVTACKCMD) {
3968 if (!mpi3mr_test_and_set_bit(cmd_idx,
3969 sc->evtack_cmds_bitmap))
3970 break;
3971 cmd_idx = MPI3MR_NUM_EVTACKCMD;
3972 }
3973 } while (retrycount--);
3974
3975 if (cmd_idx >= MPI3MR_NUM_EVTACKCMD) {
3976 delayed_evtack = malloc(sizeof(*delayed_evtack),M_MPI3MR,
3977 M_ZERO | M_NOWAIT);
3978 if (!delayed_evtack)
3979 return;
3980 delayed_evtack->event = event;
3981 delayed_evtack->event_ctx = event_ctx;
3982 TAILQ_INSERT_TAIL(&(sc->delayed_evtack_cmds_list), delayed_evtack, list);
3983 mpi3mr_dprint(sc, MPI3MR_EVENT, "%s : Event ack for event:%d is postponed\n",
3984 __func__, event);
3985 return;
3986 }
3987 drv_cmd = &sc->evtack_cmds[cmd_idx];
3988
3989 issue_cmd:
3990 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN;
3991
3992 memset(&evtack_req, 0, sizeof(evtack_req));
3993 if (drv_cmd->state & MPI3MR_CMD_PENDING) {
3994 mpi3mr_dprint(sc, MPI3MR_EVENT, "%s: Command is in use\n", __func__);
3995 goto out;
3996 }
3997 drv_cmd->state = MPI3MR_CMD_PENDING;
3998 drv_cmd->is_waiting = 0;
3999 drv_cmd->callback = mpi3mr_complete_evt_ack;
4000 evtack_req.HostTag = htole16(drv_cmd->host_tag);
4001 evtack_req.Function = MPI3_FUNCTION_EVENT_ACK;
4002 evtack_req.Event = event;
4003 evtack_req.EventContext = htole32(event_ctx);
4004 retval = mpi3mr_submit_admin_cmd(sc, &evtack_req,
4005 sizeof(evtack_req));
4006
4007 if (retval) {
4008 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Admin Post failed\n", __func__);
4009 goto out_failed;
4010 }
4011 out:
4012 return;
4013 out_failed:
4014 drv_cmd->state = MPI3MR_CMD_NOTUSED;
4015 drv_cmd->callback = NULL;
4016 mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap);
4017 }
4018
4019 /*
4020 * mpi3mr_pcietopochg_evt_th - PCIETopologyChange evt tophalf
4021 * @sc: Adapter instance reference
4022 * @event_reply: Event data
4023 *
4024 * Checks for the reason code and based on that either block I/O
4025 * to device, or unblock I/O to the device, or start the device
4026 * removal handshake with reason as remove with the firmware for
4027 * PCIe devices.
4028 *
4029 * Return: Nothing
4030 */
mpi3mr_pcietopochg_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)4031 static void mpi3mr_pcietopochg_evt_th(struct mpi3mr_softc *sc,
4032 Mpi3EventNotificationReply_t *event_reply)
4033 {
4034 Mpi3EventDataPcieTopologyChangeList_t *topo_evt =
4035 (Mpi3EventDataPcieTopologyChangeList_t *) event_reply->EventData;
4036 int i;
4037 U16 handle;
4038 U8 reason_code;
4039 struct mpi3mr_target *tgtdev = NULL;
4040
4041 for (i = 0; i < topo_evt->NumEntries; i++) {
4042 handle = le16toh(topo_evt->PortEntry[i].AttachedDevHandle);
4043 if (!handle)
4044 continue;
4045 reason_code = topo_evt->PortEntry[i].PortStatus;
4046 tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle);
4047 switch (reason_code) {
4048 case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING:
4049 if (tgtdev) {
4050 tgtdev->dev_removed = 1;
4051 tgtdev->dev_removedelay = 0;
4052 mpi3mr_atomic_set(&tgtdev->block_io, 0);
4053 }
4054 mpi3mr_dev_rmhs_send_tm(sc, handle, NULL,
4055 MPI3_CTRL_OP_REMOVE_DEVICE);
4056 break;
4057 case MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING:
4058 if (tgtdev) {
4059 tgtdev->dev_removedelay = 1;
4060 mpi3mr_atomic_inc(&tgtdev->block_io);
4061 }
4062 break;
4063 case MPI3_EVENT_PCIE_TOPO_PS_RESPONDING:
4064 if (tgtdev &&
4065 tgtdev->dev_removedelay) {
4066 tgtdev->dev_removedelay = 0;
4067 if (mpi3mr_atomic_read(&tgtdev->block_io) > 0)
4068 mpi3mr_atomic_dec(&tgtdev->block_io);
4069 }
4070 break;
4071 case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED:
4072 default:
4073 break;
4074 }
4075 }
4076 }
4077
4078 /**
4079 * mpi3mr_sastopochg_evt_th - SASTopologyChange evt tophalf
4080 * @sc: Adapter instance reference
4081 * @event_reply: Event data
4082 *
4083 * Checks for the reason code and based on that either block I/O
4084 * to device, or unblock I/O to the device, or start the device
4085 * removal handshake with reason as remove with the firmware for
4086 * SAS/SATA devices.
4087 *
4088 * Return: Nothing
4089 */
mpi3mr_sastopochg_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)4090 static void mpi3mr_sastopochg_evt_th(struct mpi3mr_softc *sc,
4091 Mpi3EventNotificationReply_t *event_reply)
4092 {
4093 Mpi3EventDataSasTopologyChangeList_t *topo_evt =
4094 (Mpi3EventDataSasTopologyChangeList_t *)event_reply->EventData;
4095 int i;
4096 U16 handle;
4097 U8 reason_code;
4098 struct mpi3mr_target *tgtdev = NULL;
4099
4100 for (i = 0; i < topo_evt->NumEntries; i++) {
4101 handle = le16toh(topo_evt->PhyEntry[i].AttachedDevHandle);
4102 if (!handle)
4103 continue;
4104 reason_code = topo_evt->PhyEntry[i].PhyStatus &
4105 MPI3_EVENT_SAS_TOPO_PHY_RC_MASK;
4106 tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle);
4107 switch (reason_code) {
4108 case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING:
4109 if (tgtdev) {
4110 tgtdev->dev_removed = 1;
4111 tgtdev->dev_removedelay = 0;
4112 mpi3mr_atomic_set(&tgtdev->block_io, 0);
4113 }
4114 mpi3mr_dev_rmhs_send_tm(sc, handle, NULL,
4115 MPI3_CTRL_OP_REMOVE_DEVICE);
4116 break;
4117 case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING:
4118 if (tgtdev) {
4119 tgtdev->dev_removedelay = 1;
4120 mpi3mr_atomic_inc(&tgtdev->block_io);
4121 }
4122 break;
4123 case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING:
4124 if (tgtdev &&
4125 tgtdev->dev_removedelay) {
4126 tgtdev->dev_removedelay = 0;
4127 if (mpi3mr_atomic_read(&tgtdev->block_io) > 0)
4128 mpi3mr_atomic_dec(&tgtdev->block_io);
4129 }
4130 case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED:
4131 default:
4132 break;
4133 }
4134 }
4135
4136 }
4137 /**
4138 * mpi3mr_devstatuschg_evt_th - DeviceStatusChange evt tophalf
4139 * @sc: Adapter instance reference
4140 * @event_reply: Event data
4141 *
4142 * Checks for the reason code and based on that either block I/O
4143 * to device, or unblock I/O to the device, or start the device
4144 * removal handshake with reason as remove/hide acknowledgment
4145 * with the firmware.
4146 *
4147 * Return: Nothing
4148 */
mpi3mr_devstatuschg_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)4149 static void mpi3mr_devstatuschg_evt_th(struct mpi3mr_softc *sc,
4150 Mpi3EventNotificationReply_t *event_reply)
4151 {
4152 U16 dev_handle = 0;
4153 U8 ublock = 0, block = 0, hide = 0, uhide = 0, delete = 0, remove = 0;
4154 struct mpi3mr_target *tgtdev = NULL;
4155 Mpi3EventDataDeviceStatusChange_t *evtdata =
4156 (Mpi3EventDataDeviceStatusChange_t *) event_reply->EventData;
4157
4158 dev_handle = le16toh(evtdata->DevHandle);
4159
4160 switch (evtdata->ReasonCode) {
4161 case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_STRT:
4162 case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_STRT:
4163 block = 1;
4164 break;
4165 case MPI3_EVENT_DEV_STAT_RC_HIDDEN:
4166 delete = 1;
4167 hide = 1;
4168 break;
4169 case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN:
4170 uhide = 1;
4171 break;
4172 case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING:
4173 delete = 1;
4174 remove = 1;
4175 break;
4176 case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_CMP:
4177 case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_CMP:
4178 ublock = 1;
4179 break;
4180 default:
4181 break;
4182 }
4183
4184 tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle);
4185
4186 if (!tgtdev) {
4187 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :target with dev_handle:0x%x not found\n",
4188 __func__, dev_handle);
4189 return;
4190 }
4191
4192 if (block)
4193 mpi3mr_atomic_inc(&tgtdev->block_io);
4194
4195 if (hide)
4196 tgtdev->is_hidden = hide;
4197
4198 if (uhide) {
4199 tgtdev->is_hidden = 0;
4200 tgtdev->dev_removed = 0;
4201 }
4202
4203 if (delete)
4204 tgtdev->dev_removed = 1;
4205
4206 if (ublock) {
4207 if (mpi3mr_atomic_read(&tgtdev->block_io) > 0)
4208 mpi3mr_atomic_dec(&tgtdev->block_io);
4209 }
4210
4211 if (remove) {
4212 mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL,
4213 MPI3_CTRL_OP_REMOVE_DEVICE);
4214 }
4215 if (hide)
4216 mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL,
4217 MPI3_CTRL_OP_HIDDEN_ACK);
4218 }
4219
4220 /**
4221 * mpi3mr_preparereset_evt_th - Prepareforreset evt tophalf
4222 * @sc: Adapter instance reference
4223 * @event_reply: Event data
4224 *
4225 * Blocks and unblocks host level I/O based on the reason code
4226 *
4227 * Return: Nothing
4228 */
mpi3mr_preparereset_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)4229 static void mpi3mr_preparereset_evt_th(struct mpi3mr_softc *sc,
4230 Mpi3EventNotificationReply_t *event_reply)
4231 {
4232 Mpi3EventDataPrepareForReset_t *evtdata =
4233 (Mpi3EventDataPrepareForReset_t *)event_reply->EventData;
4234
4235 if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_START) {
4236 mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=START\n",
4237 __func__);
4238 if (sc->prepare_for_reset)
4239 return;
4240 sc->prepare_for_reset = 1;
4241 sc->prepare_for_reset_timeout_counter = 0;
4242 } else if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_ABORT) {
4243 mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=ABORT\n",
4244 __func__);
4245 sc->prepare_for_reset = 0;
4246 sc->prepare_for_reset_timeout_counter = 0;
4247 }
4248 if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK)
4249 == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED)
4250 mpi3mr_send_evt_ack(sc, event_reply->Event, NULL,
4251 le32toh(event_reply->EventContext));
4252 }
4253
4254 /**
4255 * mpi3mr_energypackchg_evt_th - Energypackchange evt tophalf
4256 * @sc: Adapter instance reference
4257 * @event_reply: Event data
4258 *
4259 * Identifies the new shutdown timeout value and update.
4260 *
4261 * Return: Nothing
4262 */
mpi3mr_energypackchg_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)4263 static void mpi3mr_energypackchg_evt_th(struct mpi3mr_softc *sc,
4264 Mpi3EventNotificationReply_t *event_reply)
4265 {
4266 Mpi3EventDataEnergyPackChange_t *evtdata =
4267 (Mpi3EventDataEnergyPackChange_t *)event_reply->EventData;
4268 U16 shutdown_timeout = le16toh(evtdata->ShutdownTimeout);
4269
4270 if (shutdown_timeout <= 0) {
4271 mpi3mr_dprint(sc, MPI3MR_ERROR,
4272 "%s :Invalid Shutdown Timeout received = %d\n",
4273 __func__, shutdown_timeout);
4274 return;
4275 }
4276
4277 mpi3mr_dprint(sc, MPI3MR_EVENT,
4278 "%s :Previous Shutdown Timeout Value = %d New Shutdown Timeout Value = %d\n",
4279 __func__, sc->facts.shutdown_timeout, shutdown_timeout);
4280 sc->facts.shutdown_timeout = shutdown_timeout;
4281 }
4282
4283 /**
4284 * mpi3mr_cablemgmt_evt_th - Cable mgmt evt tophalf
4285 * @sc: Adapter instance reference
4286 * @event_reply: Event data
4287 *
4288 * Displays Cable manegemt event details.
4289 *
4290 * Return: Nothing
4291 */
mpi3mr_cablemgmt_evt_th(struct mpi3mr_softc * sc,Mpi3EventNotificationReply_t * event_reply)4292 static void mpi3mr_cablemgmt_evt_th(struct mpi3mr_softc *sc,
4293 Mpi3EventNotificationReply_t *event_reply)
4294 {
4295 Mpi3EventDataCableManagement_t *evtdata =
4296 (Mpi3EventDataCableManagement_t *)event_reply->EventData;
4297
4298 switch (evtdata->Status) {
4299 case MPI3_EVENT_CABLE_MGMT_STATUS_INSUFFICIENT_POWER:
4300 {
4301 mpi3mr_dprint(sc, MPI3MR_INFO, "An active cable with ReceptacleID %d cannot be powered.\n"
4302 "Devices connected to this cable are not detected.\n"
4303 "This cable requires %d mW of power.\n",
4304 evtdata->ReceptacleID,
4305 le32toh(evtdata->ActiveCablePowerRequirement));
4306 break;
4307 }
4308 case MPI3_EVENT_CABLE_MGMT_STATUS_DEGRADED:
4309 {
4310 mpi3mr_dprint(sc, MPI3MR_INFO, "A cable with ReceptacleID %d is not running at optimal speed\n",
4311 evtdata->ReceptacleID);
4312 break;
4313 }
4314 default:
4315 break;
4316 }
4317 }
4318
4319 /**
4320 * mpi3mr_process_events - Event's toph-half handler
4321 * @sc: Adapter instance reference
4322 * @event_reply: Event data
4323 *
4324 * Top half of event processing.
4325 *
4326 * Return: Nothing
4327 */
mpi3mr_process_events(struct mpi3mr_softc * sc,uintptr_t data,Mpi3EventNotificationReply_t * event_reply)4328 static void mpi3mr_process_events(struct mpi3mr_softc *sc,
4329 uintptr_t data, Mpi3EventNotificationReply_t *event_reply)
4330 {
4331 U16 evt_type;
4332 bool ack_req = 0, process_evt_bh = 0;
4333 struct mpi3mr_fw_event_work *fw_event;
4334 U16 sz;
4335
4336 if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN)
4337 goto out;
4338
4339 if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK)
4340 == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED)
4341 ack_req = 1;
4342
4343 evt_type = event_reply->Event;
4344
4345 switch (evt_type) {
4346 case MPI3_EVENT_DEVICE_ADDED:
4347 {
4348 Mpi3DevicePage0_t *dev_pg0 =
4349 (Mpi3DevicePage0_t *) event_reply->EventData;
4350 if (mpi3mr_create_device(sc, dev_pg0))
4351 mpi3mr_dprint(sc, MPI3MR_ERROR,
4352 "%s :Failed to add device in the device add event\n",
4353 __func__);
4354 else
4355 process_evt_bh = 1;
4356 break;
4357 }
4358
4359 case MPI3_EVENT_DEVICE_STATUS_CHANGE:
4360 {
4361 process_evt_bh = 1;
4362 mpi3mr_devstatuschg_evt_th(sc, event_reply);
4363 break;
4364 }
4365 case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
4366 {
4367 process_evt_bh = 1;
4368 mpi3mr_sastopochg_evt_th(sc, event_reply);
4369 break;
4370 }
4371 case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
4372 {
4373 process_evt_bh = 1;
4374 mpi3mr_pcietopochg_evt_th(sc, event_reply);
4375 break;
4376 }
4377 case MPI3_EVENT_PREPARE_FOR_RESET:
4378 {
4379 mpi3mr_preparereset_evt_th(sc, event_reply);
4380 ack_req = 0;
4381 break;
4382 }
4383 case MPI3_EVENT_DEVICE_INFO_CHANGED:
4384 {
4385 process_evt_bh = 1;
4386 break;
4387 }
4388 case MPI3_EVENT_LOG_DATA:
4389 {
4390 mpi3mr_app_save_logdata(sc, (char*)event_reply->EventData,
4391 le16toh(event_reply->EventDataLength) * 4);
4392 break;
4393 }
4394 case MPI3_EVENT_ENERGY_PACK_CHANGE:
4395 {
4396 mpi3mr_energypackchg_evt_th(sc, event_reply);
4397 break;
4398 }
4399 case MPI3_EVENT_CABLE_MGMT:
4400 {
4401 mpi3mr_cablemgmt_evt_th(sc, event_reply);
4402 break;
4403 }
4404
4405 case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE:
4406 case MPI3_EVENT_SAS_DISCOVERY:
4407 case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
4408 case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE:
4409 case MPI3_EVENT_PCIE_ENUMERATION:
4410 break;
4411 default:
4412 mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Event 0x%02x is not handled by driver\n",
4413 __func__, evt_type);
4414 break;
4415 }
4416
4417 if (process_evt_bh || ack_req) {
4418 fw_event = malloc(sizeof(struct mpi3mr_fw_event_work), M_MPI3MR,
4419 M_ZERO|M_NOWAIT);
4420
4421 if (!fw_event) {
4422 printf("%s: allocate failed for fw_event\n", __func__);
4423 return;
4424 }
4425
4426 sz = le16toh(event_reply->EventDataLength) * 4;
4427 fw_event->event_data = malloc(sz, M_MPI3MR, M_ZERO|M_NOWAIT);
4428
4429 if (!fw_event->event_data) {
4430 printf("%s: allocate failed for event_data\n", __func__);
4431 free(fw_event, M_MPI3MR);
4432 return;
4433 }
4434
4435 bcopy(event_reply->EventData, fw_event->event_data, sz);
4436 fw_event->event = event_reply->Event;
4437 if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
4438 event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ||
4439 event_reply->Event == MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE ) &&
4440 sc->track_mapping_events)
4441 sc->pending_map_events++;
4442
4443 /*
4444 * Events should be processed after Port enable is completed.
4445 */
4446 if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
4447 event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ) &&
4448 !(sc->mpi3mr_flags & MPI3MR_FLAGS_PORT_ENABLE_DONE))
4449 mpi3mr_startup_increment(sc->cam_sc);
4450
4451 fw_event->send_ack = ack_req;
4452 fw_event->event_context = le32toh(event_reply->EventContext);
4453 fw_event->event_data_size = sz;
4454 fw_event->process_event = process_evt_bh;
4455
4456 mtx_lock(&sc->fwevt_lock);
4457 TAILQ_INSERT_TAIL(&sc->cam_sc->ev_queue, fw_event, ev_link);
4458 taskqueue_enqueue(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task);
4459 mtx_unlock(&sc->fwevt_lock);
4460
4461 }
4462 out:
4463 return;
4464 }
4465
mpi3mr_handle_events(struct mpi3mr_softc * sc,uintptr_t data,Mpi3DefaultReply_t * def_reply)4466 static void mpi3mr_handle_events(struct mpi3mr_softc *sc, uintptr_t data,
4467 Mpi3DefaultReply_t *def_reply)
4468 {
4469 Mpi3EventNotificationReply_t *event_reply =
4470 (Mpi3EventNotificationReply_t *)def_reply;
4471
4472 sc->change_count = event_reply->IOCChangeCount;
4473 mpi3mr_display_event_data(sc, event_reply);
4474
4475 mpi3mr_process_events(sc, data, event_reply);
4476 }
4477
mpi3mr_process_admin_reply_desc(struct mpi3mr_softc * sc,Mpi3DefaultReplyDescriptor_t * reply_desc,U64 * reply_dma)4478 static void mpi3mr_process_admin_reply_desc(struct mpi3mr_softc *sc,
4479 Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma)
4480 {
4481 U16 reply_desc_type, host_tag = 0, idx;
4482 U16 ioc_status = MPI3_IOCSTATUS_SUCCESS;
4483 U32 ioc_loginfo = 0;
4484 Mpi3StatusReplyDescriptor_t *status_desc;
4485 Mpi3AddressReplyDescriptor_t *addr_desc;
4486 Mpi3SuccessReplyDescriptor_t *success_desc;
4487 Mpi3DefaultReply_t *def_reply = NULL;
4488 struct mpi3mr_drvr_cmd *cmdptr = NULL;
4489 Mpi3SCSIIOReply_t *scsi_reply;
4490 U8 *sense_buf = NULL;
4491
4492 *reply_dma = 0;
4493 reply_desc_type = reply_desc->ReplyFlags &
4494 MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK;
4495 switch (reply_desc_type) {
4496 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS:
4497 status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc;
4498 host_tag = status_desc->HostTag;
4499 ioc_status = status_desc->IOCStatus;
4500 if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
4501 ioc_loginfo = status_desc->IOCLogInfo;
4502 ioc_status &= MPI3_IOCSTATUS_STATUS_MASK;
4503 break;
4504 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
4505 addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc;
4506 *reply_dma = addr_desc->ReplyFrameAddress;
4507 def_reply = mpi3mr_get_reply_virt_addr(sc, *reply_dma);
4508 if (def_reply == NULL)
4509 goto out;
4510 host_tag = def_reply->HostTag;
4511 ioc_status = def_reply->IOCStatus;
4512 if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
4513 ioc_loginfo = def_reply->IOCLogInfo;
4514 ioc_status &= MPI3_IOCSTATUS_STATUS_MASK;
4515 if (def_reply->Function == MPI3_FUNCTION_SCSI_IO) {
4516 scsi_reply = (Mpi3SCSIIOReply_t *)def_reply;
4517 sense_buf = mpi3mr_get_sensebuf_virt_addr(sc,
4518 scsi_reply->SenseDataBufferAddress);
4519 }
4520 break;
4521 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
4522 success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc;
4523 host_tag = success_desc->HostTag;
4524 break;
4525 default:
4526 break;
4527 }
4528 switch (host_tag) {
4529 case MPI3MR_HOSTTAG_INITCMDS:
4530 cmdptr = &sc->init_cmds;
4531 break;
4532 case MPI3MR_HOSTTAG_CFGCMDS:
4533 cmdptr = &sc->cfg_cmds;
4534 break;
4535 case MPI3MR_HOSTTAG_IOCTLCMDS:
4536 cmdptr = &sc->ioctl_cmds;
4537 break;
4538 case MPI3MR_HOSTTAG_TMS:
4539 cmdptr = &sc->host_tm_cmds;
4540 wakeup((void *)&sc->tm_chan);
4541 break;
4542 case MPI3MR_HOSTTAG_PELABORT:
4543 cmdptr = &sc->pel_abort_cmd;
4544 break;
4545 case MPI3MR_HOSTTAG_PELWAIT:
4546 cmdptr = &sc->pel_cmds;
4547 break;
4548 case MPI3MR_HOSTTAG_INVALID:
4549 if (def_reply && def_reply->Function ==
4550 MPI3_FUNCTION_EVENT_NOTIFICATION)
4551 mpi3mr_handle_events(sc, *reply_dma ,def_reply);
4552 default:
4553 break;
4554 }
4555
4556 if (host_tag >= MPI3MR_HOSTTAG_DEVRMCMD_MIN &&
4557 host_tag <= MPI3MR_HOSTTAG_DEVRMCMD_MAX ) {
4558 idx = host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN;
4559 cmdptr = &sc->dev_rmhs_cmds[idx];
4560 }
4561
4562 if (host_tag >= MPI3MR_HOSTTAG_EVTACKCMD_MIN &&
4563 host_tag <= MPI3MR_HOSTTAG_EVTACKCMD_MAX) {
4564 idx = host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN;
4565 cmdptr = &sc->evtack_cmds[idx];
4566 }
4567
4568 if (cmdptr) {
4569 if (cmdptr->state & MPI3MR_CMD_PENDING) {
4570 cmdptr->state |= MPI3MR_CMD_COMPLETE;
4571 cmdptr->ioc_loginfo = ioc_loginfo;
4572 cmdptr->ioc_status = ioc_status;
4573 cmdptr->state &= ~MPI3MR_CMD_PENDING;
4574 if (def_reply) {
4575 cmdptr->state |= MPI3MR_CMD_REPLYVALID;
4576 memcpy((U8 *)cmdptr->reply, (U8 *)def_reply,
4577 sc->reply_sz);
4578 }
4579 if (sense_buf && cmdptr->sensebuf) {
4580 cmdptr->is_senseprst = 1;
4581 memcpy(cmdptr->sensebuf, sense_buf,
4582 MPI3MR_SENSEBUF_SZ);
4583 }
4584 if (cmdptr->is_waiting) {
4585 complete(&cmdptr->completion);
4586 cmdptr->is_waiting = 0;
4587 } else if (cmdptr->callback)
4588 cmdptr->callback(sc, cmdptr);
4589 }
4590 }
4591 out:
4592 if (sense_buf != NULL)
4593 mpi3mr_repost_sense_buf(sc,
4594 scsi_reply->SenseDataBufferAddress);
4595 return;
4596 }
4597
4598 /*
4599 * mpi3mr_complete_admin_cmd: ISR routine for admin commands
4600 * @sc: Adapter's soft instance
4601 *
4602 * This function processes admin command completions.
4603 */
mpi3mr_complete_admin_cmd(struct mpi3mr_softc * sc)4604 static int mpi3mr_complete_admin_cmd(struct mpi3mr_softc *sc)
4605 {
4606 U32 exp_phase = sc->admin_reply_ephase;
4607 U32 adm_reply_ci = sc->admin_reply_ci;
4608 U32 num_adm_reply = 0;
4609 U64 reply_dma = 0;
4610 Mpi3DefaultReplyDescriptor_t *reply_desc;
4611 U16 threshold_comps = 0;
4612
4613 mtx_lock_spin(&sc->admin_reply_lock);
4614 if (sc->admin_in_use == false) {
4615 sc->admin_in_use = true;
4616 mtx_unlock_spin(&sc->admin_reply_lock);
4617 } else {
4618 mtx_unlock_spin(&sc->admin_reply_lock);
4619 return 0;
4620 }
4621
4622 reply_desc = (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply +
4623 adm_reply_ci;
4624
4625 if ((reply_desc->ReplyFlags &
4626 MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) {
4627 mtx_lock_spin(&sc->admin_reply_lock);
4628 sc->admin_in_use = false;
4629 mtx_unlock_spin(&sc->admin_reply_lock);
4630 return 0;
4631 }
4632
4633 do {
4634 sc->admin_req_ci = reply_desc->RequestQueueCI;
4635 mpi3mr_process_admin_reply_desc(sc, reply_desc, &reply_dma);
4636 if (reply_dma)
4637 mpi3mr_repost_reply_buf(sc, reply_dma);
4638 num_adm_reply++;
4639 if (++adm_reply_ci == sc->num_admin_replies) {
4640 adm_reply_ci = 0;
4641 exp_phase ^= 1;
4642 }
4643 reply_desc =
4644 (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply +
4645 adm_reply_ci;
4646 if ((reply_desc->ReplyFlags &
4647 MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase)
4648 break;
4649
4650 if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) {
4651 mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci);
4652 threshold_comps = 0;
4653 }
4654 } while (1);
4655
4656 mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci);
4657 sc->admin_reply_ci = adm_reply_ci;
4658 sc->admin_reply_ephase = exp_phase;
4659 mtx_lock_spin(&sc->admin_reply_lock);
4660 sc->admin_in_use = false;
4661 mtx_unlock_spin(&sc->admin_reply_lock);
4662 return num_adm_reply;
4663 }
4664
4665 static void
mpi3mr_cmd_done(struct mpi3mr_softc * sc,struct mpi3mr_cmd * cmd)4666 mpi3mr_cmd_done(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd)
4667 {
4668 mpi3mr_unmap_request(sc, cmd);
4669
4670 mtx_lock(&sc->mpi3mr_mtx);
4671 if (cmd->callout_owner) {
4672 callout_stop(&cmd->callout);
4673 cmd->callout_owner = false;
4674 }
4675
4676 if (sc->unrecoverable)
4677 mpi3mr_set_ccbstatus(cmd->ccb, CAM_DEV_NOT_THERE);
4678
4679 xpt_done(cmd->ccb);
4680 cmd->ccb = NULL;
4681 mtx_unlock(&sc->mpi3mr_mtx);
4682 mpi3mr_release_command(cmd);
4683 }
4684
mpi3mr_process_op_reply_desc(struct mpi3mr_softc * sc,Mpi3DefaultReplyDescriptor_t * reply_desc,U64 * reply_dma)4685 void mpi3mr_process_op_reply_desc(struct mpi3mr_softc *sc,
4686 Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma)
4687 {
4688 U16 reply_desc_type, host_tag = 0;
4689 U16 ioc_status = MPI3_IOCSTATUS_SUCCESS;
4690 U32 ioc_loginfo = 0;
4691 Mpi3StatusReplyDescriptor_t *status_desc = NULL;
4692 Mpi3AddressReplyDescriptor_t *addr_desc = NULL;
4693 Mpi3SuccessReplyDescriptor_t *success_desc = NULL;
4694 Mpi3SCSIIOReply_t *scsi_reply = NULL;
4695 U8 *sense_buf = NULL;
4696 U8 scsi_state = 0, scsi_status = 0, sense_state = 0;
4697 U32 xfer_count = 0, sense_count =0, resp_data = 0;
4698 struct mpi3mr_cmd *cm = NULL;
4699 union ccb *ccb;
4700 struct ccb_scsiio *csio;
4701 struct mpi3mr_cam_softc *cam_sc;
4702 U32 target_id;
4703 U8 *scsi_cdb;
4704 struct mpi3mr_target *target = NULL;
4705 U32 ioc_pend_data_len = 0, tg_pend_data_len = 0, data_len_blks = 0;
4706 struct mpi3mr_throttle_group_info *tg = NULL;
4707 U8 throttle_enabled_dev = 0;
4708 static int ratelimit;
4709
4710 *reply_dma = 0;
4711 reply_desc_type = reply_desc->ReplyFlags &
4712 MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK;
4713 switch (reply_desc_type) {
4714 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS:
4715 status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc;
4716 host_tag = status_desc->HostTag;
4717 ioc_status = status_desc->IOCStatus;
4718 if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
4719 ioc_loginfo = status_desc->IOCLogInfo;
4720 ioc_status &= MPI3_IOCSTATUS_STATUS_MASK;
4721 break;
4722 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY:
4723 addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc;
4724 *reply_dma = addr_desc->ReplyFrameAddress;
4725 scsi_reply = mpi3mr_get_reply_virt_addr(sc,
4726 *reply_dma);
4727 if (scsi_reply == NULL) {
4728 mpi3mr_dprint(sc, MPI3MR_ERROR, "scsi_reply is NULL, "
4729 "this shouldn't happen, reply_desc: %p\n",
4730 reply_desc);
4731 goto out;
4732 }
4733
4734 host_tag = scsi_reply->HostTag;
4735 ioc_status = scsi_reply->IOCStatus;
4736 scsi_status = scsi_reply->SCSIStatus;
4737 scsi_state = scsi_reply->SCSIState;
4738 sense_state = (scsi_state & MPI3_SCSI_STATE_SENSE_MASK);
4739 xfer_count = scsi_reply->TransferCount;
4740 sense_count = scsi_reply->SenseCount;
4741 resp_data = scsi_reply->ResponseData;
4742 sense_buf = mpi3mr_get_sensebuf_virt_addr(sc,
4743 scsi_reply->SenseDataBufferAddress);
4744 if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK)
4745 ioc_loginfo = scsi_reply->IOCLogInfo;
4746 ioc_status &= MPI3_IOCSTATUS_STATUS_MASK;
4747 if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY)
4748 mpi3mr_dprint(sc, MPI3MR_ERROR, "Ran out of sense buffers\n");
4749
4750 break;
4751 case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS:
4752 success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc;
4753 host_tag = success_desc->HostTag;
4754
4755 default:
4756 break;
4757 }
4758
4759 cm = sc->cmd_list[host_tag];
4760
4761 if (cm->state == MPI3MR_CMD_STATE_FREE)
4762 goto out;
4763
4764 cam_sc = sc->cam_sc;
4765 ccb = cm->ccb;
4766 csio = &ccb->csio;
4767 target_id = csio->ccb_h.target_id;
4768
4769 scsi_cdb = scsiio_cdb_ptr(csio);
4770
4771 target = mpi3mr_find_target_by_per_id(cam_sc, target_id);
4772 if (sc->iot_enable) {
4773 data_len_blks = csio->dxfer_len >> 9;
4774
4775 if (target) {
4776 tg = target->throttle_group;
4777 throttle_enabled_dev =
4778 target->io_throttle_enabled;
4779 }
4780
4781 if ((data_len_blks >= sc->io_throttle_data_length) &&
4782 throttle_enabled_dev) {
4783 mpi3mr_atomic_sub(&sc->pend_large_data_sz, data_len_blks);
4784 ioc_pend_data_len = mpi3mr_atomic_read(
4785 &sc->pend_large_data_sz);
4786 if (tg) {
4787 mpi3mr_atomic_sub(&tg->pend_large_data_sz,
4788 data_len_blks);
4789 tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz);
4790 if (ratelimit % 1000) {
4791 mpi3mr_dprint(sc, MPI3MR_IOT,
4792 "large vd_io completion persist_id(%d), handle(0x%04x), data_len(%d),"
4793 "ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n",
4794 target->per_id,
4795 target->dev_handle,
4796 data_len_blks, ioc_pend_data_len,
4797 tg_pend_data_len,
4798 sc->io_throttle_low,
4799 tg->low);
4800 ratelimit++;
4801 }
4802 if (tg->io_divert && ((ioc_pend_data_len <=
4803 sc->io_throttle_low) &&
4804 (tg_pend_data_len <= tg->low))) {
4805 tg->io_divert = 0;
4806 mpi3mr_dprint(sc, MPI3MR_IOT,
4807 "VD: Coming out of divert perst_id(%d) tg_id(%d)\n",
4808 target->per_id, tg->id);
4809 mpi3mr_set_io_divert_for_all_vd_in_tg(
4810 sc, tg, 0);
4811 }
4812 } else {
4813 if (ratelimit % 1000) {
4814 mpi3mr_dprint(sc, MPI3MR_IOT,
4815 "large pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n",
4816 target->per_id,
4817 target->dev_handle,
4818 data_len_blks, ioc_pend_data_len,
4819 sc->io_throttle_low);
4820 ratelimit++;
4821 }
4822
4823 if (ioc_pend_data_len <= sc->io_throttle_low) {
4824 target->io_divert = 0;
4825 mpi3mr_dprint(sc, MPI3MR_IOT,
4826 "PD: Coming out of divert perst_id(%d)\n",
4827 target->per_id);
4828 }
4829 }
4830
4831 } else if (target->io_divert) {
4832 ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz);
4833 if (!tg) {
4834 if (ratelimit % 1000) {
4835 mpi3mr_dprint(sc, MPI3MR_IOT,
4836 "pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n",
4837 target->per_id,
4838 target->dev_handle,
4839 data_len_blks, ioc_pend_data_len,
4840 sc->io_throttle_low);
4841 ratelimit++;
4842 }
4843
4844 if ( ioc_pend_data_len <= sc->io_throttle_low) {
4845 mpi3mr_dprint(sc, MPI3MR_IOT,
4846 "PD: Coming out of divert perst_id(%d)\n",
4847 target->per_id);
4848 target->io_divert = 0;
4849 }
4850
4851 } else if (ioc_pend_data_len <= sc->io_throttle_low) {
4852 tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz);
4853 if (ratelimit % 1000) {
4854 mpi3mr_dprint(sc, MPI3MR_IOT,
4855 "vd_io completion persist_id(%d), handle(0x%04x), data_len(%d),"
4856 "ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n",
4857 target->per_id,
4858 target->dev_handle,
4859 data_len_blks, ioc_pend_data_len,
4860 tg_pend_data_len,
4861 sc->io_throttle_low,
4862 tg->low);
4863 ratelimit++;
4864 }
4865 if (tg->io_divert && (tg_pend_data_len <= tg->low)) {
4866 tg->io_divert = 0;
4867 mpi3mr_dprint(sc, MPI3MR_IOT,
4868 "VD: Coming out of divert perst_id(%d) tg_id(%d)\n",
4869 target->per_id, tg->id);
4870 mpi3mr_set_io_divert_for_all_vd_in_tg(
4871 sc, tg, 0);
4872 }
4873
4874 }
4875 }
4876 }
4877
4878 if (success_desc) {
4879 mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
4880 goto out_success;
4881 }
4882
4883 if (ioc_status == MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN
4884 && xfer_count == 0 && (scsi_status == MPI3_SCSI_STATUS_BUSY ||
4885 scsi_status == MPI3_SCSI_STATUS_RESERVATION_CONFLICT ||
4886 scsi_status == MPI3_SCSI_STATUS_TASK_SET_FULL))
4887 ioc_status = MPI3_IOCSTATUS_SUCCESS;
4888
4889 if ((sense_state == MPI3_SCSI_STATE_SENSE_VALID) && sense_count
4890 && sense_buf) {
4891 int sense_len, returned_sense_len;
4892
4893 returned_sense_len = min(le32toh(sense_count),
4894 sizeof(struct scsi_sense_data));
4895 if (returned_sense_len < csio->sense_len)
4896 csio->sense_resid = csio->sense_len -
4897 returned_sense_len;
4898 else
4899 csio->sense_resid = 0;
4900
4901 sense_len = min(returned_sense_len,
4902 csio->sense_len - csio->sense_resid);
4903 bzero(&csio->sense_data, sizeof(csio->sense_data));
4904 bcopy(sense_buf, &csio->sense_data, sense_len);
4905 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
4906 }
4907
4908 switch (ioc_status) {
4909 case MPI3_IOCSTATUS_BUSY:
4910 case MPI3_IOCSTATUS_INSUFFICIENT_RESOURCES:
4911 mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ);
4912 break;
4913 case MPI3_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4914 /*
4915 * If devinfo is 0 this will be a volume. In that case don't
4916 * tell CAM that the volume is not there. We want volumes to
4917 * be enumerated until they are deleted/removed, not just
4918 * failed.
4919 */
4920 if (cm->targ->devinfo == 0)
4921 mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
4922 else
4923 mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE);
4924 break;
4925 case MPI3_IOCSTATUS_SCSI_TASK_TERMINATED:
4926 case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED:
4927 case MPI3_IOCSTATUS_SCSI_EXT_TERMINATED:
4928 mpi3mr_set_ccbstatus(ccb, CAM_SCSI_BUSY);
4929 mpi3mr_dprint(sc, MPI3MR_TRACE,
4930 "func: %s line:%d tgt %u Hosttag %u loginfo %x\n",
4931 __func__, __LINE__,
4932 target_id, cm->hosttag,
4933 le32toh(scsi_reply->IOCLogInfo));
4934 mpi3mr_dprint(sc, MPI3MR_TRACE,
4935 "SCSIStatus %x SCSIState %x xfercount %u\n",
4936 scsi_reply->SCSIStatus, scsi_reply->SCSIState,
4937 le32toh(xfer_count));
4938 break;
4939 case MPI3_IOCSTATUS_SCSI_DATA_OVERRUN:
4940 /* resid is ignored for this condition */
4941 csio->resid = 0;
4942 mpi3mr_set_ccbstatus(ccb, CAM_DATA_RUN_ERR);
4943 break;
4944 case MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN:
4945 csio->resid = cm->length - le32toh(xfer_count);
4946 case MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR:
4947 case MPI3_IOCSTATUS_SUCCESS:
4948 if ((scsi_reply->IOCStatus & MPI3_IOCSTATUS_STATUS_MASK) ==
4949 MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR)
4950 mpi3mr_dprint(sc, MPI3MR_XINFO, "func: %s line: %d recovered error\n", __func__, __LINE__);
4951
4952 /* Completion failed at the transport level. */
4953 if (scsi_reply->SCSIState & (MPI3_SCSI_STATE_NO_SCSI_STATUS |
4954 MPI3_SCSI_STATE_TERMINATED)) {
4955 mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
4956 break;
4957 }
4958
4959 /* In a modern packetized environment, an autosense failure
4960 * implies that there's not much else that can be done to
4961 * recover the command.
4962 */
4963 if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) {
4964 mpi3mr_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL);
4965 break;
4966 }
4967
4968 /*
4969 * Intentionally override the normal SCSI status reporting
4970 * for these two cases. These are likely to happen in a
4971 * multi-initiator environment, and we want to make sure that
4972 * CAM retries these commands rather than fail them.
4973 */
4974 if ((scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_COMMAND_TERMINATED) ||
4975 (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_TASK_ABORTED)) {
4976 mpi3mr_set_ccbstatus(ccb, CAM_REQ_ABORTED);
4977 break;
4978 }
4979
4980 /* Handle normal status and sense */
4981 csio->scsi_status = scsi_reply->SCSIStatus;
4982 if (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_GOOD)
4983 mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP);
4984 else
4985 mpi3mr_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR);
4986
4987 if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) {
4988 int sense_len, returned_sense_len;
4989
4990 returned_sense_len = min(le32toh(scsi_reply->SenseCount),
4991 sizeof(struct scsi_sense_data));
4992 if (returned_sense_len < csio->sense_len)
4993 csio->sense_resid = csio->sense_len -
4994 returned_sense_len;
4995 else
4996 csio->sense_resid = 0;
4997
4998 sense_len = min(returned_sense_len,
4999 csio->sense_len - csio->sense_resid);
5000 bzero(&csio->sense_data, sizeof(csio->sense_data));
5001 bcopy(cm->sense, &csio->sense_data, sense_len);
5002 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
5003 }
5004
5005 break;
5006 case MPI3_IOCSTATUS_INVALID_SGL:
5007 mpi3mr_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR);
5008 break;
5009 case MPI3_IOCSTATUS_EEDP_GUARD_ERROR:
5010 case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR:
5011 case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR:
5012 case MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5013 case MPI3_IOCSTATUS_INVALID_FUNCTION:
5014 case MPI3_IOCSTATUS_INTERNAL_ERROR:
5015 case MPI3_IOCSTATUS_INVALID_FIELD:
5016 case MPI3_IOCSTATUS_INVALID_STATE:
5017 case MPI3_IOCSTATUS_SCSI_IO_DATA_ERROR:
5018 case MPI3_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
5019 case MPI3_IOCSTATUS_INSUFFICIENT_POWER:
5020 case MPI3_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
5021 default:
5022 csio->resid = cm->length;
5023 mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR);
5024 break;
5025 }
5026
5027 out_success:
5028 if (mpi3mr_get_ccbstatus(ccb) != CAM_REQ_CMP) {
5029 ccb->ccb_h.status |= CAM_DEV_QFRZN;
5030 xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1);
5031 }
5032
5033 mpi3mr_atomic_dec(&cm->targ->outstanding);
5034 mpi3mr_cmd_done(sc, cm);
5035 mpi3mr_dprint(sc, MPI3MR_TRACE, "Completion IO path :"
5036 " cdb[0]: %x targetid: 0x%x SMID: %x ioc_status: 0x%x ioc_loginfo: 0x%x scsi_status: 0x%x "
5037 "scsi_state: 0x%x response_data: 0x%x\n", scsi_cdb[0], target_id, host_tag,
5038 ioc_status, ioc_loginfo, scsi_status, scsi_state, resp_data);
5039 mpi3mr_atomic_dec(&sc->fw_outstanding);
5040 out:
5041
5042 if (sense_buf)
5043 mpi3mr_repost_sense_buf(sc,
5044 scsi_reply->SenseDataBufferAddress);
5045 return;
5046 }
5047
5048 /*
5049 * mpi3mr_complete_io_cmd: ISR routine for IO commands
5050 * @sc: Adapter's soft instance
5051 * @irq_ctx: Driver's internal per IRQ structure
5052 *
5053 * This function processes IO command completions.
5054 */
mpi3mr_complete_io_cmd(struct mpi3mr_softc * sc,struct mpi3mr_irq_context * irq_ctx)5055 int mpi3mr_complete_io_cmd(struct mpi3mr_softc *sc,
5056 struct mpi3mr_irq_context *irq_ctx)
5057 {
5058 struct mpi3mr_op_reply_queue *op_reply_q = irq_ctx->op_reply_q;
5059 U32 exp_phase = op_reply_q->ephase;
5060 U32 reply_ci = op_reply_q->ci;
5061 U32 num_op_replies = 0;
5062 U64 reply_dma = 0;
5063 Mpi3DefaultReplyDescriptor_t *reply_desc;
5064 U16 req_qid = 0, threshold_comps = 0;
5065
5066 mtx_lock_spin(&op_reply_q->q_lock);
5067 if (op_reply_q->in_use == false) {
5068 op_reply_q->in_use = true;
5069 mtx_unlock_spin(&op_reply_q->q_lock);
5070 } else {
5071 mtx_unlock_spin(&op_reply_q->q_lock);
5072 return 0;
5073 }
5074
5075 reply_desc = (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci;
5076 mpi3mr_dprint(sc, MPI3MR_TRACE, "[QID:%d]:reply_desc: (%pa) reply_ci: %x"
5077 " reply_desc->ReplyFlags: 0x%x\n"
5078 "reply_q_base_phys: %#016jx reply_q_base: (%pa) exp_phase: %x\n",
5079 op_reply_q->qid, reply_desc, reply_ci, reply_desc->ReplyFlags, op_reply_q->q_base_phys,
5080 op_reply_q->q_base, exp_phase);
5081
5082 if (((reply_desc->ReplyFlags &
5083 MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) || !op_reply_q->qid) {
5084 mtx_lock_spin(&op_reply_q->q_lock);
5085 op_reply_q->in_use = false;
5086 mtx_unlock_spin(&op_reply_q->q_lock);
5087 return 0;
5088 }
5089
5090 do {
5091 req_qid = reply_desc->RequestQueueID;
5092 sc->op_req_q[req_qid - 1].ci =
5093 reply_desc->RequestQueueCI;
5094
5095 mpi3mr_process_op_reply_desc(sc, reply_desc, &reply_dma);
5096 mpi3mr_atomic_dec(&op_reply_q->pend_ios);
5097 if (reply_dma)
5098 mpi3mr_repost_reply_buf(sc, reply_dma);
5099 num_op_replies++;
5100 if (++reply_ci == op_reply_q->num_replies) {
5101 reply_ci = 0;
5102 exp_phase ^= 1;
5103 }
5104 reply_desc =
5105 (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci;
5106 if ((reply_desc->ReplyFlags &
5107 MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase)
5108 break;
5109
5110 if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) {
5111 mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci);
5112 threshold_comps = 0;
5113 }
5114
5115 } while (1);
5116
5117
5118 mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci);
5119 op_reply_q->ci = reply_ci;
5120 op_reply_q->ephase = exp_phase;
5121 mtx_lock_spin(&op_reply_q->q_lock);
5122 op_reply_q->in_use = false;
5123 mtx_unlock_spin(&op_reply_q->q_lock);
5124 return num_op_replies;
5125 }
5126
5127 /*
5128 * mpi3mr_isr: Primary ISR function
5129 * privdata: Driver's internal per IRQ structure
5130 *
5131 * This is driver's primary ISR function which is being called whenever any admin/IO
5132 * command completion.
5133 */
mpi3mr_isr(void * privdata)5134 void mpi3mr_isr(void *privdata)
5135 {
5136 struct mpi3mr_irq_context *irq_ctx = (struct mpi3mr_irq_context *)privdata;
5137 struct mpi3mr_softc *sc = irq_ctx->sc;
5138 U16 msi_idx;
5139
5140 if (!irq_ctx)
5141 return;
5142
5143 msi_idx = irq_ctx->msix_index;
5144
5145 if (!sc->intr_enabled)
5146 return;
5147
5148 if (!msi_idx)
5149 mpi3mr_complete_admin_cmd(sc);
5150
5151 if (irq_ctx->op_reply_q && irq_ctx->op_reply_q->qid) {
5152 mpi3mr_complete_io_cmd(sc, irq_ctx);
5153 }
5154 }
5155
5156 /*
5157 * mpi3mr_alloc_requests - Allocates host commands
5158 * @sc: Adapter reference
5159 *
5160 * This function allocates controller supported host commands
5161 *
5162 * Return: 0 on success and proper error codes on failure
5163 */
5164 int
mpi3mr_alloc_requests(struct mpi3mr_softc * sc)5165 mpi3mr_alloc_requests(struct mpi3mr_softc *sc)
5166 {
5167 struct mpi3mr_cmd *cmd;
5168 int i, j, nsegs, ret;
5169
5170 nsegs = sc->max_sgl_entries;
5171 ret = bus_dma_tag_create( sc->mpi3mr_parent_dmat, /* parent */
5172 1, 0, /* algnmnt, boundary */
5173 sc->dma_loaddr, /* lowaddr */
5174 BUS_SPACE_MAXADDR, /* highaddr */
5175 NULL, NULL, /* filter, filterarg */
5176 BUS_SPACE_MAXSIZE, /* maxsize */
5177 nsegs, /* nsegments */
5178 BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
5179 BUS_DMA_ALLOCNOW, /* flags */
5180 busdma_lock_mutex, /* lockfunc */
5181 &sc->io_lock, /* lockarg */
5182 &sc->buffer_dmat);
5183 if (ret) {
5184 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate buffer DMA tag ret: %d\n", ret);
5185 return (ENOMEM);
5186 }
5187
5188 /*
5189 * sc->cmd_list is an array of struct mpi3mr_cmd pointers.
5190 * Allocate the dynamic array first and then allocate individual
5191 * commands.
5192 */
5193 sc->cmd_list = malloc(sizeof(struct mpi3mr_cmd *) * sc->max_host_ios,
5194 M_MPI3MR, M_NOWAIT | M_ZERO);
5195
5196 if (!sc->cmd_list) {
5197 device_printf(sc->mpi3mr_dev, "Cannot alloc memory for mpt_cmd_list.\n");
5198 return (ENOMEM);
5199 }
5200
5201 for (i = 0; i < sc->max_host_ios; i++) {
5202 sc->cmd_list[i] = malloc(sizeof(struct mpi3mr_cmd),
5203 M_MPI3MR, M_NOWAIT | M_ZERO);
5204 if (!sc->cmd_list[i]) {
5205 for (j = 0; j < i; j++)
5206 free(sc->cmd_list[j], M_MPI3MR);
5207 free(sc->cmd_list, M_MPI3MR);
5208 sc->cmd_list = NULL;
5209 return (ENOMEM);
5210 }
5211 }
5212
5213 for (i = 1; i < sc->max_host_ios; i++) {
5214 cmd = sc->cmd_list[i];
5215 cmd->hosttag = i;
5216 cmd->sc = sc;
5217 cmd->state = MPI3MR_CMD_STATE_BUSY;
5218 callout_init_mtx(&cmd->callout, &sc->mpi3mr_mtx, 0);
5219 cmd->ccb = NULL;
5220 TAILQ_INSERT_TAIL(&(sc->cmd_list_head), cmd, next);
5221 if (bus_dmamap_create(sc->buffer_dmat, 0, &cmd->dmamap))
5222 return ENOMEM;
5223 }
5224 return (0);
5225 }
5226
5227 /*
5228 * mpi3mr_get_command: Get a coomand structure from free command pool
5229 * @sc: Adapter soft instance
5230 * Return: MPT command reference
5231 *
5232 * This function returns an MPT command to the caller.
5233 */
5234 struct mpi3mr_cmd *
mpi3mr_get_command(struct mpi3mr_softc * sc)5235 mpi3mr_get_command(struct mpi3mr_softc *sc)
5236 {
5237 struct mpi3mr_cmd *cmd = NULL;
5238
5239 mtx_lock(&sc->cmd_pool_lock);
5240 if (!TAILQ_EMPTY(&sc->cmd_list_head)) {
5241 cmd = TAILQ_FIRST(&sc->cmd_list_head);
5242 TAILQ_REMOVE(&sc->cmd_list_head, cmd, next);
5243 } else {
5244 goto out;
5245 }
5246
5247 mpi3mr_dprint(sc, MPI3MR_TRACE, "Get command SMID: 0x%x\n", cmd->hosttag);
5248
5249 memset((uint8_t *)&cmd->io_request, 0, MPI3MR_AREQ_FRAME_SZ);
5250 cmd->data_dir = 0;
5251 cmd->ccb = NULL;
5252 cmd->targ = NULL;
5253 cmd->state = MPI3MR_CMD_STATE_BUSY;
5254 cmd->data = NULL;
5255 cmd->length = 0;
5256 out:
5257 mtx_unlock(&sc->cmd_pool_lock);
5258 return cmd;
5259 }
5260
5261 /*
5262 * mpi3mr_release_command: Return a cmd to free command pool
5263 * input: Command packet for return to free command pool
5264 *
5265 * This function returns an MPT command to the free command list.
5266 */
5267 void
mpi3mr_release_command(struct mpi3mr_cmd * cmd)5268 mpi3mr_release_command(struct mpi3mr_cmd *cmd)
5269 {
5270 struct mpi3mr_softc *sc = cmd->sc;
5271
5272 mtx_lock(&sc->cmd_pool_lock);
5273 TAILQ_INSERT_HEAD(&(sc->cmd_list_head), cmd, next);
5274 cmd->state = MPI3MR_CMD_STATE_FREE;
5275 cmd->req_qidx = 0;
5276 mpi3mr_dprint(sc, MPI3MR_TRACE, "Release command SMID: 0x%x\n", cmd->hosttag);
5277 mtx_unlock(&sc->cmd_pool_lock);
5278
5279 return;
5280 }
5281
5282 /**
5283 * mpi3mr_free_ioctl_dma_memory - free memory for ioctl dma
5284 * @sc: Adapter instance reference
5285 *
5286 * Free the DMA memory allocated for IOCTL handling purpose.
5287 *
5288 * Return: None
5289 */
mpi3mr_free_ioctl_dma_memory(struct mpi3mr_softc * sc)5290 static void mpi3mr_free_ioctl_dma_memory(struct mpi3mr_softc *sc)
5291 {
5292 U16 i;
5293 struct dma_memory_desc *mem_desc;
5294
5295 for (i=0; i<MPI3MR_NUM_IOCTL_SGE; i++) {
5296 mem_desc = &sc->ioctl_sge[i];
5297 if (mem_desc->addr && mem_desc->dma_addr) {
5298 bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap);
5299 bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap);
5300 mem_desc->addr = NULL;
5301 if (mem_desc->tag != NULL)
5302 bus_dma_tag_destroy(mem_desc->tag);
5303 }
5304 }
5305
5306 mem_desc = &sc->ioctl_chain_sge;
5307 if (mem_desc->addr && mem_desc->dma_addr) {
5308 bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap);
5309 bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap);
5310 mem_desc->addr = NULL;
5311 if (mem_desc->tag != NULL)
5312 bus_dma_tag_destroy(mem_desc->tag);
5313 }
5314
5315 mem_desc = &sc->ioctl_resp_sge;
5316 if (mem_desc->addr && mem_desc->dma_addr) {
5317 bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap);
5318 bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap);
5319 mem_desc->addr = NULL;
5320 if (mem_desc->tag != NULL)
5321 bus_dma_tag_destroy(mem_desc->tag);
5322 }
5323
5324 sc->ioctl_sges_allocated = false;
5325 }
5326
5327 /**
5328 * mpi3mr_alloc_ioctl_dma_memory - Alloc memory for ioctl dma
5329 * @sc: Adapter instance reference
5330 *
5331 * This function allocates dmaable memory required to handle the
5332 * application issued MPI3 IOCTL requests.
5333 *
5334 * Return: None
5335 */
mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_softc * sc)5336 void mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_softc *sc)
5337 {
5338 struct dma_memory_desc *mem_desc;
5339 U16 i;
5340
5341 for (i=0; i<MPI3MR_NUM_IOCTL_SGE; i++) {
5342 mem_desc = &sc->ioctl_sge[i];
5343 mem_desc->size = MPI3MR_IOCTL_SGE_SIZE;
5344
5345 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
5346 4, 0, /* algnmnt, boundary */
5347 sc->dma_loaddr, /* lowaddr */
5348 BUS_SPACE_MAXADDR, /* highaddr */
5349 NULL, NULL, /* filter, filterarg */
5350 mem_desc->size, /* maxsize */
5351 1, /* nsegments */
5352 mem_desc->size, /* maxsegsize */
5353 0, /* flags */
5354 NULL, NULL, /* lockfunc, lockarg */
5355 &mem_desc->tag)) {
5356 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
5357 goto out_failed;
5358 }
5359
5360 if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr,
5361 BUS_DMA_NOWAIT, &mem_desc->dmamap)) {
5362 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
5363 goto out_failed;
5364 }
5365 bzero(mem_desc->addr, mem_desc->size);
5366 bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size,
5367 mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT);
5368
5369 if (!mem_desc->addr)
5370 goto out_failed;
5371 }
5372
5373 mem_desc = &sc->ioctl_chain_sge;
5374 mem_desc->size = MPI3MR_4K_PGSZ;
5375 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
5376 4, 0, /* algnmnt, boundary */
5377 sc->dma_loaddr, /* lowaddr */
5378 BUS_SPACE_MAXADDR, /* highaddr */
5379 NULL, NULL, /* filter, filterarg */
5380 mem_desc->size, /* maxsize */
5381 1, /* nsegments */
5382 mem_desc->size, /* maxsegsize */
5383 0, /* flags */
5384 NULL, NULL, /* lockfunc, lockarg */
5385 &mem_desc->tag)) {
5386 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
5387 goto out_failed;
5388 }
5389
5390 if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr,
5391 BUS_DMA_NOWAIT, &mem_desc->dmamap)) {
5392 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__);
5393 goto out_failed;
5394 }
5395 bzero(mem_desc->addr, mem_desc->size);
5396 bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size,
5397 mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT);
5398
5399 if (!mem_desc->addr)
5400 goto out_failed;
5401
5402 mem_desc = &sc->ioctl_resp_sge;
5403 mem_desc->size = MPI3MR_4K_PGSZ;
5404 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
5405 4, 0, /* algnmnt, boundary */
5406 sc->dma_loaddr, /* lowaddr */
5407 BUS_SPACE_MAXADDR, /* highaddr */
5408 NULL, NULL, /* filter, filterarg */
5409 mem_desc->size, /* maxsize */
5410 1, /* nsegments */
5411 mem_desc->size, /* maxsegsize */
5412 0, /* flags */
5413 NULL, NULL, /* lockfunc, lockarg */
5414 &mem_desc->tag)) {
5415 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n");
5416 goto out_failed;
5417 }
5418
5419 if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr,
5420 BUS_DMA_NOWAIT, &mem_desc->dmamap)) {
5421 mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n");
5422 goto out_failed;
5423 }
5424 bzero(mem_desc->addr, mem_desc->size);
5425 bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size,
5426 mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT);
5427
5428 if (!mem_desc->addr)
5429 goto out_failed;
5430
5431 sc->ioctl_sges_allocated = true;
5432
5433 return;
5434 out_failed:
5435 printf("cannot allocate DMA memory for the mpt commands"
5436 " from the applications, application interface for MPT command is disabled\n");
5437 mpi3mr_free_ioctl_dma_memory(sc);
5438 }
5439
5440 static void inline
mpi3mr_free_dma_mem(struct mpi3mr_softc * sc,struct dma_memory_desc * mem_desc)5441 mpi3mr_free_dma_mem(struct mpi3mr_softc *sc,
5442 struct dma_memory_desc *mem_desc)
5443 {
5444 if (mem_desc->dma_addr)
5445 bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap);
5446
5447 if (mem_desc->addr != NULL) {
5448 bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap);
5449 mem_desc->addr = NULL;
5450 }
5451
5452 if (mem_desc->tag != NULL)
5453 bus_dma_tag_destroy(mem_desc->tag);
5454 }
5455
5456 static int
mpi3mr_alloc_dma_mem(struct mpi3mr_softc * sc,struct dma_memory_desc * mem_desc)5457 mpi3mr_alloc_dma_mem(struct mpi3mr_softc *sc,
5458 struct dma_memory_desc *mem_desc)
5459 {
5460 int retval;
5461
5462 if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
5463 4, 0, /* algnmnt, boundary */
5464 sc->dma_loaddr, /* lowaddr */
5465 sc->dma_hiaddr, /* highaddr */
5466 NULL, NULL, /* filter, filterarg */
5467 mem_desc->size, /* maxsize */
5468 1, /* nsegments */
5469 mem_desc->size, /* maxsize */
5470 0, /* flags */
5471 NULL, NULL, /* lockfunc, lockarg */
5472 &mem_desc->tag)) {
5473 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate DMA tag\n", __func__);
5474 return ENOMEM;
5475 }
5476
5477 if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr,
5478 BUS_DMA_NOWAIT, &mem_desc->dmamap)) {
5479 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate DMA memory\n", __func__);
5480 retval = ENOMEM;
5481 goto out;
5482 }
5483
5484 bzero(mem_desc->addr, mem_desc->size);
5485
5486 bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size,
5487 mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT);
5488
5489 if (!mem_desc->addr) {
5490 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot load DMA map\n", __func__);
5491 retval = ENOMEM;
5492 goto out;
5493 }
5494 return 0;
5495 out:
5496 mpi3mr_free_dma_mem(sc, mem_desc);
5497 return retval;
5498 }
5499
5500 static int
mpi3mr_post_cfg_req(struct mpi3mr_softc * sc,Mpi3ConfigRequest_t * cfg_req)5501 mpi3mr_post_cfg_req(struct mpi3mr_softc *sc, Mpi3ConfigRequest_t *cfg_req)
5502 {
5503 int retval;
5504
5505 mtx_lock(&sc->cfg_cmds.completion.lock);
5506 if (sc->cfg_cmds.state & MPI3MR_CMD_PENDING) {
5507 mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue cfg request: cfg command is in use\n");
5508 mtx_unlock(&sc->cfg_cmds.completion.lock);
5509 return -1;
5510 }
5511
5512 sc->cfg_cmds.state = MPI3MR_CMD_PENDING;
5513 sc->cfg_cmds.is_waiting = 1;
5514 sc->cfg_cmds.callback = NULL;
5515 sc->cfg_cmds.ioc_status = 0;
5516 sc->cfg_cmds.ioc_loginfo = 0;
5517
5518 cfg_req->HostTag = htole16(MPI3MR_HOSTTAG_CFGCMDS);
5519 cfg_req->Function = MPI3_FUNCTION_CONFIG;
5520 cfg_req->PageType = MPI3_CONFIG_PAGETYPE_DRIVER;
5521 cfg_req->PageNumber = 1;
5522 cfg_req->PageAddress = 0;
5523
5524 init_completion(&sc->cfg_cmds.completion);
5525
5526 retval = mpi3mr_submit_admin_cmd(sc, cfg_req, sizeof(*cfg_req));
5527 if (retval) {
5528 mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue cfg request: Admin Post failed\n");
5529 goto out;
5530 }
5531
5532 wait_for_completion_timeout(&sc->cfg_cmds.completion,
5533 (MPI3MR_INTADMCMD_TIMEOUT));
5534
5535 if (!(sc->cfg_cmds.state & MPI3MR_CMD_COMPLETE)) {
5536 if (!(sc->cfg_cmds.state & MPI3MR_CMD_RESET)) {
5537 mpi3mr_dprint(sc, MPI3MR_ERROR, "config request command timed out\n");
5538 mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT);
5539 }
5540 retval = -1;
5541 sc->cfg_cmds.is_waiting = 0;
5542 goto out;
5543 }
5544
5545 if ((sc->cfg_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) !=
5546 MPI3_IOCSTATUS_SUCCESS ) {
5547 mpi3mr_dprint(sc, MPI3MR_ERROR, "config request failed, IOCStatus(0x%04x) "
5548 " Loginfo(0x%08x) \n",(sc->cfg_cmds.ioc_status &
5549 MPI3_IOCSTATUS_STATUS_MASK), sc->cfg_cmds.ioc_loginfo);
5550 retval = -1;
5551 }
5552
5553 out:
5554 sc->cfg_cmds.state = MPI3MR_CMD_NOTUSED;
5555 mtx_unlock(&sc->cfg_cmds.completion.lock);
5556 return retval;
5557 }
5558
mpi3mr_process_cfg_req(struct mpi3mr_softc * sc,Mpi3ConfigRequest_t * cfg_req,Mpi3ConfigPageHeader_t * cfg_hdr,void * cfg_buf,U32 cfg_buf_sz)5559 static int mpi3mr_process_cfg_req(struct mpi3mr_softc *sc,
5560 Mpi3ConfigRequest_t *cfg_req,
5561 Mpi3ConfigPageHeader_t *cfg_hdr,
5562 void *cfg_buf, U32 cfg_buf_sz)
5563 {
5564 int retval;
5565 struct dma_memory_desc mem_desc = {0};
5566
5567 if (cfg_req->Action == MPI3_CONFIG_ACTION_PAGE_HEADER)
5568 mem_desc.size = sizeof(Mpi3ConfigPageHeader_t);
5569 else {
5570 mem_desc.size = le16toh(cfg_hdr->PageLength) * 4;
5571 cfg_req->PageLength = cfg_hdr->PageLength;
5572 cfg_req->PageVersion = cfg_hdr->PageVersion;
5573 }
5574
5575 retval = mpi3mr_alloc_dma_mem(sc, &mem_desc);
5576 if (retval) {
5577 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Failed to allocate DMA memory\n", __func__);
5578 return retval;
5579 }
5580
5581 mpi3mr_add_sg_single(&cfg_req->SGL, MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST,
5582 mem_desc.size, mem_desc.dma_addr);
5583
5584 retval = mpi3mr_post_cfg_req(sc, cfg_req);
5585 if (retval)
5586 mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Failed to post config request\n", __func__);
5587 else
5588 memcpy(cfg_buf, mem_desc.addr, min(mem_desc.size, cfg_buf_sz));
5589
5590 mpi3mr_free_dma_mem(sc, &mem_desc);
5591 return retval;
5592 }
5593
mpi3mr_cfg_get_driver_pg1(struct mpi3mr_softc * sc)5594 int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_softc *sc)
5595 {
5596 int retval;
5597 Mpi3DriverPage1_t driver_pg1 = {0};
5598 Mpi3ConfigPageHeader_t cfg_hdr = {0};
5599 Mpi3ConfigRequest_t cfg_req = {0};
5600
5601 cfg_req.Action = MPI3_CONFIG_ACTION_PAGE_HEADER;
5602 retval = mpi3mr_process_cfg_req(sc, &cfg_req, NULL, &cfg_hdr, sizeof(cfg_hdr));
5603 if (retval)
5604 goto error;
5605
5606 cfg_req.Action = MPI3_CONFIG_ACTION_READ_CURRENT;
5607 retval = mpi3mr_process_cfg_req(sc, &cfg_req, &cfg_hdr, &driver_pg1, sizeof(driver_pg1));
5608
5609 error:
5610 if (!retval && driver_pg1.TimeStampUpdate)
5611 sc->ts_update_interval = driver_pg1.TimeStampUpdate;
5612 else
5613 sc->ts_update_interval = MPI3MR_TSUPDATE_INTERVAL;
5614
5615 return retval;
5616 }
5617
5618 void
mpi3mr_destory_mtx(struct mpi3mr_softc * sc)5619 mpi3mr_destory_mtx(struct mpi3mr_softc *sc)
5620 {
5621 int i;
5622 struct mpi3mr_op_req_queue *op_req_q;
5623 struct mpi3mr_op_reply_queue *op_reply_q;
5624
5625 if (sc->admin_reply) {
5626 if (mtx_initialized(&sc->admin_reply_lock))
5627 mtx_destroy(&sc->admin_reply_lock);
5628 }
5629
5630 if (sc->op_reply_q) {
5631 for(i = 0; i < sc->num_queues; i++) {
5632 op_reply_q = sc->op_reply_q + i;
5633 if (mtx_initialized(&op_reply_q->q_lock))
5634 mtx_destroy(&op_reply_q->q_lock);
5635 }
5636 }
5637
5638 if (sc->op_req_q) {
5639 for(i = 0; i < sc->num_queues; i++) {
5640 op_req_q = sc->op_req_q + i;
5641 if (mtx_initialized(&op_req_q->q_lock))
5642 mtx_destroy(&op_req_q->q_lock);
5643 }
5644 }
5645
5646 if (mtx_initialized(&sc->init_cmds.completion.lock))
5647 mtx_destroy(&sc->init_cmds.completion.lock);
5648
5649 if (mtx_initialized(&sc->cfg_cmds.completion.lock))
5650 mtx_destroy(&sc->cfg_cmds.completion.lock);
5651
5652 if (mtx_initialized(&sc->ioctl_cmds.completion.lock))
5653 mtx_destroy(&sc->ioctl_cmds.completion.lock);
5654
5655 if (mtx_initialized(&sc->host_tm_cmds.completion.lock))
5656 mtx_destroy(&sc->host_tm_cmds.completion.lock);
5657
5658 for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
5659 if (mtx_initialized(&sc->dev_rmhs_cmds[i].completion.lock))
5660 mtx_destroy(&sc->dev_rmhs_cmds[i].completion.lock);
5661 }
5662
5663 if (mtx_initialized(&sc->reset_mutex))
5664 mtx_destroy(&sc->reset_mutex);
5665
5666 if (mtx_initialized(&sc->target_lock))
5667 mtx_destroy(&sc->target_lock);
5668
5669 if (mtx_initialized(&sc->fwevt_lock))
5670 mtx_destroy(&sc->fwevt_lock);
5671
5672 if (mtx_initialized(&sc->cmd_pool_lock))
5673 mtx_destroy(&sc->cmd_pool_lock);
5674
5675 if (mtx_initialized(&sc->reply_free_q_lock))
5676 mtx_destroy(&sc->reply_free_q_lock);
5677
5678 if (mtx_initialized(&sc->sense_buf_q_lock))
5679 mtx_destroy(&sc->sense_buf_q_lock);
5680
5681 if (mtx_initialized(&sc->chain_buf_lock))
5682 mtx_destroy(&sc->chain_buf_lock);
5683
5684 if (mtx_initialized(&sc->admin_req_lock))
5685 mtx_destroy(&sc->admin_req_lock);
5686
5687 if (mtx_initialized(&sc->mpi3mr_mtx))
5688 mtx_destroy(&sc->mpi3mr_mtx);
5689 }
5690
5691 /**
5692 * mpi3mr_free_mem - Freeup adapter level data structures
5693 * @sc: Adapter reference
5694 *
5695 * Return: Nothing.
5696 */
5697 void
mpi3mr_free_mem(struct mpi3mr_softc * sc)5698 mpi3mr_free_mem(struct mpi3mr_softc *sc)
5699 {
5700 int i;
5701 struct mpi3mr_op_req_queue *op_req_q;
5702 struct mpi3mr_op_reply_queue *op_reply_q;
5703 struct mpi3mr_irq_context *irq_ctx;
5704
5705 if (sc->cmd_list) {
5706 for (i = 0; i < sc->max_host_ios; i++) {
5707 free(sc->cmd_list[i], M_MPI3MR);
5708 }
5709 free(sc->cmd_list, M_MPI3MR);
5710 sc->cmd_list = NULL;
5711 }
5712
5713 if (sc->pel_seq_number && sc->pel_seq_number_dma) {
5714 bus_dmamap_unload(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap);
5715 bus_dmamem_free(sc->pel_seq_num_dmatag, sc->pel_seq_number, sc->pel_seq_num_dmamap);
5716 sc->pel_seq_number = NULL;
5717 if (sc->pel_seq_num_dmatag != NULL)
5718 bus_dma_tag_destroy(sc->pel_seq_num_dmatag);
5719 }
5720
5721 if (sc->throttle_groups) {
5722 free(sc->throttle_groups, M_MPI3MR);
5723 sc->throttle_groups = NULL;
5724 }
5725
5726 /* Free up operational queues*/
5727 if (sc->op_req_q) {
5728 for (i = 0; i < sc->num_queues; i++) {
5729 op_req_q = sc->op_req_q + i;
5730 if (op_req_q->q_base && op_req_q->q_base_phys) {
5731 bus_dmamap_unload(op_req_q->q_base_tag, op_req_q->q_base_dmamap);
5732 bus_dmamem_free(op_req_q->q_base_tag, op_req_q->q_base, op_req_q->q_base_dmamap);
5733 op_req_q->q_base = NULL;
5734 if (op_req_q->q_base_tag != NULL)
5735 bus_dma_tag_destroy(op_req_q->q_base_tag);
5736 }
5737 }
5738 free(sc->op_req_q, M_MPI3MR);
5739 sc->op_req_q = NULL;
5740 }
5741
5742 if (sc->op_reply_q) {
5743 for (i = 0; i < sc->num_queues; i++) {
5744 op_reply_q = sc->op_reply_q + i;
5745 if (op_reply_q->q_base && op_reply_q->q_base_phys) {
5746 bus_dmamap_unload(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap);
5747 bus_dmamem_free(op_reply_q->q_base_tag, op_reply_q->q_base, op_reply_q->q_base_dmamap);
5748 op_reply_q->q_base = NULL;
5749 if (op_reply_q->q_base_tag != NULL)
5750 bus_dma_tag_destroy(op_reply_q->q_base_tag);
5751 }
5752 }
5753 free(sc->op_reply_q, M_MPI3MR);
5754 sc->op_reply_q = NULL;
5755 }
5756
5757 /* Free up chain buffers*/
5758 if (sc->chain_sgl_list) {
5759 for (i = 0; i < sc->chain_buf_count; i++) {
5760 if (sc->chain_sgl_list[i].buf && sc->chain_sgl_list[i].buf_phys) {
5761 bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap);
5762 bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf,
5763 sc->chain_sgl_list[i].buf_dmamap);
5764 sc->chain_sgl_list[i].buf = NULL;
5765 }
5766 }
5767 if (sc->chain_sgl_list_tag != NULL)
5768 bus_dma_tag_destroy(sc->chain_sgl_list_tag);
5769 free(sc->chain_sgl_list, M_MPI3MR);
5770 sc->chain_sgl_list = NULL;
5771 }
5772
5773 if (sc->chain_bitmap) {
5774 free(sc->chain_bitmap, M_MPI3MR);
5775 sc->chain_bitmap = NULL;
5776 }
5777
5778 for (i = 0; i < sc->msix_count; i++) {
5779 irq_ctx = sc->irq_ctx + i;
5780 if (irq_ctx)
5781 irq_ctx->op_reply_q = NULL;
5782 }
5783
5784 /* Free reply_buf_tag */
5785 if (sc->reply_buf && sc->reply_buf_phys) {
5786 bus_dmamap_unload(sc->reply_buf_tag, sc->reply_buf_dmamap);
5787 bus_dmamem_free(sc->reply_buf_tag, sc->reply_buf,
5788 sc->reply_buf_dmamap);
5789 sc->reply_buf = NULL;
5790 if (sc->reply_buf_tag != NULL)
5791 bus_dma_tag_destroy(sc->reply_buf_tag);
5792 }
5793
5794 /* Free reply_free_q_tag */
5795 if (sc->reply_free_q && sc->reply_free_q_phys) {
5796 bus_dmamap_unload(sc->reply_free_q_tag, sc->reply_free_q_dmamap);
5797 bus_dmamem_free(sc->reply_free_q_tag, sc->reply_free_q,
5798 sc->reply_free_q_dmamap);
5799 sc->reply_free_q = NULL;
5800 if (sc->reply_free_q_tag != NULL)
5801 bus_dma_tag_destroy(sc->reply_free_q_tag);
5802 }
5803
5804 /* Free sense_buf_tag */
5805 if (sc->sense_buf && sc->sense_buf_phys) {
5806 bus_dmamap_unload(sc->sense_buf_tag, sc->sense_buf_dmamap);
5807 bus_dmamem_free(sc->sense_buf_tag, sc->sense_buf,
5808 sc->sense_buf_dmamap);
5809 sc->sense_buf = NULL;
5810 if (sc->sense_buf_tag != NULL)
5811 bus_dma_tag_destroy(sc->sense_buf_tag);
5812 }
5813
5814 /* Free sense_buf_q_tag */
5815 if (sc->sense_buf_q && sc->sense_buf_q_phys) {
5816 bus_dmamap_unload(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap);
5817 bus_dmamem_free(sc->sense_buf_q_tag, sc->sense_buf_q,
5818 sc->sense_buf_q_dmamap);
5819 sc->sense_buf_q = NULL;
5820 if (sc->sense_buf_q_tag != NULL)
5821 bus_dma_tag_destroy(sc->sense_buf_q_tag);
5822 }
5823
5824 /* Free up internal(non-IO) commands*/
5825 if (sc->init_cmds.reply) {
5826 free(sc->init_cmds.reply, M_MPI3MR);
5827 sc->init_cmds.reply = NULL;
5828 }
5829
5830 if (sc->cfg_cmds.reply) {
5831 free(sc->cfg_cmds.reply, M_MPI3MR);
5832 sc->cfg_cmds.reply = NULL;
5833 }
5834
5835 if (sc->ioctl_cmds.reply) {
5836 free(sc->ioctl_cmds.reply, M_MPI3MR);
5837 sc->ioctl_cmds.reply = NULL;
5838 }
5839
5840 if (sc->pel_cmds.reply) {
5841 free(sc->pel_cmds.reply, M_MPI3MR);
5842 sc->pel_cmds.reply = NULL;
5843 }
5844
5845 if (sc->pel_abort_cmd.reply) {
5846 free(sc->pel_abort_cmd.reply, M_MPI3MR);
5847 sc->pel_abort_cmd.reply = NULL;
5848 }
5849
5850 if (sc->host_tm_cmds.reply) {
5851 free(sc->host_tm_cmds.reply, M_MPI3MR);
5852 sc->host_tm_cmds.reply = NULL;
5853 }
5854
5855 if (sc->log_data_buffer) {
5856 free(sc->log_data_buffer, M_MPI3MR);
5857 sc->log_data_buffer = NULL;
5858 }
5859
5860 for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
5861 if (sc->dev_rmhs_cmds[i].reply) {
5862 free(sc->dev_rmhs_cmds[i].reply, M_MPI3MR);
5863 sc->dev_rmhs_cmds[i].reply = NULL;
5864 }
5865 }
5866
5867 for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) {
5868 if (sc->evtack_cmds[i].reply) {
5869 free(sc->evtack_cmds[i].reply, M_MPI3MR);
5870 sc->evtack_cmds[i].reply = NULL;
5871 }
5872 }
5873
5874 if (sc->removepend_bitmap) {
5875 free(sc->removepend_bitmap, M_MPI3MR);
5876 sc->removepend_bitmap = NULL;
5877 }
5878
5879 if (sc->devrem_bitmap) {
5880 free(sc->devrem_bitmap, M_MPI3MR);
5881 sc->devrem_bitmap = NULL;
5882 }
5883
5884 if (sc->evtack_cmds_bitmap) {
5885 free(sc->evtack_cmds_bitmap, M_MPI3MR);
5886 sc->evtack_cmds_bitmap = NULL;
5887 }
5888
5889 /* Free Admin reply*/
5890 if (sc->admin_reply && sc->admin_reply_phys) {
5891 bus_dmamap_unload(sc->admin_reply_tag, sc->admin_reply_dmamap);
5892 bus_dmamem_free(sc->admin_reply_tag, sc->admin_reply,
5893 sc->admin_reply_dmamap);
5894 sc->admin_reply = NULL;
5895 if (sc->admin_reply_tag != NULL)
5896 bus_dma_tag_destroy(sc->admin_reply_tag);
5897 }
5898
5899 /* Free Admin request*/
5900 if (sc->admin_req && sc->admin_req_phys) {
5901 bus_dmamap_unload(sc->admin_req_tag, sc->admin_req_dmamap);
5902 bus_dmamem_free(sc->admin_req_tag, sc->admin_req,
5903 sc->admin_req_dmamap);
5904 sc->admin_req = NULL;
5905 if (sc->admin_req_tag != NULL)
5906 bus_dma_tag_destroy(sc->admin_req_tag);
5907 }
5908 mpi3mr_free_ioctl_dma_memory(sc);
5909
5910 }
5911
5912 /**
5913 * mpi3mr_drv_cmd_comp_reset - Flush a internal driver command
5914 * @sc: Adapter instance reference
5915 * @cmdptr: Internal command tracker
5916 *
5917 * Complete an internal driver commands with state indicating it
5918 * is completed due to reset.
5919 *
5920 * Return: Nothing.
5921 */
mpi3mr_drv_cmd_comp_reset(struct mpi3mr_softc * sc,struct mpi3mr_drvr_cmd * cmdptr)5922 static inline void mpi3mr_drv_cmd_comp_reset(struct mpi3mr_softc *sc,
5923 struct mpi3mr_drvr_cmd *cmdptr)
5924 {
5925 if (cmdptr->state & MPI3MR_CMD_PENDING) {
5926 cmdptr->state |= MPI3MR_CMD_RESET;
5927 cmdptr->state &= ~MPI3MR_CMD_PENDING;
5928 if (cmdptr->is_waiting) {
5929 complete(&cmdptr->completion);
5930 cmdptr->is_waiting = 0;
5931 } else if (cmdptr->callback)
5932 cmdptr->callback(sc, cmdptr);
5933 }
5934 }
5935
5936 /**
5937 * mpi3mr_flush_drv_cmds - Flush internal driver commands
5938 * @sc: Adapter instance reference
5939 *
5940 * Flush all internal driver commands post reset
5941 *
5942 * Return: Nothing.
5943 */
mpi3mr_flush_drv_cmds(struct mpi3mr_softc * sc)5944 static void mpi3mr_flush_drv_cmds(struct mpi3mr_softc *sc)
5945 {
5946 int i = 0;
5947 struct mpi3mr_drvr_cmd *cmdptr;
5948
5949 cmdptr = &sc->init_cmds;
5950 mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
5951
5952 cmdptr = &sc->cfg_cmds;
5953 mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
5954
5955 cmdptr = &sc->ioctl_cmds;
5956 mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
5957
5958 cmdptr = &sc->host_tm_cmds;
5959 mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
5960
5961 for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) {
5962 cmdptr = &sc->dev_rmhs_cmds[i];
5963 mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
5964 }
5965
5966 for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) {
5967 cmdptr = &sc->evtack_cmds[i];
5968 mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
5969 }
5970
5971 cmdptr = &sc->pel_cmds;
5972 mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
5973
5974 cmdptr = &sc->pel_abort_cmd;
5975 mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
5976 }
5977
5978
5979 /**
5980 * mpi3mr_memset_buffers - memset memory for a controller
5981 * @sc: Adapter instance reference
5982 *
5983 * clear all the memory allocated for a controller, typically
5984 * called post reset to reuse the memory allocated during the
5985 * controller init.
5986 *
5987 * Return: Nothing.
5988 */
mpi3mr_memset_buffers(struct mpi3mr_softc * sc)5989 static void mpi3mr_memset_buffers(struct mpi3mr_softc *sc)
5990 {
5991 U16 i;
5992 struct mpi3mr_throttle_group_info *tg;
5993
5994 memset(sc->admin_req, 0, sc->admin_req_q_sz);
5995 memset(sc->admin_reply, 0, sc->admin_reply_q_sz);
5996
5997 memset(sc->init_cmds.reply, 0, sc->reply_sz);
5998 memset(sc->cfg_cmds.reply, 0, sc->reply_sz);
5999 memset(sc->ioctl_cmds.reply, 0, sc->reply_sz);
6000 memset(sc->host_tm_cmds.reply, 0, sc->reply_sz);
6001 memset(sc->pel_cmds.reply, 0, sc->reply_sz);
6002 memset(sc->pel_abort_cmd.reply, 0, sc->reply_sz);
6003 for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++)
6004 memset(sc->dev_rmhs_cmds[i].reply, 0, sc->reply_sz);
6005 for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++)
6006 memset(sc->evtack_cmds[i].reply, 0, sc->reply_sz);
6007 memset(sc->removepend_bitmap, 0, sc->dev_handle_bitmap_sz);
6008 memset(sc->devrem_bitmap, 0, sc->devrem_bitmap_sz);
6009 memset(sc->evtack_cmds_bitmap, 0, sc->evtack_cmds_bitmap_sz);
6010
6011 for (i = 0; i < sc->num_queues; i++) {
6012 sc->op_reply_q[i].qid = 0;
6013 sc->op_reply_q[i].ci = 0;
6014 sc->op_reply_q[i].num_replies = 0;
6015 sc->op_reply_q[i].ephase = 0;
6016 mpi3mr_atomic_set(&sc->op_reply_q[i].pend_ios, 0);
6017 memset(sc->op_reply_q[i].q_base, 0, sc->op_reply_q[i].qsz);
6018
6019 sc->op_req_q[i].ci = 0;
6020 sc->op_req_q[i].pi = 0;
6021 sc->op_req_q[i].num_reqs = 0;
6022 sc->op_req_q[i].qid = 0;
6023 sc->op_req_q[i].reply_qid = 0;
6024 memset(sc->op_req_q[i].q_base, 0, sc->op_req_q[i].qsz);
6025 }
6026
6027 mpi3mr_atomic_set(&sc->pend_large_data_sz, 0);
6028 if (sc->throttle_groups) {
6029 tg = sc->throttle_groups;
6030 for (i = 0; i < sc->num_io_throttle_group; i++, tg++) {
6031 tg->id = 0;
6032 tg->fw_qd = 0;
6033 tg->modified_qd = 0;
6034 tg->io_divert= 0;
6035 tg->high = 0;
6036 tg->low = 0;
6037 mpi3mr_atomic_set(&tg->pend_large_data_sz, 0);
6038 }
6039 }
6040 }
6041
6042 /**
6043 * mpi3mr_invalidate_devhandles -Invalidate device handles
6044 * @sc: Adapter instance reference
6045 *
6046 * Invalidate the device handles in the target device structures
6047 * . Called post reset prior to reinitializing the controller.
6048 *
6049 * Return: Nothing.
6050 */
mpi3mr_invalidate_devhandles(struct mpi3mr_softc * sc)6051 static void mpi3mr_invalidate_devhandles(struct mpi3mr_softc *sc)
6052 {
6053 struct mpi3mr_target *target = NULL;
6054
6055 mtx_lock_spin(&sc->target_lock);
6056 TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) {
6057 if (target) {
6058 target->dev_handle = MPI3MR_INVALID_DEV_HANDLE;
6059 target->io_throttle_enabled = 0;
6060 target->io_divert = 0;
6061 target->throttle_group = NULL;
6062 target->ws_len = 0;
6063 }
6064 }
6065 mtx_unlock_spin(&sc->target_lock);
6066 }
6067
6068 /**
6069 * mpi3mr_rfresh_tgtdevs - Refresh target device exposure
6070 * @sc: Adapter instance reference
6071 *
6072 * This is executed post controller reset to identify any
6073 * missing devices during reset and remove from the upper layers
6074 * or expose any newly detected device to the upper layers.
6075 *
6076 * Return: Nothing.
6077 */
6078
mpi3mr_rfresh_tgtdevs(struct mpi3mr_softc * sc)6079 static void mpi3mr_rfresh_tgtdevs(struct mpi3mr_softc *sc)
6080 {
6081 struct mpi3mr_target *target = NULL;
6082 struct mpi3mr_target *target_temp = NULL;
6083
6084 TAILQ_FOREACH_SAFE(target, &sc->cam_sc->tgt_list, tgt_next, target_temp) {
6085 if (target->dev_handle == MPI3MR_INVALID_DEV_HANDLE) {
6086 if (target->exposed_to_os)
6087 mpi3mr_remove_device_from_os(sc, target->dev_handle);
6088 mpi3mr_remove_device_from_list(sc, target, true);
6089 } else if (target->is_hidden && target->exposed_to_os) {
6090 mpi3mr_remove_device_from_os(sc, target->dev_handle);
6091 }
6092 }
6093
6094 TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) {
6095 if ((target->dev_handle != MPI3MR_INVALID_DEV_HANDLE) &&
6096 !target->is_hidden && !target->exposed_to_os) {
6097 mpi3mr_add_device(sc, target->per_id);
6098 }
6099 }
6100
6101 }
6102
mpi3mr_flush_io(struct mpi3mr_softc * sc)6103 static void mpi3mr_flush_io(struct mpi3mr_softc *sc)
6104 {
6105 int i;
6106 struct mpi3mr_cmd *cmd = NULL;
6107 union ccb *ccb = NULL;
6108
6109 for (i = 0; i < sc->max_host_ios; i++) {
6110 cmd = sc->cmd_list[i];
6111
6112 if (cmd && cmd->ccb) {
6113 if (cmd->callout_owner) {
6114 ccb = (union ccb *)(cmd->ccb);
6115 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
6116 mpi3mr_atomic_dec(&sc->fw_outstanding);
6117 mpi3mr_atomic_dec(&cmd->targ->outstanding);
6118 mpi3mr_cmd_done(sc, cmd);
6119 } else {
6120 cmd->ccb = NULL;
6121 mpi3mr_release_command(cmd);
6122 }
6123 }
6124 }
6125 }
6126
6127 /**
6128 * mpi3mr_set_diagsave - Set diag save bit for snapdump
6129 * @sc: Adapter reference
6130 *
6131 * Set diag save bit in IOC configuration register to enable
6132 * snapdump.
6133 *
6134 * Return: Nothing.
6135 */
mpi3mr_set_diagsave(struct mpi3mr_softc * sc)6136 static inline void mpi3mr_set_diagsave(struct mpi3mr_softc *sc)
6137 {
6138 U32 ioc_config;
6139
6140 ioc_config =
6141 mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
6142 ioc_config |= MPI3_SYSIF_IOC_CONFIG_DIAG_SAVE;
6143 mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
6144 }
6145
6146 /**
6147 * mpi3mr_issue_reset - Issue reset to the controller
6148 * @sc: Adapter reference
6149 * @reset_type: Reset type
6150 * @reset_reason: Reset reason code
6151 *
6152 * Unlock the host diagnostic registers and write the specific
6153 * reset type to that, wait for reset acknowledgement from the
6154 * controller, if the reset is not successful retry for the
6155 * predefined number of times.
6156 *
6157 * Return: 0 on success, non-zero on failure.
6158 */
mpi3mr_issue_reset(struct mpi3mr_softc * sc,U16 reset_type,U16 reset_reason)6159 static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type,
6160 U16 reset_reason)
6161 {
6162 int retval = -1;
6163 U8 unlock_retry_count = 0;
6164 U32 host_diagnostic, ioc_status, ioc_config, scratch_pad0;
6165 U32 timeout = MPI3MR_RESET_ACK_TIMEOUT * 10;
6166
6167 if ((reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) &&
6168 (reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT))
6169 return retval;
6170 if (sc->unrecoverable)
6171 return retval;
6172
6173 if (reset_reason == MPI3MR_RESET_FROM_FIRMWARE) {
6174 retval = 0;
6175 return retval;
6176 }
6177
6178 mpi3mr_dprint(sc, MPI3MR_INFO, "%s reset due to %s(0x%x)\n",
6179 mpi3mr_reset_type_name(reset_type),
6180 mpi3mr_reset_rc_name(reset_reason), reset_reason);
6181
6182 mpi3mr_clear_reset_history(sc);
6183 do {
6184 mpi3mr_dprint(sc, MPI3MR_INFO,
6185 "Write magic sequence to unlock host diag register (retry=%d)\n",
6186 ++unlock_retry_count);
6187 if (unlock_retry_count >= MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT) {
6188 mpi3mr_dprint(sc, MPI3MR_ERROR,
6189 "%s reset failed! due to host diag register unlock failure"
6190 "host_diagnostic(0x%08x)\n", mpi3mr_reset_type_name(reset_type),
6191 host_diagnostic);
6192 sc->unrecoverable = 1;
6193 return retval;
6194 }
6195
6196 mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
6197 MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH);
6198 mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
6199 MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST);
6200 mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
6201 MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND);
6202 mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
6203 MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD);
6204 mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
6205 MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH);
6206 mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
6207 MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH);
6208 mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
6209 MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH);
6210
6211 DELAY(1000); /* delay in usec */
6212 host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET);
6213 mpi3mr_dprint(sc, MPI3MR_INFO,
6214 "wrote magic sequence: retry_count(%d), host_diagnostic(0x%08x)\n",
6215 unlock_retry_count, host_diagnostic);
6216 } while (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE));
6217
6218 if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT)
6219 mpi3mr_set_diagsave(sc);
6220
6221 scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_FREEBSD <<
6222 MPI3MR_RESET_REASON_OSTYPE_SHIFT) |
6223 (sc->facts.ioc_num <<
6224 MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason);
6225 mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, scratch_pad0);
6226 mpi3mr_regwrite(sc, MPI3_SYSIF_HOST_DIAG_OFFSET, host_diagnostic | reset_type);
6227
6228 if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) {
6229 do {
6230 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
6231 if (ioc_status &
6232 MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) {
6233 ioc_config =
6234 mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
6235 if (mpi3mr_soft_reset_success(ioc_status,
6236 ioc_config)) {
6237 mpi3mr_clear_reset_history(sc);
6238 retval = 0;
6239 break;
6240 }
6241 }
6242 DELAY(100 * 1000);
6243 } while (--timeout);
6244 } else if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT) {
6245 do {
6246 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
6247 if (mpi3mr_diagfault_success(sc, ioc_status)) {
6248 retval = 0;
6249 break;
6250 }
6251 DELAY(100 * 1000);
6252 } while (--timeout);
6253 }
6254
6255 mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET,
6256 MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND);
6257
6258 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
6259 ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
6260
6261 mpi3mr_dprint(sc, MPI3MR_INFO,
6262 "IOC Status/Config after %s reset is (0x%x)/(0x%x)\n",
6263 !retval ? "successful":"failed", ioc_status,
6264 ioc_config);
6265
6266 if (retval)
6267 sc->unrecoverable = 1;
6268
6269 return retval;
6270 }
6271
mpi3mr_cleanup_event_taskq(struct mpi3mr_softc * sc)6272 inline void mpi3mr_cleanup_event_taskq(struct mpi3mr_softc *sc)
6273 {
6274 /*
6275 * Block the taskqueue before draining. This means any new tasks won't
6276 * be queued to the taskqueue worker thread. But it doesn't stop the
6277 * current workers that are running. taskqueue_drain waits for those
6278 * correctly in the case of thread backed taskqueues. The while loop
6279 * ensures that all taskqueue threads have finished their current tasks.
6280 */
6281 taskqueue_block(sc->cam_sc->ev_tq);
6282 while (taskqueue_cancel(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task, NULL) != 0) {
6283 taskqueue_drain(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task);
6284 }
6285 }
6286
6287 /**
6288 * mpi3mr_soft_reset_handler - Reset the controller
6289 * @sc: Adapter instance reference
6290 * @reset_reason: Reset reason code
6291 * @snapdump: snapdump enable/disbale bit
6292 *
6293 * This is an handler for recovering controller by issuing soft
6294 * reset or diag fault reset. This is a blocking function and
6295 * when one reset is executed if any other resets they will be
6296 * blocked. All IOCTLs/IO will be blocked during the reset. If
6297 * controller reset is successful then the controller will be
6298 * reinitalized, otherwise the controller will be marked as not
6299 * recoverable
6300 *
6301 * Return: 0 on success, non-zero on failure.
6302 */
mpi3mr_soft_reset_handler(struct mpi3mr_softc * sc,U16 reset_reason,bool snapdump)6303 int mpi3mr_soft_reset_handler(struct mpi3mr_softc *sc,
6304 U16 reset_reason, bool snapdump)
6305 {
6306 int retval = 0, i = 0;
6307 enum mpi3mr_iocstate ioc_state;
6308
6309 mpi3mr_dprint(sc, MPI3MR_INFO, "soft reset invoked: reason code: %s\n",
6310 mpi3mr_reset_rc_name(reset_reason));
6311
6312 if ((reset_reason == MPI3MR_RESET_FROM_IOCTL) &&
6313 (sc->reset.ioctl_reset_snapdump != true))
6314 snapdump = false;
6315
6316 mpi3mr_dprint(sc, MPI3MR_INFO,
6317 "soft_reset_handler: wait if diag save is in progress\n");
6318 while (sc->diagsave_timeout)
6319 DELAY(1000 * 1000);
6320
6321 ioc_state = mpi3mr_get_iocstate(sc);
6322 if (ioc_state == MRIOC_STATE_UNRECOVERABLE) {
6323 mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is in unrecoverable state, exit\n");
6324 sc->reset.type = MPI3MR_NO_RESET;
6325 sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON;
6326 sc->reset.status = -1;
6327 sc->reset.ioctl_reset_snapdump = false;
6328 return -1;
6329 }
6330
6331 if (sc->reset_in_progress) {
6332 mpi3mr_dprint(sc, MPI3MR_INFO, "reset is already in progress, exit\n");
6333 return -1;
6334 }
6335
6336 /* Pause IOs, drain and block the event taskqueue */
6337 xpt_freeze_simq(sc->cam_sc->sim, 1);
6338
6339 mpi3mr_cleanup_event_taskq(sc);
6340
6341 sc->reset_in_progress = 1;
6342 sc->block_ioctls = 1;
6343
6344 if (sc->timestamp_thread_active)
6345 wakeup(&sc->timestamp_chan);
6346
6347 while (mpi3mr_atomic_read(&sc->pend_ioctls) && (i < PEND_IOCTLS_COMP_WAIT_TIME)) {
6348 ioc_state = mpi3mr_get_iocstate(sc);
6349 if (ioc_state == MRIOC_STATE_FAULT)
6350 break;
6351 i++;
6352 if (!(i % 5)) {
6353 mpi3mr_dprint(sc, MPI3MR_INFO,
6354 "[%2ds]waiting for IOCTL to be finished from %s\n", i, __func__);
6355 }
6356 DELAY(1000 * 1000);
6357 }
6358
6359 if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) &&
6360 (reset_reason != MPI3MR_RESET_FROM_FIRMWARE) &&
6361 (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) {
6362
6363 mpi3mr_dprint(sc, MPI3MR_INFO, "Turn off events prior to reset\n");
6364
6365 for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
6366 sc->event_masks[i] = -1;
6367 mpi3mr_issue_event_notification(sc);
6368 }
6369
6370 mpi3mr_disable_interrupts(sc);
6371
6372 if (snapdump)
6373 mpi3mr_trigger_snapdump(sc, reset_reason);
6374
6375 retval = mpi3mr_issue_reset(sc,
6376 MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, reset_reason);
6377 if (retval) {
6378 mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to issue soft reset to the ioc\n");
6379 goto out;
6380 }
6381
6382 mpi3mr_flush_drv_cmds(sc);
6383 mpi3mr_flush_io(sc);
6384 mpi3mr_invalidate_devhandles(sc);
6385 mpi3mr_memset_buffers(sc);
6386
6387 if (sc->prepare_for_reset) {
6388 sc->prepare_for_reset = 0;
6389 sc->prepare_for_reset_timeout_counter = 0;
6390 }
6391
6392 retval = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_RESET);
6393 if (retval) {
6394 mpi3mr_dprint(sc, MPI3MR_ERROR, "reinit after soft reset failed: reason %d\n",
6395 reset_reason);
6396 goto out;
6397 }
6398
6399 DELAY((1000 * 1000) * 10);
6400 out:
6401 if (!retval) {
6402 sc->diagsave_timeout = 0;
6403 sc->reset_in_progress = 0;
6404 mpi3mr_rfresh_tgtdevs(sc);
6405 sc->ts_update_counter = 0;
6406 sc->block_ioctls = 0;
6407 sc->pel_abort_requested = 0;
6408 if (sc->pel_wait_pend) {
6409 sc->pel_cmds.retry_count = 0;
6410 mpi3mr_issue_pel_wait(sc, &sc->pel_cmds);
6411 mpi3mr_app_send_aen(sc);
6412 }
6413 } else {
6414 ioc_state = mpi3mr_get_iocstate(sc);
6415 if (ioc_state != MRIOC_STATE_FAULT)
6416 mpi3mr_issue_reset(sc,
6417 MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason);
6418
6419 sc->unrecoverable = 1;
6420 sc->reset_in_progress = 0;
6421 sc->block_ioctls = 0;
6422 }
6423
6424 mpi3mr_dprint(sc, MPI3MR_INFO, "Soft Reset: %s\n", ((retval == 0) ? "SUCCESS" : "FAILED"));
6425
6426 taskqueue_unblock(sc->cam_sc->ev_tq);
6427 xpt_release_simq(sc->cam_sc->sim, 1);
6428
6429 sc->reset.type = MPI3MR_NO_RESET;
6430 sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON;
6431 sc->reset.status = retval;
6432 sc->reset.ioctl_reset_snapdump = false;
6433
6434 return retval;
6435 }
6436
6437 /**
6438 * mpi3mr_issue_ioc_shutdown - shutdown controller
6439 * @sc: Adapter instance reference
6440 *
6441 * Send shutodwn notification to the controller and wait for the
6442 * shutdown_timeout for it to be completed.
6443 *
6444 * Return: Nothing.
6445 */
mpi3mr_issue_ioc_shutdown(struct mpi3mr_softc * sc)6446 static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_softc *sc)
6447 {
6448 U32 ioc_config, ioc_status;
6449 U8 retval = 1, retry = 0;
6450 U32 timeout = MPI3MR_DEFAULT_SHUTDOWN_TIME * 10;
6451
6452 mpi3mr_dprint(sc, MPI3MR_INFO, "sending shutdown notification\n");
6453 if (sc->unrecoverable) {
6454 mpi3mr_dprint(sc, MPI3MR_ERROR,
6455 "controller is unrecoverable, shutdown not issued\n");
6456 return;
6457 }
6458 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
6459 if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK)
6460 == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS) {
6461 mpi3mr_dprint(sc, MPI3MR_ERROR, "shutdown already in progress\n");
6462 return;
6463 }
6464
6465 ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
6466 ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL;
6467 ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ;
6468
6469 mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
6470
6471 if (sc->facts.shutdown_timeout)
6472 timeout = sc->facts.shutdown_timeout * 10;
6473
6474 do {
6475 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
6476 if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK)
6477 == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_COMPLETE) {
6478 retval = 0;
6479 break;
6480 }
6481
6482 if (sc->unrecoverable)
6483 break;
6484
6485 if ((ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) {
6486 mpi3mr_print_fault_info(sc);
6487
6488 if (retry >= MPI3MR_MAX_SHUTDOWN_RETRY_COUNT)
6489 break;
6490
6491 if (mpi3mr_issue_reset(sc,
6492 MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
6493 MPI3MR_RESET_FROM_CTLR_CLEANUP))
6494 break;
6495
6496 ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
6497 ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL;
6498 ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ;
6499
6500 mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config);
6501
6502 if (sc->facts.shutdown_timeout)
6503 timeout = sc->facts.shutdown_timeout * 10;
6504
6505 retry++;
6506 }
6507
6508 DELAY(100 * 1000);
6509
6510 } while (--timeout);
6511
6512 ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET);
6513 ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET);
6514
6515 if (retval) {
6516 if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK)
6517 == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS)
6518 mpi3mr_dprint(sc, MPI3MR_ERROR,
6519 "shutdown still in progress after timeout\n");
6520 }
6521
6522 mpi3mr_dprint(sc, MPI3MR_INFO,
6523 "ioc_status/ioc_config after %s shutdown is (0x%x)/(0x%x)\n",
6524 (!retval)?"successful":"failed", ioc_status,
6525 ioc_config);
6526 }
6527
6528 /**
6529 * mpi3mr_cleanup_ioc - Cleanup controller
6530 * @sc: Adapter instance reference
6531
6532 * controller cleanup handler, Message unit reset or soft reset
6533 * and shutdown notification is issued to the controller.
6534 *
6535 * Return: Nothing.
6536 */
mpi3mr_cleanup_ioc(struct mpi3mr_softc * sc)6537 void mpi3mr_cleanup_ioc(struct mpi3mr_softc *sc)
6538 {
6539 enum mpi3mr_iocstate ioc_state;
6540
6541 mpi3mr_dprint(sc, MPI3MR_INFO, "cleaning up the controller\n");
6542 mpi3mr_disable_interrupts(sc);
6543
6544 ioc_state = mpi3mr_get_iocstate(sc);
6545
6546 if ((!sc->unrecoverable) && (!sc->reset_in_progress) &&
6547 (ioc_state == MRIOC_STATE_READY)) {
6548 if (mpi3mr_mur_ioc(sc,
6549 MPI3MR_RESET_FROM_CTLR_CLEANUP))
6550 mpi3mr_issue_reset(sc,
6551 MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET,
6552 MPI3MR_RESET_FROM_MUR_FAILURE);
6553 mpi3mr_issue_ioc_shutdown(sc);
6554 }
6555
6556 mpi3mr_dprint(sc, MPI3MR_INFO, "controller cleanup completed\n");
6557 }
6558